Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
10 views57 pages

Chapter 9

Uploaded by

Asma Mohammed
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views57 pages

Chapter 9

Uploaded by

Asma Mohammed
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 57

Computer

Programming
Chapter 9
Prepared Mohammed Esmaail Shakfah 1
Spring 2024

06/10/2025
Contents
 Object-Oriented Programming
 Implementing a Simple Class
 Specifying the Public Interface of a Class
 Designing the Data Representation
 Constructors
 Implementing Methods
 Testing a Class
 Application: Writing a Fraction Class

06/10/2025
Object-Oriented Programming
 You have learned structured programming
 Breaking tasks into subtasks A class describes objects with the same behavior.
 Writing re-usable methods to handle tasks For example, a Car class describes all passenger
 We will now study Objects and Classes vehicles that have a certain capacity and shape.
 To build larger and more complex programs
 To model objects we use in the world

 You have learned how to structure your programs by decomposing tasks


into functions
 Experience shows that it does not go far enough
 It is difficult to understand and update a program that consists of a large
collection of functions
 To overcome this problem, computer scientists invented object-oriented
programming, a programming style in which tasks are solved by
collaborating objects
 Each object has its own set of data, together with a set of methods that act
upon the data
06/10/2025
Objects and Programs
 You have already experienced this programming style when you used strings, lists, and file
objects. Each of these objects has a set of methods
 For example, you can use the insert() or remove() methods to operate on list objects

Python Classes
 A class describes a set of objects with the same  In contrast, the list class describes the
behavior. behavior of objects that can be used to
 For example, the str class describes the behavior of store a collection of values
all strings  This class has a different set of methods
 This class specifies how a string stores its  For example, the following call would be
characters, which methods can be used with strings, illegal—the list class has no upper()
and how the methods are implemented. method
 For example, when you have a str object, you can
invoke the upper method: ["Hello",
"World"].upper()
"Hello, World".upper()
• However, list has a pop() method,
and the following call is legal

["Hello", "World"].pop()
String Method of class 06/10/2025
object String
Public Interfaces
 The set of all methods provided by a class, together with a description of
their behavior, is called the public interface of the class
 When you work with an object of a class, you do not know how the object
stores its data, or how the methods are implemented
 You need not know how a str object organizes a character sequence, or how a
list stores its elements
 All you need to know is the public interface––which methods you can apply,
and what these methods do

 The process of providing a public interface, while hiding the


implementation details, is called encapsulation
 If you work on a program that is being developed over a long period of
time, it is common for implementation details to change, usually to make
objects more efficient or more capable
 When the implementation is hidden, the improvements do not affect the
programmers who use the objects

06/10/2025
Public Interfaces

In an object-oriented program, objects are asked to carry out the tasks that are
Objects
necessary to achieve a goal.

Methods In order to get an object to carry out a task, you invoke a method on it.

Classes A class describes a set of objects with the same behavior.

Public Interface The public interface of a class tells you what you can do with objects of the class.

The public interface tells you the "what", not the "how". This gives the implementor
Encapsulation
of the class the freedom to change the implementation.

06/10/2025
Implementing a Simple Class
 Example:
 Tally Counter: A class that models a mechanical device that is used to count people
 For example, to find out how many people attend a concert or board a bus

 What should it do?


 Increment the tally
 Get the current total

 First, we construct an object of the class (object construction will be covered shortly):
 In Python, you don’t explicitly declare instance variables
 Instead, when one first assigns a value to an instance variable, the instance variable is created

tally = Counter() # Creates an instance


 Next, we invoke methods on our object
tally.reset()
tally.click()
tally.click()
result = tally.getValue() # Result is 2
tally.click()
result = tally.getValue() # Result is 3
06/10/2025
Instance Variables
 An object stores its data in instance variables
 An instance of a class is an object of the class
 In our example, each Counter object has a single instance variable named
_value

For example, if concertCounter and boardingCounter are two objects of the
Counter class, then each object has its own _value variable

 Instance variables are part of the


implementation details that should be hidden
from the user of the class
 With some programming languages an instance
variable can only be accessed by the methods of its
own class
 The Python language does not enforce this
restriction
 However, the underscore indicates to class users
that they should not directly access the instance
variables
06/10/2025
Class Methods
 The methods provided by the class are defined in the class body
 The click() method advances the _value instance variable by 1

def click(self) :
self._value = self._value + 1

