Chapter 1
Introduction Object-Oriented
Programming
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 1
Motivations
After learning the previous procedural programming concepts, you are
capable of solving many programming problems using selections, loops,
and functions.
However, these Python features are not sufficient for developing
graphical user interfaces and large scale software systems.
Suppose you want to develop a graphical user interface as shown
below. How do you program it?
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 2
Objectives
• To describe objects and classes, and use classes to model objects (§9.2).
• To define classes with data fields and methods (§9.2.1).
• To construct an object using a constructor that invokes the initializer to create and initialize data fields
(§9.2.2).
• To access the members of objects using the dot operator (.) (§9.2.3).
• To reference an object itself with the self parameter (§9.2.4).
• To use UML graphical notation to describe classes and objects (§9.3).
• To use the datetime class from the Python library (<LINK>§9.4</LINK>).
• To distinguish between immutable and mutable objects (§9.5).
• To hide data fields to prevent data corruption and make classes easy to maintain (§9.6).
• To apply class abstraction and encapsulation to software development (§9.7).
• To explore the differences between the procedural paradigm and the object-oriented paradigm
(§9.8).
• To define special methods for operators (§9.9).
• To design the Rational class for representing rational numbers (§9.10).
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 3
OO Programming Concepts
Object-oriented programming (OOP) involves programming using objects.
An object represents an entity in the real world that can be distinctly
identified.
For example, a student, a desk, a circle, a button, and even a loan can all be
viewed as objects.
An object has a unique identity, state, and behaviors.
The state of an object consists of a set of data fields (also known as
properties) with their current values.
The behavior of an object is defined by a set of methods.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved.
4
• An object’s identity is like a person’s Social Security number. Python
automatically assigns each object a unique id for identifying the object at
runtime.
• An object’s state (also known as its properties or attributes) is
represented by variables, called data fields. A circle object, for example,
has a data field radius, which is a property that characterizes a circle. A
rectangle object has the data fields width and height, which are
properties that characterize a rectangle.
• Python uses methods to define an object’s behavior (also known as its
actions). Recall that methods are defined as functions. You make an
object perform an action by invoking a method on that object. For
example, you can define methods named getArea() and getPerimeter()
for circle objects. A circle object can then invoke the getArea() method to
return its area and the getPerimeter() method to return its perimeter.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 5
Objects
Class Name: Circle A class template
Data Fields:
radius is _______
Methods:
getArea
Circle Object 1 Circle Object 2 Circle Object 3 Three objects of
the Circle class
Data Fields: Data Fields: Data Fields:
radius is 10 radius is 25 radius is 125
An object has both a state and behavior. The state defines the
object, and the behavior defines what the object does.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 6
Classes
A Python class uses variables to store data fields and defines methods to
perform actions. Additionally, a class provides a special type method
__init__, known as initializer, which is invoked to create a new object.
An initializer can perform any action, but initializer is designed to
perform initializing actions, such as creating the data fields of objects.
class ClassName:
initializer
methods
Circle TestCircle
Circle TestCircle
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 7
Constructing Objects
Once a class is defined, you can create objects from the class
by using the following syntax, called a constructor:
ClassName(arguments)
1. It creates an object in the memory for object
the class. Data Fields:
2. It invokes the class’s __init__ method
to initialize the object. The self
parameter in the __init__ method is
__init__(self, …)
automatically set to reference the
object that was just created.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 8
Constructing Objects
The effect of constructing a Circle object using Circle(5) is
shown below:
1. Creates a Circle object. Circle object
2. Invokes __init__(self, radius) Circle object
radius: 5
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 9
Instance Methods
Methods are functions defined inside a class. They are invoked
by objects to perform actions on the objects.
For this reason, the methods are also called instance methods in
Python.
You probably noticed that all the methods including the __init__
have the first parameter self, which refers to the object that
invokes the method.
You can use any name for this parameter. But by convention,
self is used.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 10
Accessing Objects
After an object is created, you can access its data fields and invoke its
methods using the dot operator (.), also known as the object member access
operator.
For example, the following code accesses the radius data field and invokes
the getPerimeter and getArea methods.
>>> from Circle import Circle
>>> c = Circle(5)
>>> c.getPerimeter()
31.41592653589793
>>> c.radius = 10
>>> c.getArea()
314.1592653589793
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 11
Why self?
Note that the first parameter is special. It is used in the implementation of
the method, but not used when the method is called. So, what is this
parameter self for? Why does Python need it?
self is a parameter that represents an object. Using self, you can access
instance variables in an object.
Instance variables are for storing data fields.
Each object is an instance of a class.
Instance variables are tied to specific objects.
Each object has its own instance variables. You can use the syntax self.x
to access the instance variable x for the object self in a method.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 12
UML Class Diagram
UML Class Diagram Circle Class name
radius: float Data fields
Circle(radius = 1: float)
Constructors
getArea(): float methods
getPerimeter(): float
setRadius(radius: float): None
circle2: Circle circle3: Circle UML notation
circle1: Circle
for objects
radius = 1 radius = 25 radius = 125
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 13
Example: Defining Classes and Creating
Objects
TV
channel: int The current channel (1 to 120) of this TV.
volumeLevel: int The current volume level (1 to 7) of this TV.
on: bool Indicates whether this TV is on/off.
TV() Constructs a default TV object.
turnOn(): None Turns on this TV.
turnOff(): None Turns off this TV.
getChannel(): int Returns the channel for this TV.
setChannel(channel: int): None Sets a new channel for this TV. TV
getVolume(): int Gets the volume level for this TV. TV
setVolume(volumeLevel: int): None Sets a new volume level for this TV. TestTV
channelUp(): None Increases the channel number by 1.
TestTV
channelDown(): None Decreases the channel number by 1.
volumeUp(): None Increases the volume level by 1.
volumeDown(): None Decreases the volume level by 1.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 14
TV.py
class TV:
def __init__(self):
self.channel = 1 # Default channel is 1
self.volumeLevel = 1 # Default volume level is 1
self.on = False # By default TV is off
def turnOn(self):
self.on = True
def turnOff(self):
self.on = False
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 15
def getChannel(self):
return self.channel
def setChannel(self, channel):
if self.on and 1 <= self.channel <= 120:
self.channel = channel
def getVolumeLevel(self):
return self.volumeLevel
def setVolume(self, volumeLevel):
if self.on and 1 <= self.volumeLevel <= 7:
self.volumeLevel = volumeLevel
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 16
def channelUp(self):
if self.on and self.channel < 120:
self.channel += 1
def channelDown(self):
if self.on and self.channel > 1:
self.channel -= 1
def volumeUp(self):
if self.on and self.volumeLevel < 7:
self.volumeLevel += 1
def volumeDown(self):
if self.on and self.volumeLevel > 1:
self.volumeLevel -= 1
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 17
TestTV.py
from TV import TV
def main():
tv1 = TV()
tv1.turnOn()
tv1.setChannel(30)
tv1.setVolume(3)
tv2 = TV() #create a default TV
tv2.turnOn()
tv2.channelUp() #channel becomes 2
tv2.channelUp() #channel is now 3
tv2.volumeUp()
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 18
print("tv1's channel is", tv1.getChannel(),
"and volume level is", tv1.getVolumeLevel())
print("tv2's channel is", tv2.getChannel(),
"and volume level is", tv2.getVolumeLevel())
main() # Call the main function
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 19
Immutable Objects vs. Mutable Objects
• When passing a mutable object to a function, the function
may change the contents of the object.
• Recall that numbers and strings are immutable objects in
Python. Their contents cannot be changed.
• When passing an immutable object to a function, the object
will not be changed.
• However, if you pass a mutable object to a function, the
contents of the object may change.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 20
TestPassMutableObject
from Circle import Circle TestPassMutableObject
def main():
# Create a Circle object with radius 1
myCircle = Circle()
# Print areas for radius 1, 2, 3, 4, and 5
n=5
printAreas(myCircle, n)
# Display myCircle.radius and times
print("\nRadius is", myCircle.radius)
print("n is", n)
# Print a table of areas for radius
def printAreas(c, times):
print("Radius \t\tArea")
while times >= 1:
print(c.radius, "\t\t", c.getArea())
c.radius = c.radius + 1
times = times - 1
main() # Call the main function
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 21
animation
Trace Code Assign object reference
to myCircle
myCircle = Circle(5.0)
myCircle reference value
yourCircle = Circle()
yourCircle.radius = 100 : Circle
radius: 5.0
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 22
animation
Trace Code
myCircle = Circle(5.0)
myCircle reference value
yourCircle = Circle()
yourCircle.radius = 100 : Circle
radius: 5.0
Assign object reference
to yourCircle
yourCircle reference value
: Circle
radius: 1.0
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 23
animation
Trace Code
myCircle = Circle(5.0)
myCircle reference value
yourCircle = Circle()
yourCircle.radius = 100 : Circle
radius: 5.0
Modify radius in
yourCircle
yourCircle reference value
: Circle
radius: 100
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 24
The datetime Class
from datetime import datetime
d = datetime.now() #create a current object of datetime class
print("Current year is " + str(d.year))
print("Current month is " + str(d.month))
print("Current day of month is " + str(d.day))
print("Current hour is " + str(d.hour))
print("Current minute is " + str(d.minute))
print("Current second is " + str(d.second))
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 25
Data Field Encapsulation (hiding data Fields)
• To protect data.
• To make class easy to maintain.
• To prevent direct modifications of data fields, don’t let the
client directly access data fields. This is known as data field
encapsulation.
• This can be done by defining private data fields.
• In Python, the private data fields are defined with two
leading underscores.
• You can also define a private method named with two leading
underscores.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 26
CircleWithPrivateRadius
import math CircleWithPrivateRadius
class Circle:
# Construct a circle object
def __init__(self, radius = 1):
self.__radius = radius
def getRadius(self):
return self.__radius
def getPerimeter(self):
return 2 * self.__radius * math.pi
def getArea(self):
return self.__radius * self.__radius * math.pi
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 27
Data Field Encapsulation
CircleWithPrivateRadius
CircleWithPrivateRadius
>>> from CircleWithPrivateRadius import Circle
>>> c = Circle(5)
>>> c.__radius
AttributeError: 'Circle' object has no attribute
'__radius'
>>> c.getRadius()
5
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 28
Hiding data fields …
• Private data fields and methods can be accessed within a
class, but they cannot be accessed outside the class.
• To make a data field accessible for the client, provide a get
method to return its value. To enable a data field to be
modified, provide a set method to set a new value.
• Colloquially, a get method is referred to as a getter (or
accessor), and a set method is referred to as a setter (or
mutator).
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 29
Hiding ….
• A get method has the following header:
• def getPropertyName(self):
• If the return type is Boolean, the get method is defined as
follows by convention:
• def isPropertyName(self):
• A set method has the following header:
• def setPropertyName(self, propertyNameValue):
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 30
Design Guide
• If a class is designed for other programs to use, to prevent
data from being tampered with and to make the class easy to
maintain, define data fields as private.
• If a class is only used internally by your own program, there
is no need to encapsulate the data fields.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 31
Class Abstraction and Encapsulation
• Class abstraction means to separate class implementation from
the use of the class.
• The creator of the class provides a description of the class and
let the user know how the class can be used.
• The user of the class does not need to know how the class is
implemented. The detail of implementation is encapsulated
and hidden from the user.
Class implementation Class Contract
is like a black box (Signatures of Clients use the
hidden from the clients
Class public methods and class through the
public constants) contract of the class
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 32
Designing the Loan Class
The – sign denotes a private data field.
The get methods for these data fields are
provided in the class, but omitted in the
UML diagram for brevity.
Loan
-annualInterestRate: float The annual interest rate of the loan (default: 2.5).
-numberOfYears: int The number of years for the loan (default: 1)
-loanAmount: float The loan amount (default: 1000).
-borrower: str The borrower of this loan.
Loan(annualInterestRate: float, Constructs a Loan object with the specified annual
numberOfYear: int, loanAmount: interest rate, number of years, loan amount, and
float, borrower: str) borrower.
Loan TestLoanClass
Loan TestLoanClass
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 33
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 34
Loan.py
class Loan:
def __init__(self, annualInterestRate = 2.5,
numberOfYears = 1, loanAmount = 1000, borrower = " "):
self.__annualInterestRate = annualInterestRate
self.__numberOfYears = numberOfYears
self.__loanAmount = loanAmount
self.__borrower = borrower
def getAnnualInterestRate(self):
return self.__annualInterestRate
def getNumberOfYears(self):
return self.__numberOfYears
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 35
def getLoanAmount(self):
return self.__loanAmount
def getBorrower(self):
return self.__borrower
def setAnnualInterestRate(self, annualInterestRate):
self.__annualInterestRate = annualInterestRate
def setNumberOfYears(self, numberOfYears):
self.__numberOfYears = numberOfYears
def setLoanAmount(self, loanAmount):
self.__loanAmount = loanAmount
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 36
def setBorrower(self, borrower):
self.__borrower = borrower
def getMonthlyPayment(self):
monthlyInterestRate = self.__annualInterestRate / 1200
monthlyPayment = self.__loanAmount * monthlyInterestRate / (1 - (1 /
(1 + monthlyInterestRate) ** (self.__numberOfYears * 12)))
return monthlyPayment
def getTotalPayment(self):
totalPayment = self.getMonthlyPayment() * self.__numberOfYears * 12
return totalPayment
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 37
TestLoanClass.py
from Loan import Loan
from datetime import datetime
def main():
# Enter yearly interest rate
annualInterestRate = eval(input("Enter yearly interest rate, for example, 7.25: "))
# Enter number of years
numberOfYears = eval(input("Enter number of years as an integer: "))
# Enter loan amount
loanAmount = eval(input("Enter loan amount, for example, 120000.95: "))
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 38
# Enter a borrwer
borrower = input("Enter a borrower's name: ")
# Create a Loan object
loan = Loan(annualInterestRate, numberOfYears, loanAmount, borrower)
# Display loan date, monthly payment, and total payment
print("The loan date is", d.day, ",", d.month, ",", d.year)
print("The loan is for", loan.getBorrower())
print("The monthly payment is", format(loan.getMonthlyPayment(), '.2f'))
print("The total payment is", format(loan.getTotalPayment(), '.2f'))
main() # Call the main function
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 39
Object-Oriented Thinking
• The approach used is to teach problem solving and
fundamental programming techniques before object-oriented
programming.
• This section will show how procedural and object-oriented
programming differ. You will see the benefits of object-
oriented programming and learn to use it effectively.
• We will use several examples in the rest of the chapter to
illustrate the advantages of the object-oriented approach. The
examples involve designing new classes and using them in
applications.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 40
The BMI Class
The get methods for these data fields are
provided in the class, but omitted in the
UML diagram for brevity.
BMI
-name: str The name of the person.
-age: int The age of the person.
-weight: float The weight of the person in pounds.
-height: float The height of the person in inches.
BMI(name: str, age: int, weight: float, Creates a BMI object with the specified
height: float) name, weight, height, and a default age
20.
getBMI(): float Returns the BMI
getStatus(): str Returns the BMI status (e.g., normal,
overweight, etc.)
BMI UseBMIClass
BMI UseBMIClass
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 41
BMI.py
class BMI:
def __init__(self, name, age, weight, height):
self.__name = name
self.__age = age
self.__weight = weight
self.__height = height
def getBMI(self):
KILOGRAMS_PER_POUND = 0.45359237
METERS_PER_INCH = 0.0254
bmi = self.__weight * KILOGRAMS_PER_POUND / ((self.__height *
METERS_PER_INCH) * (self.__height * METERS_PER_INCH))
return round(bmi * 100) / 100
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 42
def getStatus(self):
bmi = self.getBMI()
if bmi < 18.5:
return "Underweight"
elif bmi < 25:
return "Normal"
elif bmi < 30:
return "Overweight"
else:
return "Obese"
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 43
def getName(self):
return self.__name
def getAge(self):
return self.__age
def getWeight(self):
return self.__weight
def getHeight(self):
return self.__height
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 44
UseBMIClass.py
from BMI import BMI
def main():
bmi1 = BMI("John Doe", 18, 145, 70)
print("The BMI for", bmi1.getName(), "is",
bmi1.getBMI(), bmi1.getStatus())
bmi2 = BMI("Peter King", 50, 215, 70)
print("The BMI for", bmi2.getName(), "is",
bmi2.getBMI(), bmi2.getStatus())
main() # Call the main function
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 45
The datetime Class
datetime
year: int The year, month, day, hour, minute, second,
and microsecond in this datatime object.
month: int
day: int
hour: int
minute: int
second: int
microsecond: int
datetime(year, month, day, hour = 0, Creates a datetime object using the specified
minute = 0, second = 0, microsecond = year, month, day, hour, minute, second, and
0) microsecond.
now(): datetime Returns a datetime object for the current
time.
fromtimestamp(timestamp): datetime Returns a datetime object from the specified
timestamp in seconds.
timestamp(): int Returns the timestamp in seconds in this
datetime object.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 46
Procedural vs. Object-Oriented
• In procedural programming, data and operations on the data
are separate, and this methodology requires sending data to
methods.
• Object-oriented programming places data and the operations
that pertain to them in an object. This approach solves many
of the problems inherent in procedural programming.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 47
Procedural vs. Object-Oriented
• The object-oriented programming approach organizes
programs in a way that mirrors the real world, in which all
objects are associated with both attributes and activities.
• Using objects improves software reusability and makes
programs easier to develop and easier to maintain.
• Programming in Python involves thinking in terms of objects; a
Python program can be viewed as a collection of cooperating
objects.
© Copyright 2018 by Pearson Education, Inc. All Rights Reserved. 48