• A method definition is very similar to a function with these exceptions:


• A method is defined as part of a class definition
• The first parameter variable of a method is called self

Class

Methods and Attributes
Note how the click() method increments the instance variable _value
 Which instance variable? The one belonging to the object on which the method is invoked
 In the example below the call to click() advances the _value variable of the concertCounter object
 No argument was provided when the click() method was called even though the definition includes the
self parameter variable

 The self parameter variable refers to the object on which the method was invoked concertCounter in
this example
concertCounter.click() 06/10/2025
Example of Encapsulation
 The getValue() method returns the current _value:

def getValue(self) :
return self._value

• This method is provided so that users of the Counter class can find out
how many times a particular counter has been clicked
• A class user should not directly access any instance variables
• Restricting access to instance variables is an essential part of
encapsulation

06/10/2025
Complete Simple Class Example

Program execution

06/10/2025
Example
1. Lines 11, 12, and 13 execute. The next line
executed after line 13 is line _____.
2. Next, line 3 executes. What is the value of
tally._value?
3. The next line executed after line 3 is line _____.
4. The next line executed is line _____.
5. Next, line 6 executes. What is the new value of
tally._value?
6. The next line executed after line 6 is line _____.
7. The next line executed is line _____.
8. Next, line 6 executes. What is the new value of
tally._value?
9. The next line executed after line 6 is line _____.
10. The next line executed is line _____.
11. Next, line 9 executes. The execution flow returns
to line 16 in the main function. What is the value of 06/10/2025 12
result?
Public Interface of a Class
 When you design a class, start by specifying the public interface of the new class
 What tasks will this class perform?
 What methods will you need?
 What parameters will the methods need to receive?

Example Public Interface


• Example: A Cash Register Class
Task Method
Add the price of an item addItem(price)

Get the total amount owed getTotal()

Get the count of items purchased getCount()


Clear the cash register for a new clear()
sale
 Since the ‘self’ parameter is required for all methods it was excluded for simplicity

06/10/2025
Writing the Public Interface
## A simulated cash register that tracks the item count and the total
amount due.
#
Class comments document
class CashRegister :
the class and the behavior
## Adds an item to this cash register.
of each method
# @param price: the price of this item
#
The method declarations make
def addItem(self, price) :
up the public interface of the
# Method body
class

## Gets the price of all items in the current sale.


# @return the total price
#
def getTotal(self): ...
The data and method bodies make up
the private implementation of the
class

06/10/2025
Using the Class
 After defining the class we can now construct an object:

register1 = CashRegister()
# Constructs a CashRegister object
• This statement defines the register1 variable and initializes it with a reference to a new
CashRegister object

 Now that an object has been constructed, we are ready to invoke a


method:
register1.addItem(1.95) # Invokes a method.

06/10/2025
Accessor and Mutator Methods
 Many methods fall into two categories:
1) Accessor Methods: 'get' methods
 Asks the object for information without changing it
 Normally returns the current value of an attribute

def getTotal(self):
def getCount(self):

2) Mutator Methods: 'set' methods


• Changes values in the object
• Usually take a parameter that will change an instance variable

def addItem(self, price):


def clear(self):

06/10/2025
Instance Variables of
Objects
 Each object of a class has a separate set of instance variables

The values stored in


instance variables make
up the state of the object.

06/10/2025
Designing the Data Representation
 An object stores data in instance variables
 Variables declared inside the class
 All methods inside the class have access to them
 Can change or access them
 What data will our CashRegister methods need?
Task Method Data Needed
Add the price of an item addItem(price) total, count

Get the total amount owed getTotal() total


Get the count of items getCount() count
purchased
Clear cash register for a new clear() total, count
An object holds instance variables that are accessed by methods
sale

06/10/2025
Example
Consider the following code segment.

class Date :
...
def getMonth(self) :
return self._month

def getDay(self) :
return self._day
...
1. Assuming that object birthday is an instance of the Date class, which is a correct
way to call the getMonth method?

06/10/2025 19
Example
1. Lines 1 through 5 execute. What is the value of
count?
2. Next, lines 6 and 7 execute. What is the value of
total?
3. Next, line 8 executes. What is the new value of
count
4. Next, lines 9 and 10 execute. What is the new
value of total?

06/10/2025 20
Example
Classify the following methods as either an accessor or a mutator.
1. The addItem method of the CashRegister class.
2. The getTotal method of the CashRegister class.
3. The clear method of the CashRegister class.
4. The click method of the Counter class.
5. The getValue method of the Counter class.
6. The pop method of the list class.
7. The upper method of the str class.

8. What is the name of the instance variable in the following code segment?

class Fruit :
def getColor(self) :
return self._color
06/10/2025 21
Programming Tip 9.1
 All instance variables should be private and most methods should be public
 Although most object-oriented languages provide a mechanism to explicitly hide
or protect private members from outside access, Python does not
 It is common practice among Python programmers to use names that begin
with a single underscore for private instance variables and methods
 The single underscore serves as a flag to the class user that those members are
private
 You should always use encapsulation, in which all instance variables are
private and are only manipulated with methods
 Typically, methods are public
 However, sometimes you have a method that is used only as a helper method by
other methods
 In that case, you should identify the helper method as private by using a name
that begins with a single underscore 06/10/2025
06/10/2025 23
Constructors  Only one constructor can be defined per class
 A constructor is a method that
 But you can a define constructor with default
initializes instance variables of an
argument values that simulate multiple
object
 It is automatically called when an object definitions
is created
class BankAccount :
# Calling a method that matches the
def __init__(self, initialBalance =
name of the class
0.0) :
# invokes the constructor
self._balance
• If no value = initialBalance
is passed to the constructor when a
register = CashRegister()
BankAccount object is created the default value will be
• Python uses the special name _ _init_ _ used
for the constructor because its purpose is joesAccount = BankAccount() # Balance is set
to initialize an instance of the class: to 0
If a value is passed to the constructor that value
will be used instead of the default one
def _ _init_ _(self) :
self._itemCount = 0
joesAccount = BankAccount(499.95) # Balance
self._totalPrice = 0
is set to 499.95
• Default arguments can be used in any method
and not just constructors
06/10/2025
Syntax: Constructors

06/10/2025
Constructors: Self
 The first parameter variable of every constructor must be self
 When the constructor is invoked to construct a new object, the self
parameter variable is set to the object that is being initialized
Refers to the
object being
initialized
def _ _init_ _(self) :
self._itemCount = 0
self._totalPrice = 0

register = CashRegister()
print("Your total $",
register.getTotal())

After the constructor ends this is a Call the


reference to the newly created object method
through the
 This reference then allows methods of the reference
object to be invoked
06/10/2025
Common Error 9.1 (2)
 The constructor can set a new CashRegister object to the cleared state,
but you should not call the constructor on an existing object. Instead,
replace the object with a new one:
register1 = CashRegister()
register1 = CashRegister() #
OK

In general, you should never call a Python method that starts with a
double underscore. The are intended for specific internal purposes
(in this case, to initialize a newly created object).

 After an object has been constructed, you should not directly call the
constructor on that object again:
register1 = CashRegister()
register1._ _init_ _() # Bad style

06/10/2025
Example
class Date :
def __init__(self) :
self._month = 1
self._day = 1
self._year = 2000
## Mutator method to change the value of instance variable day.
def setDay(self, newDay) :
## Accessor to retrieve the value of instance variable day.
def getDay(self) :
1. Assuming that methods setDay and getDay are implemented correctly, what is
the output from the following code segment?

birthday = Date()
yesterday = Date()
birthday.setDay(15)
print(birthday.getDay(), yesterday.getDay()) 06/10/2025 28
06/10/2025 29
Implementing Methods
 Implementing a method is very similar to implementing a function except that you access
the instance variables of the object in the method body
def addItem(self, price):
self._itemCount = self._itemCount + 1
self._totalPrice = self._totalPrice + price
Task Method
Add the price of an item addItem(price)

Get the total amount owed getTotal()

Get the count of items purchased getCount()

Clear the cash register for a new clear()


sale
register1 = CashRegister() #1 New object
register1.addItem(2.95) #2 Calling method
… #3 After method
def addItem(self, price):
self._itemCount =
self._itemCount + 1
self._totalPrice = 06/10/2025
self._totalPrice + price
Syntax: Instance Methods
 Use instance variables inside methods of the class
 Similar to the constructor, all other instance methods must
include the self parameter as the first parameter
 You must specify the self implicit parameter when using
instance variables inside the class

06/10/2025
Invoking Instance Methods
 As with the constructor, every method must include the special self
parameter variable, and it must be listed first.
 When a method is called, a reference to the object on which the method
was invoked (register1) is automatically passed to the self parameter
variable:
register1.addItem(2.95)

def addItem(self, price):

Accessing Instance Variables  Which _itemCount is incremented?


 To access an instance variable, such as _itemCount
 In this call, it is the _itemCount of the
or _totalPrice, in a method, you must access the register1 object.
variable name through the self reference
 This indicates that you want to access the instance
variables of the object on which the method is invoked,
and not those of some other CashRegister object
 The first statement in the addItem() method is
06/10/2025
self._itemCount = self._itemCount + 1
Calling One Method Within Another
 When one method needs to call another method on the same object, you
invoke the method on the self parameter

def addItems(self, quantity,


price) :
for i in range(quantity) :
self.addItem(price)

 register1.addItems(6, 0.95)

06/10/2025
Example: CashRegister.py (1)

06/10/2025
Programming Tip 9.2
 Instance variables should only be defined in the constructor
 All variables, including instance variables, are created at run time
 There is nothing to prevent you from creating instance variables in any method of a class

 The constructor is invoked before any method can be called, so any instance variables that were created in
the constructor are sure to be available in all methods

06/10/2025
06/10/2025 36
Testing a Class
 In the long run, your class may become a part of a larger program that interacts with
users, stores data in files, and so on
 You should always test your class in isolation integrating a class into a program
 Testing in isolation, outside a complete program, is called unit testing

 Some interactive development environments provide access to the Python


shell in which individual statements can be executed
 You can test a class simply by constructing an object, calling methods, and
verifying that you get the expected return values

>>> from cashregister import CashRegister


>>> reg = CashRegister()
>>> reg.addItem(1.95)
>>> reg.addItem(0.95)
>>> reg.addItem(2.50)
>>> print(reg.getCount())
3
>>> print(reg.getTotal())
5.4
06/10/2025
>>>
Choices for Testing: Test Drivers
 Interactive testing is quick and convenient but it has a drawback
 When you find and fix a mistake, you need to type in the tests again

 As your classes get more complex, you should write tester programs
 A tester program is a driver module that imports the class and contains statements to run methods
of your class

Steps Performed by a Tester Program

1. Construct one or more objects of the class that is being tested


2. Invoke one or more methods
3. Print out one or more results
4. Print the expected results
5. Compare the computed results with the expected

06/10/2025
Example Test Program Program execution

 It runs and tests the methods of the


CashRegister class

• You need to import the class you are testing


(here, the CashRegister class) into the
driver module:
from cashregister import CashRegister

 The specific details for running the


program depend on your development
 Thinking about the sample program:
environment
 We add three items totaling $5.40
 When displaying the method results, we also display messages that describe the values we expect
to see
 This is a very important step. You want to spend some time thinking about what the
expected result is before you run a test program
 This thought process will help you understand how your program should behave, and it
can help you track down errors at an early stage 06/10/2025
Writing a Fraction Class
 So far we have worked with floating-point numbers but computers store binary values, so not all
real numbers can be represented precisely
 In applications where the precision of real numbers is important, we can use rational numbers to
store exact values
 This helps to reduce or eliminate round-off errors that can occur when performing arithmetic operations
 A rational number is a number that can be expressed as a ratio of two integers: 7/8
 The top value is called the numerator and the bottom value, which cannot be zero, is called the
denominator

 We want to use our rational numbers as we would use integers and floating point values
 Thus, our Fraction class must perform the following operations:
1. Create a rational number
2. Access the numerator and denominator values, individually
3. Determine if the rational number is negative or zero
4. Perform normal mathematical operations on two rational numbers (addition, subtraction,
multiplication, division, exponentiation)
5. Logically compare two rational numbers
6. Produce a string representation of the rational number
 The objects of the Fraction class will be immutable because none of the operations
06/10/2025modify
the objects’ instance variables
Required Data Attributes
 Because a rational number consists of two integers, we need two instance variables to
store those values:
self._numerator = 0
self._denominator = 1

• At no time should the rational number be converted to a floating-point value or we will lose
the precision gained from working with rational numbers

 Signed values
 Negative and positive rational numbers each have two forms that can be used to specify the
corresponding value
 Positive values can be indicated as 1/2 or –1/–2, and negative values as –2/5 or 2/–5
 When performing an arithmetic operation or logically comparing two rational numbers, it will be
much easier if we have a single way to represent a negative value
 For simplicity, we choose to set only the numerator to a negative value when the rational number
is negative, and both the numerator and denominator will be positive integers when the rational
number is positive

06/10/2025
Representing Values Equivalently
 Equivalent fractions
 For example, 1/4 can be written as 1/4, 2/8, 16/64, or 123/492
 It will be much easier to perform the operation if the number is stored in reduced
form

The Constructor (1)


def _ _init_ _(self, numerator,
denominator)
 Because : objects are immutable, their values must be set when
Fraction
they are created. This requires parameter variables for both the numerator
and denominator
• The method must check for special cases:
• Zero denominators
• The number represents zero or a negative number

06/10/2025
The Constructor
def _ _init_ _(self, numerator = 0, denominator =
1) :
if denominator == 0 :
raise ZeroDivisionError("Denominator
cannot be zero.")
if numerator == 0 :
self._numerator = 0
self._denominator = 1
else :
if (numerator < 0 and denominator >= 0 or
numerator >= 0 and denominator < 0) :
sign = -1
else : frac1 = Fraction(1, 8) # Stored as 1/8
sign = 1
a = abs(numerator) frac2 = Fraction(-2, -4) # Stored as 1/2
b = abs(denominator) frac3 = Fraction(-2, 4) # Stored as -1/2
while a % b != 0 : frac4 = Fraction(3, -7) # Stored as -3/7
tempA = a frac5 = Fraction(0, 15) # Stored as 0/1
tempB = b frac6 = Fraction(8, 0) # Error! exception is
a = tempB raised.
b = tempA % tempB
self._numerator = abs(numerator) // b * 06/10/2025
sign
Comparing Fractions (1)
 In Python, we can define and implement methods that will be called
automatically when a standard Python operator (+, *, ==, <) is applied to an
instance of the class
 For example, to test whether two fractions are equal, we could implement a
method:
 isequal() and use it as follows:

if frac1.isequal(frac2) :
print("The fractions are equal.")

06/10/2025
Comparing Fractions (2)
• Of course, we would prefer to use the operator ==
• This is achieved by defining the special method:
_ _eq_ _():

def _ _eq_ _(self, rhsValue) :


return (self._numerator == rhsValue.numerator and
self._denominator ==
rhsValue.denominator)
 Automatically calls this method when we compare two
Fraction objects using the == operator:

if frac1 == frac2 : # Calls frac1._ _eq_ _(frac2)


print("The fractions are equal.")

06/10/2025
Special Methods
• Some special methods are called when an instance of
the class is passed to a built-in function. For example,
suppose you attempt to convert a Fraction object to a
floating point number using the float() function:
x = float(frac1)
 Then the _ _float_ _() special method is called.
 Here is a definition of that method:

def _ _float_ _(self) :


return self._numerator /
self._denominator

06/10/2025
Common Special Methods

06/10/2025
Common Special Methods

06/10/2025
Addition of Fractions
 All of the arithmetic operations that can be performed on a Fraction object
should return the result in a new Fraction object
 For example, when the statement below is executed, frac1 should be
added to frac2 and the result returned as a new Fraction object that is
assigned to the newFrac variable

newFrac = frac1 + frac2

06/10/2025
Fractional Addition
 From elementary arithmetic, you know that two fractions must have a
common denominator in order to add them. If they do not have a common
denominator, we can still add them using the formula:

06/10/2025
Defining the Method For Addition

def _ _add_ _(self, rhsValue) :


num = (self._numerator *
rhsValue._denominator +
self._denominator * rhsValue._numerator)
den = self._denominator *
rhsValue._denominator
return Fraction(num, den)

06/10/2025
Logic: Less Than
 Note that a / b < c / d when d · a < b · c. (Multiply both sides with b · d.)
 Based on this observation, the less than operation is implemented by the _
_lt_ _() method as follows:
def _ _lt_ _(self, rhsValue) :
return (self._numerator *
rhsValue._denominator
self._denominator *
rhsValue._numerator)

06/10/2025
Fraction.py

06/10/2025
06/10/2025
06/10/2025
06/10/2025
Checking Type
 To ensure that, Python provides the built-in isinstance() function that can
be used to check the type of object referenced by a variable.
 For example, the constructor for the Fraction class requires two integers
class Fraction :
def _ _init_ _(self, numerator, denominator) :
if (not isinstance(numerator, int) or
not isinstance(denominator, int)) :
raise TypeError
("The numerator and denominator must be
integers.")

06/10/2025

You might also like