0% found this document useful (0 votes)
6 views44 pages

Module IV Python

Module IV of the Application Development Using Python course covers the concepts of classes and objects, including user-defined types, attributes, and methods. It explains the creation and manipulation of classes, including inheritance and encapsulation, using practical examples such as Point and Rectangle classes. The module emphasizes the importance of attributes, instance vs class attributes, and provides sample programs to illustrate these concepts.

Uploaded by

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

Module IV Python

Module IV of the Application Development Using Python course covers the concepts of classes and objects, including user-defined types, attributes, and methods. It explains the creation and manipulation of classes, including inheritance and encapsulation, using practical examples such as Point and Rectangle classes. The module emphasizes the importance of attributes, instance vs class attributes, and provides sample programs to illustrate these concepts.

Uploaded by

Rakshitha P
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Application Development Using Python (18CS55) Module IV

MODULE IV

4.1 CLASSES AND OBJECTS


Programmer defined types, Attributes, Rectangles, Copying
4.2 CLASSES AND FUNCTIONS
Time, Pure Functions, Modifiers, Prototyping vs Planning
4.3 CLASSES AND METHODS
Object Oriented Features, Printing objects, Another example, A more complicated example, The init
Method and str Method, Operator Overloading, Type-based dispatch, Polymorphism, Interface and
Implementation
4.4 INHERITANCE
Card objects, Class attributes, Comparing cards, Decks, Printing the deck, Add, remove, shuffle and sort,
Inheritance, Class diagrams, Data encapsulation

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 1


Application Development Using Python (18CS55) Module IV

MODULE IV

4.1 CLASSES AND OBJECTS


 Python is an object-oriented programming language, and class is a basis for any object oriented
programming language.
 Class is a user-defined data type which binds data and functions together into single entity.
 Class is just a prototype (or a logical entity/blue print) which will not consume any memory.
 An object is an instance of a class and it has physical existence.
 One can create any number of objects for a class.
 A class can have a set of variables (also known as attributes, member variables) and member
functions (also known as methods).

 Programmer-defined Types
 We have used many of Python’s built-in types; now we are going to define a new type.
 Lets create our own user-defined type: Point.
 Consider the concept of a mathematical point. In two dimensions, a point is two numbers (coordinates)
that are treated collectively as a single object/entity.
 In mathematical notation, points are often written in parentheses with a comma separating the
coordinates. For example, (0, 0) represents the origin, and (x, y) represents the point x units to the right
and y units up from the origin.
 There are several ways we might represent points in Python:
o We could store the coordinates separately in two variables, x and y.
o We could store the coordinates as elements in a list or tuple.
o We could create a new type to represent points as objects.
 A programmer-defined new type is also called a class
 A class in Python can be created using a keyword class.
 The syntax rules for a class definition is:
o There is a header which begins with the keyword, class, followed by the name of the class,
and ending with a colon.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 2


Application Development Using Python (18CS55) Module IV

o The body is a docstring that explains what the class is for.


o We can define variables and methods inside a class definition,
 Here, we are creating an empty class without any members by just using the keyword passwithin it.
class Point:
pass
OR
class Point:
“““Represents a point 2-D Space”””

print(Point)
The output would be –
<class ' main .Point'>
 The term main indicates that the class Point is in the main scope of the current module.
 In other words, this class is at the top level while executing the program.
 Now, a user-defined data type Point got created, and this can be used to create any number of
objects of this class.
 Observe the following statements:
p=Point()
 Now, a reference (for easy understanding, treat reference as a pointer) to Point object is created
and is returned. This returned reference is assigned to the object p.
 The process of creating a new object is called as instantiation and the object is instance of a
class.
 Classes, like functions, are callable, and we instantiate a Point object by calling the Point class
 When we print an object, Python tells which class it belongs to and where it is stored in the
memory.
print(p)
The output would be –
< main .Point object at 0x003C1BF0>
 The output displays the address (in hexadecimal format) of the object in the memory.
 It is now clear that, the object occupies the physical space, whereas the class does not.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 3


Application Development Using Python (18CS55) Module IV

 Attributes
 User-defined classes in Python have two types of attributes viz. class attributes and instance
attributes.
 Class attributes are defined inside the class (usually, immediately after class header). They are
common to all the objects of that class. That is, they are shared by all the objects created from that
class.
 But, instance attributes defined for individual objects. They are available only for that instance (or
object).
 Attributes of one instance are not available for another instance of the same class.
 An object can contain named elements known as instance attributes.
 One can assign values to these attributes using dot operator.
 For example, keeping coordinate points in mind, we can assign two attributes x and y for the
object of a class Point as below
p.x =10.0
p.y =20.0
 A state diagram that shows an object and its attributes is called as object diagram.
 For the object p, the object diagram is shown in Figure below.

Point
x 10.0
y 20.0
p

Figure : Object Diagram

 The diagram indicates that a variable (i.e. object) p refers to a Point object, which contains two
attributes.
 Each attributes refers to a floating point number.
 One can access attributes of an object as shown –
>>> print(p.x)
10.0
>>> print(p.y)
20.0

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 4


Application Development Using Python (18CS55) Module IV

 Here, p.x means “Go to the object p refers to and get the value of x”.
 Attributes of an object can be assigned to other variables
>>> x= p.x
>>> print(x)
10.0
 Here, the variable x is nothing to do with attribute x.
 There will not be any name conflict between normal program variable and attributes of an object.
 A complete program:
 Write a class Point representing a point on coordinate system. Implement following functions –
 A function read_point() to receive x and y attributes of a Point object as user input.
 A function distance() which takes two objects of Point class as arguments and computes the
Euclidean distance between them.
 A function print_point() to display one point in the form of ordered-pair.

Program:
import math
class Point:
""" This is a class Point representing a coordinate point"""

#function to read the attributes of the Point object


def read_point(p):
p.x=float(input("x coordinate:"))
p.y=float(input("y coordinate:"))

#function to print the attributes of the Point object


def print_point(p):
print("(%g,%g)"%(p.x, p.y))

#function which takes two objects of Point class as arguments and computes the Euclidean
distance between them
def distance(p1,p2):

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 5


Application Development Using Python (18CS55) Module IV

d=[Link]((p1.x-p2.x)**2+(p1.y-p2.y)**2)
return d

p1=Point() #create first object


print("Enter First point:")
read_point(p1) #read x and y for p1

p2=Point() #create second object


print("Enter Second point:")
read_point(p2) #read x and y for p2

dist=distance(p1,p2) #compute distance

print("First point is:")


print_point(p1) #print p1

print("Second point is:")


print_point(p2) #print p2

print("Distance is: %g" % dist) #print the Euclidean distance between p1 and p2

The sample output of above program would be –


Enter First point:
x coordinate:10
y coordinate:20
Enter Second point:
x coordinate:3
y coordinate:5
First point is: (10,20)

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 6


Application Development Using Python (18CS55) Module IV

Second point is:(3,5)


Distance is: 16.5529

Let us discuss the working of above program thoroughly –


 The class Point contains a string enclosed within 3 double-quotes. This is known as docstring.
Usually, a string literal is written within 3 consecutive double-quotes inside a class, module or
function definition. It is an important part of documentation and is to help someone to
understand the purpose of the said class/module/function. In the above program, there is no
need of docstring and we would have just used pass to indicate an empty class. But, it is better
to understand the professional way of writing user-defined types and hence, introduced
docstring.
 The function read_point(p) take one argument of type Point object. When we use the
statements like,
read_point(p1) #function call
the parameter p of this function will act as an alias for the argument p1. Hence, the
modification done to the alias p reflects the original argument p1. With the help of this
function, we are instructing Python that the object p1 has two attributes x and y.
 The function print_point() also takes one argument and with the help of format- strings, we are
printing the attributes x and y of the Point object as an ordered-pair (x,y).
 As we know, the Euclidean distance between two points (x1,y1) and (x2,y2) is


x1 x2
2 
y1 y2
2

In this program, we have Point objects as (p1.x, p1.y) and (p2.x, p2.y). Apply the formula on
these points by passing objects p1 and p2 as parameters to the function distance(). And then
return the result.

Thus, the above program gives an idea of defining a class, instantiating objects, creating attributes,
defining functions that takes objects as arguments and finally, calling (or invoking) such functions
whenever and wherever necessary.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 7


Application Development Using Python (18CS55) Module IV

NOTE: User-defined classes in Python have two types of attributes viz. class attributes and instance
attributes. Class attributes are defined inside the class (usually, immediately after class header). They
are common to all the objects of that class. That is, they are shared by all the objects created from that
class. But, instance attributes defined for individual objects. They are available only for that instance (or
object). Attributes of one instance are not available for another instance of the same class.
For example, consider the class Point as discussed earlier –

class Point:
pass

p1= Point() #first object of the class


p1.x=10.0 #attributes for p1
p1.y=20.0
print(p1.x, p1.y) #prints 10.0 20.0

p2= Point() #second object of the class


print(p2.x) #displays error as below
AttributeError: 'Point' object has no attribute 'x'

 This clearly indicates that the attributes x and y created are available only for the object p1, but
not for p2. Thus, x and y are instance attributes but not class attributes.
 We will discuss class attributes late in-detail. But, for the understanding purpose, observe the
following example –

class Point:
x=2
y=3

p1=Point() #first object of the class


print(p1.x, p1.y) # prints 2 3

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 8


Application Development Using Python (18CS55) Module IV

p2=Point() #second object of the class


print(p2.x, p2.y) # prints 2 3

 Here, the attributes x and y are defined inside the definition of the class Point itself. Hence, they
are available to all the objects of that class.

 Rectangles
 It is possible to make an object of one class as an attribute to other class.
 To illustrate this, consider an example of creating a class called as Rectangle.
 A rectangle can be created using any of the following data –
 By knowing width and height of a rectangle and one corner point (ideally, a bottom- left
corner) in a coordinate system
 By knowing two opposite corner points
 Let us consider the first technique and implement the task:
 Program : Write a class Rectangle containing numeric attributes width and height. This class
should contain another attribute corner which is an instance of another class Point. Implement
following functions –
o A function to print corner point as an ordered-pair
o A function find_center() to compute center point of the rectangle
o A function resize() to modify the size of
rectangle
 The program is as given below –

class Point:
""" This is a class Point representing coordinate point"""

class Rectangle:
""" This is a class Rectangle. Attributes: width, height and Corner Point """

def find_center(rect):
"""Returns a Point at the center of a Rectangle.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 9


Application Development Using Python (18CS55) Module IV

rect: Rectangle object


returns: new Point object"""
center=Point()
center.x = [Link].x + [Link]/2
center.y = [Link].y + [Link]/2
return center

def resize(rect, w, h):


"""Modifies the Rectangle by adding to its width and height.
rect: Rectangle object.
dwidth: change in width (can be negative).
dheight: change in height (can be negative). """
[Link] +=w
[Link]+=h

def print_point(p):
print("(%g,%g)"%(p.x, p.y))

box=Rectangle() #create Rectangle object


[Link]=Point() #define an attribute corner for box
[Link]=100 #set attribute width to box
[Link]=200 #set attribute height to box
[Link].x=0 #corner itself has two attributes x and y
[Link].y=0 #initialize x and y to 0

print("Original Rectangle is:")


print("width=%g, height=%g"%([Link], [Link]))

center=find_center(box)
print("The center of rectangle is:")
print_point(center)

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 10


Application Development Using Python (18CS55) Module IV

resize(box,50,70)
print("Rectangle after resize:")
print("width=%g, height=%g"%([Link], [Link]))

center=find_center(box)
print("The center of resized rectangle is:")
print_point(center)

A sample output would be:


Original Rectangle is: width=100, height=200
The center of rectangle is: (50,100)
Rectangle after resize: width=150, height=270
The center of resized rectangle is: (75,135)

The working of above program is explained in detail here –


 Two classes Pointand Rectanglehave been created with suitable docstrings. As of now, they
do not contain any class-level attributes.
 The following statement instantiates an object of Rectangleclass.
box=Rectangle()
The statement
[Link]=Point()
indicates that corner is an attribute for the object box and this attribute itself is an object of
the class Point. The following statements indicate that the object box has two more attributes

[Link]=100 #give any numeric value


[Link]=200 #give any numeric value

In this program, we are treating the corner point as the origin in coordinate system and hence
the following assignments –
[Link].x=0 [Link].y=0

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 11


Application Development Using Python (18CS55) Module IV

(Note that, instead of origin, any other location in the coordinate system can be given as
corner point.) Based on all above statements, an object diagram can be drawn as –

Rectangle
width 100 Point
height 200
box x 0
corner y 0

The expression [Link].x means, “Go to the object box refers to and select the attribute
named corner; then go to that object and select the attribute named x.”

 The function find_center() takes an object rect as an argument. So, when a call is made using
the statement –
center=find_center(box)
the object rect acts as an alias for the argument box.

A local object center of type Point has been created inside this function. The attributes of center
are x and y, which takes the values as the coordinates of center point of rectangle. Center of a
rectangle can be computed with the help of following diagram.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 12


Application Development Using Python (18CS55) Module IV

The function find_center() returns the computed center point. Note that, the return value of a
function here is an instance of some class. That is, one can have an instance as return values
from a function.

 The function resize() takes three arguments: rect – an instance of Rectangle class and two
numeric variables w and h. The values w and h are added to existing attributes width and
height. This clearly shows that objects are mutable. State of an object can be changed by
modifying any of its attributes. When this function is called with a statement –
resize(box,50,70)
the rect acts as an alias for box. Hence, width and height modified within the function will
reflect the original object box.

Thus, the above program illustrates the concepts: Object of one class is made as attribute for object of
another class, returning objects from functions and objects are mutable.

 Copying
 An object will be aliased whenever there an object is assigned to another object of same class.
This may happen in following situations –
 Direct object assignment (like p2=p1)
 When an object is passed as an argument to a function
 When an object is returned from a function
 The last two cases have been understood from the two programs in previous sections.
 Let us understand the concept of aliasing more in detail using the following program
>>> class Point:
pass

>>> p1=Point()
>>> p1.x=10
>>> p1.y=20
>>> p2=p1

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 13


Application Development Using Python (18CS55) Module IV

>>> print(p1)
< main .Point object at 0x01581BF0>
>>> print(p2)
< main .Point object at 0x01581BF0>

 Observe that both p1 and p2 objects have same physical memory. It is clear now that the object p2
is an alias for p1.
 So, we can draw the object diagram as below –

p1 x 10 p2
y 20

 Hence, if we check for equality and identity of these two objects, we will get following result.
>>> p1 is p2
True
>>> p1==p2
True
 But, the aliasing is not good always. For example, we may need to create a new object using an
existing object such that – the new object should have a different physical memory, but it must have
same attribute (and their values) as that of existing object. Diagrammatically, we need something as
below –

x 10 p2
p1 x 10 y 20
y 20

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 14


Application Development Using Python (18CS55) Module IV

 In short, we need a copy of an object, but not an alias.


 To do this, Python provides a module called copy and a method called copy(). Consider the below
given program to understand the concept.

>>> class Point:


pass

>>> p1=Point()
>>> p1.x=10
>>> p1.y=20

>>> import copy #import module copy


>>> p3=[Link](p1) #use the method copy()
>>> print(p1)
< main .Point object at 0x01581BF0>
>>> print(p3)
< main .Point object at 0x02344A50>
>>> print(p3.x,p3.y)
10 20

 Observe that the physical address of the objects p1 and p3 are now different.
 But, values of attributes xand y are same. Now, use the following statements –

>>> p1 is p3
False
>>> p1 == p3
False
 Here, the is operator gives the result as False for the obvious reason of p1 and p3 are being two
different entities on the memory.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 15


Application Development Using Python (18CS55) Module IV
 But, why == operator is generating False as the result, though the contents of two objects are
same? The reason is p1 and p3 are the objects of user-defined type.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 16


Application Development Using Python (18CS55) Module IV

 And, Python cannot understand the meaning of equality on the new data type. The default behavior
of equality (==) is identity (is operator) itself. Hence, Python applies this default behavior on p1 ==
p3and results in False.
NOTE: If we need to define the meaning of equality (==) operator explicitly on user-defined data types
(i.e. on class objects), then we need to override the method eq () inside the class. This will be
discussed later in detail.
 The copy() method of copy module duplicates the object.
 The content (i.e. attributes) of one object is copied into another object as we have discussed till
now.
 But, when an object itself is an attribute inside another object, the duplication will result in a
strange manner.
 To understand this concept, try to copy Rectangle object (created in previous section) as given
below

import copy class


Point:
""" This is a class Point representing coordinate point"""

class Rectangle:
""" This is a class [Link]: width, height and Corner Point """

box1=Rectangle()
[Link]=Point()
[Link]=100
[Link]=200
[Link].x=0
[Link].y=0

box2=[Link](box1)
print(box1 is box2) #prints False
print([Link] is [Link]) #prints True

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 17


Application Development Using Python (18CS55) Module IV

 Now, the question is – why [Link] and [Link] are same objects, when box1 and box2
are different? Whenever the statement is executed,
box2=[Link](box1)
 The contents of all the attributes of box1 object are copied into the respective attributes of box2
object.
 That is, [Link] is copied into [Link], [Link] is copied into [Link].
 Similarly, [Link] is copied into [Link].
 Now, recollect the fact that corner is not exactly the object itself, but it is a reference to the object
of type Point (Read the discussion done for Figure at the beginning of this Chapter).
 Hence, the value of reference (that is, the physical address) stored in [Link] is copied into
[Link].
 Thus, the physical object to which [Link] and [Link] are pointing is only one.
 This type of copying the objects is known as shallow copy.
 To understand this behavior, observe the following object diagram :

 Now, the attributes width and height for two objects box1 and box2 are independent.
 Whereas, the attribute corner is shared by both the objects.
 Thus, any modification done to [Link] will reflect [Link] as well.
 Obviously, we don’t want this to happen, whenever we create duplicate objects. That is, we want
two independent physical objects.
 Python provides a method deepcopy() for doing this task.
 This method copies not only the object but also the objects it refers to, and the objects they refer
to, and so on.
box3=[Link](box1)
print(box1 is box3) #prints False
print([Link] is [Link]) #prints False
Thus, the objects box1 and box3 are now completely independent.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 18


Application Development Using Python (18CS55) Module IV

 Debugging
 While dealing with classes and objects, we may encounter different types of errors.
 For example, if we try to access an attribute which is not there for the object, we will get
AttributeError. For example –

>>> p= Point()
>>> p.x = 10
>>> p.y = 20
>>> print(p.z)
AttributeError: 'Point' object has no attribute 'z'

 To avoid such error, it is better to enclose such codes within try/except as given below –
try:
z = p.x
except AttributeError:
z=0

 When we are not sure, which type of object it is, then we can use type() as –
>>> type(box1)
<class ' main .Rectangle'>

 Another method isinstance() helps to check whether an object is an instance of a particular class
>>> isinstance(box1,Rectangle)
True

 When we are not sure whether an object has a particular attribute or not, use a function hasattr() –
>>> hasattr(box1, 'width')
True
 Observe the string notation for second argument of the function hasattr(). Though the attribute
width is basically numeric, while giving it as an argument to function hasattr(), it must be enclosed
within quotes.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 19


Application Development Using Python (18CS55) Module IV

4.2 CLASSES AND FUNCTIONS

 Though Python is object oriented programming languages, it is possible to use it as functional


programming. There are two types of functions viz. pure functions and modifiers.
 A pure function takes objects as arguments and does some work without modifying any of the
original argument.
 On the other hand, as the name suggests, modifier function modifies the original argument.
 In practical applications, the development of a program will follow a technique called as
prototype and patch.
 That is, solution to a complex problem starts with simple prototype and incrementally dealing
with the complications.

 Pure Functions
 To understand the concept of pure functions, let us consider an example of creating a class called
Time.
 An object of class Time contains hour, minute and second as attributes.
 Write a function to print time in HH:MM:SS format and another function to add two time objects.
 Note that, adding two time objects should yield proper result and hence we need to check whether
number of seconds exceeds 60, minutes exceeds 60 etc, and take appropriate action.

class Time:
"""Represents the time of a day Attributes: hour, minute, second """

def printTime(t):
print("%.2d:%.2d:%.2d"%([Link],[Link],[Link]))

def add_time(t1,t2):
sum=Time()
[Link] = [Link] + [Link]
[Link] = [Link] + [Link]

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 20


Application Development Using Python (18CS55) Module IV

[Link] = [Link] + [Link]


if [Link] >= 60:
[Link] -= 60
[Link] += 1
if [Link] >= 60:
[Link] -= 60
[Link] += 1
return sum

t1=Time()
[Link]=10
[Link]=34
[Link]=25
print("Time1 is:")
printTime(t1)

t2=Time()
[Link]=2
[Link]=12
[Link]=41
print("Time2 is :")
printTime(t2)

t3=add_time(t1,t2)
print("After adding two time objects:")
printTime(t3)

The output of this program would be :


Time1 is: 10:34:25
Time2 is : 02:12:41
After adding two time objects: 12:47:06

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 21


Application Development Using Python (18CS55) Module IV

Here, the function add_time() takes two arguments of type Time, and returns a Time object, whereas,
it is not modifying contents of its arguments t1 and t2.
Such functions are called as pure functions.

 Modifiers
 Sometimes, it is necessary to modify the underlying argument so as to reflect the caller.
 That is, arguments have to be modified inside a function and these modifications should be
available to the caller.
 The functions that perform such modifications are known as modifier function.
 Assume that, we need to add few seconds to a time object, and get a new time. Then, we can
write a function as below

def increment(t, seconds):


[Link] += seconds

while [Link] >= 60:


[Link] -= 60
[Link] += 1

while [Link] >= 60:


[Link] -= 60
[Link] += 1

 In this function, we will initially add the argument seconds to [Link].


 Now, there is a chance that [Link] is exceeding 60.
 So, we will increment minute counter till [Link] becomes lesser than 60.
 Similarly, till the [Link] becomes lesser than 60, we will decrement minute counter.
 Note that, the modification is done on the argument t itself. Thus, the above function is a modifier.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 22


Application Development Using Python (18CS55) Module IV

 Prototyping v/s Planning


 Whenever we do not know the complete problem statement, we may write the program initially,
and then keep of modifying it as and when requirement (problem definition) changes. This
methodology is known as prototype and patch.
 That is, first design the prototype based on the information available and then perform patch-work
as and when extra information is gathered.
 But, this type of incremental development may end-up in unnecessary code, with many special
cases and it may be unreliable too.
 An alternative is designed development, in which high-level insight into the problem can make the
programming much easier.
 For example, if we consider the problem of adding two time objects, adding seconds to time object
etc. as a problem involving numbers with base 60 (as every hour is 60 minutes and every minute is
60 seconds), then our code can be improved.
 In this case, the insight is that a Time object is really a three-digit number in base 60! The second
component is the ones column, the minute component is the sixties column, and the hour
component is the thirty-six hundreds column.
 This observation suggests another approach to the whole problem – we can convert a Time object
into a single number and take advantage of the fact that the computer knows how to do arithmetic
with numbers.
 The two functions required are that converts a Time object into an integer, integer to Time object
 The following function converts a Time object into an integer:
def time_to_int(time):
minute=[Link]*60+[Link]
seconds=minute*60+[Link]
return seconds
 Now, all we need is a way to convert from an integer to a Time object:
 Recall that divmod divides the first argument by the second and returns the quotient and remainder
as a tuple
def int_to_time(seconds):
time = Time()

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 23


Application Development Using Python (18CS55) Module IV

minutes, [Link] = divmod(seconds, 60)


[Link], [Link] = divmod(minutes, 60)
return time
 Rewrite the add_time() function
def add_time(t1, t2):
seconds = time_to_int(t1) + time_to_int(t2)
return int_to_time(seconds)
 Debugging
 In the program written inabove, we have treated time objects as valid values.
 But, what if the attributes (second, minute, hour) of time object are given as wrong values like
negative number, or hours with value more than 24, minutes/seconds with more than 60 etc? So, it is
better to write error-conditions in such situations to verify the input.
 We can write a function similar to as given below –

def valid_time(time):
if [Link] < 0 or [Link] < 0 or [Link] < 0:
return False

if [Link]>=24 or [Link] >= 60 or [Link] >= 60:


return False

return True
 Now, at the beginning of add_time() function, we can put a condition as –
def add_time(t1, t2):
if not valid_time(t1) or not valid_time(t2):
raise ValueError('invalid Time object in add_time')
seconds = time_to_int(t1) + time_to_int(t2)
return int_to_time(seconds)
 Python provides another debugging statement assert.
 When this keyword is used, Python evaluates the statement following it. If the statement is True,

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 24


Application Development Using Python (18CS55) Module IV

further statements will be evaluated sequentially. But, if the statement is False, then
AssertionError exception is raised.
 The usage of assert is shown here –
def add_time(t1, t2):
assert valid_time(t1) and valid_time(t2)
seconds = time_to_int(t1) + time_to_int(t2)
return int_to_time(seconds)

 The assert statement clearly distinguishes the normal conditional statements as a part of the logic
of the program and the code that checks for errors.

4.3 CLASSES AND METHODS


 The classes that have been considered till now were just empty classes without having any
definition.
 But, in a true object oriented programming, a class contains class-level attributes, instance-level
attributes, methods etc.
 There will be a tight relationship between the object of the class and the function that operate on
those objects. Hence, the object oriented nature of Python classes will be discussed here.

 Object-Oriented Features
 Python as an object oriented programming language, it must possess the following characteristics:
 Programs include class and method definitions.
 Most of the computation is expressed in terms of operations on objects.
 Objects often represent things in the real world, and methods often correspond to the ways
objects in the real world interact.
 To establish relationship between the object of the class and a function, we must define a function
as a member of the class.
 For example, the Time class defined earlier corresponds to the way people record the time of day,
and the functions we defined correspond to the kinds of things people do with times
 A function which is associated with a particular class is known as a method.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 25


Application Development Using Python (18CS55) Module IV

 Methods are semantically the same as functions, but there are two syntactic differences:
 Methods are defined inside a class definition in order to make the relationship
between the class and the method explicit.
 The syntax for invoking a method is different from the syntax for calling a function.

 Printing objects
 In the last program, we defined a class named Time and wrote a function named print_time,
which should have looked something like this:

 To make print_time a method, all we have to do is move the function definition inside the class
definition. Notice the change in indentation.
class Time:
def print_time(time):
#body
 Now we can invoke print_time using dot notation in two ways.
 Time.print_time(start) #start is Time object
 start.print_time()
 In this use of dot notation, print_time is the name of the method (again), and start is the object the

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 26


Application Development Using Python (18CS55) Module IV

method is invoked on, which is called the subject.


 Inside the method, the subject is assigned to the first parameter, so in this case start is assigned to
time.
 By convention, the first parameter of any method is called self which is reference to the invoking
object, so it would be more common to write print_time like this:
class Time:
def print_time(self):
print('%.2d:%.2d:%.2d' % ([Link], [Link], [Link]))

 Another example
 Here’s a version of increment rewritten as a method:
# inside class Time:
def increment(self, seconds):
seconds += self.time_to_int()
return int_to_time(seconds)
 This version assumes that time_to_int is written as a method. Also, note that it is a pure function,
not a modifier.
 Here’s how we would invoke increment:
>>> start.print_time()
09:45:00
>>> end = [Link](1337)
>>> end.print_time()
10:07:17
 The subject, start, gets assigned to the first parameter, self. The argument, 1337, gets assigned to
the second parameter, seconds.
 This mechanism can be confusing, especially if we make an error. For example, if we invoke
increment with two arguments, we get:
>>> end = [Link](1337, 460)
TypeError: increment() takes 2 positional arguments but 3 were given
 The error message is initially confusing, because there are only two arguments in parentheses. But

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 27


Application Development Using Python (18CS55) Module IV

the subject is also considered an argument, so all together that’s three.


 A more complicated example
 Designing is_after() methis is slightly more complicated because it takes two Time objects as
parameters.
 In this case it is conventional to name the first parameter self and the second parameter other:
# inside class Time:
def is_after(self, other):
return self.time_to_int() > other.time_to_int()
 To use this method, we have to invoke it on one object and pass the other as an argument:
>>> end.is_after(start)
True

 The init () Method


 A method init () has to be written with two underscores before and after the word init
 Python provides a special method called as init () which is similar to constructor method in other
programming languages like C++/Java.
 The term init indicates initialization.
 As the name suggests, this method is invoked automatically when the object of a class is created.
Consider the example given here –
import math
class Point:
def init (self,a,b):
self.x=a
self.y=b

def dist(self,p2):
d=[Link]((self.x-p2.x)**2 + (self.y-p2.y)**2)
return d

def str (self):


return "(%d,%d)"%(self.x, self.y)

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 28


Application Development Using Python (18CS55) Module IV

p1=Point(10,20) # init () is called automatically


p2=Point(4,5) # init () is called automatically

print("P1 is:",p1) # str () is called automatically


print("P2 is:",p2) # str () is called automatically

d=[Link](p2) #explicit call for dist()


print("The distance is:",d)
The sample output is –
P1 is: (10,20)
P2 is: (4,5)
Distance is: 16.15549442140351

 Let us understand the working of this program and the concepts involved:
 Keep in mind that every method of any class must have the first argument as self. The argument
self is a reference to the current object. That is, it is reference to the object which invoked the
method. (Those who know C++, can relate self with this pointer). The object which invokes a
method is also known as subject.
 The method init () inside the class is an initialization method, which will be invoked
automatically when the object gets created. When the statement like –

p1=Point(10,20)

is used, the init () method will be called automatically. The internal meaning of the above
line is –
p1. init (10,20)

Here, p1 is the object which is invoking a method. Hence, reference to this object is created and
passed to init () as self. The values 10 and 20 are passed to formal parameters a and b of init ()
method. Now, inside init () method, we have statements

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 29


Application Development Using Python (18CS55) Module IV

self.x=10
self.y=20
This indicates, xand yare instance attributes. The value of xfor the object p1 is 10 and, the
value of y for the object p1is 20.

When we create another object p2, it will have its own set of x and y. That is, memory
locations of instance attributes are different for every object.

Thus, state of the object can be understood by instance attributes.


 The method dist() is an ordinary member method of the class Point. As mentioned earlier, its
first argument must be self. Thus, when we make a call as –

d=[Link](p2)

a reference to the object p1 is passed as self to dist() method and p2 is passed explicitly as a
second argument. Now, inside the dist()method, we are calculating distance between two point
(Euclidian distance formula is used) objects. Note that, in this method, we cannot use the name
p1, instead we will use self which is a reference (alias) to p1.

 The str method

 The next method inside the class is str ().


 It is a special method used for string representation of user-defined object.
 Usually, print() is used for printing basic types in Python. But, user-defined types (class
objects) have their own meaning and a way of representation.
 To display such types, we can write functions or methods like print_point() as we did in
previous section
 But, more polymorphic way is to use str () so that, when we write just print() in the main
part of the program, the str () method will be invoked automatically. Thus, when we use
the statement like –
print("P1 is:",p1)
Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 30
Application Development Using Python (18CS55) Module IV

the ordinary print() method will print the portion “P1 is:” and the remaining portion is taken care by
str () method.
 In fact, str () method will return the string format what we have given inside it, and that string
will be printed by print() method.

 Operator Overloading
 Some languages make it possible to change the definition of the built- in operators when they are
applied to user-defined types.
 Changing the behavior of an operator so that it works with programmer-defined types is called
operator overloading or Ability of an existing operator to work on user-defined data type (class)
is known as operator overloading.
 By defining other special methods, we can specify the behavior of operators on programmer defined
types.
 For example, if you define a method named add for the Time class, you can use the +
operator on Time objects.
 As usual, the first parameter is the object on which the method is invoked.
 The second parameter is conveniently named other to distinguish it from self.
 It is a polymorphic nature of any object oriented programming.
 Basic operators like +, -, * etc. can be overloaded.
 To overload an operator, one needs to write a method within user-defined class.
 Python provides a special set of methods which have to be used for overloading required operator.
 The method should consist of the code what the programmer is willing to do with the operator.
Following table shows gives a list of operators and their respective Python methods for overloading.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 31


Application Development Using Python (18CS55) Module IV

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 32


Application Development Using Python (18CS55) Module IV

 Let us consider an example of Point class considered earlier.


 Using operator overloading, we can try to add two point objects. Consider the program given
below –

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 33


Application Development Using Python (18CS55) Module IV

class Point:
def _init_ (self,a=0,b=0):
self.x=a
self.y=b

def add (self, other):


p3=Point()
p3.x=self.x+other.x
p3.y=self.y+other.y
return p3

def str (self):


return "(%d,%d)"%(self.x, self.y)

p1=Point(10,20)
p2=Point(4,5)

print("P1 is:",p1)
print("P2 is:",p2)
p4=p1+p2 #call for add () method
print("Sum is:",p4)

The output would be –


P1 is: (10,20)
P2 is: (4,5)
Sum is: (14,25)

 In the above program, when the statement p4 = p1+p2 is used, it invokes a special method _add
() written inside the class. Because, internal meaning of this statement is–
p4 = p1. add (p2)

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 34


Application Development Using Python (18CS55) Module IV

Here, p1 is the object invoking the method. Hence, self inside _add () is the reference (alias) of p1.
And, p2 is passed as argument explicitly.

In the definition of add (), we are creating an object p3with the statement –
p3=Point()

The object p3 is created without initialization. Whenever we need to create an object with and without
initialization in the same program, we must set arguments of init () for some default values. Hence, in the
above program arguments a and b of init () are made as default arguments with values as zero. Thus, x
and y attributes of p3will be now zero. In the add () method, we are adding respective attributes of self and
other and storing in p3.x and p3.y. Then the object p3 is returned. This returned object is received as p4
and is printed
NOTE that, in a program containing operator overloading, the overloaded operator behaves in a
normal way when basic types are given. That is, in the above program, if we use the statements
m= 3+4
print(m)

it will be usual addition and gives the result as 7. But, when user-defined types are used as operands,
then the overloaded method is invoked.
 Type based dispatch
 Let us consider a more complicated program involving overloading.
 Consider a problem of creating a class called Time, adding two Time objects, adding a number to
Time object etc. that we had considered in previous section.
 Here is a complete program with more of OOP concepts.

class Time:
def init (self, h=0,m=0,s=0):
[Link]=h
[Link]=m
[Link]=s

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 35


Application Development Using Python (18CS55) Module IV

def time_to_int(self):
minute=[Link]*60+[Link]
seconds=minute*60+[Link]
return seconds

def int_to_time(self, seconds):


t=Time()
minutes, [Link]=divmod(seconds,60)
[Link], [Link]=divmod(minutes,60)
return t

def _str (self):


return "%.2d:%.2d:%.2d"%([Link],[Link],[Link])

def _ eq (self,other):
return [Link]==[Link] and [Link]==[Link] and [Link]==[Link]

def add (self,other):


if isinstance(other, Time):
return [Link](other)
else:
return [Link](other)

def addTime(self, other):


seconds=self.time_to_int()+other.time_to_int()
return self.int_to_time(seconds)

def increment(self, seconds):


seconds += self.time_to_int()
return self.int_to_time(seconds)

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 36


Application Development Using Python (18CS55) Module IV

def radd (self,other):


return self. add (other)

T1=Time(3,40)
T2=Time(5,45)
print("T1 is:",T1)
print("T2 is:",T2)
print("Whether T1 is same as T2?",T1==T2) #call for eq ()
T3=T1+T2 #call for add ()
print("T1+T2 is:",T3)

T4=T1+75 #call for add ()


print("T1+75=",T4)

T5=130+T1 #call for radd ()


print("130+T1=",T5)

T6=sum([T1,T2,T3,T4])
print("Using sum([T1,T2,T3,T4]):",T6)

The output would be –


T1 is: 03:40:00
T2 is: 05:45:00
Whether T1 is same as T2? False
T1+T2 is: 09:25:00
T1+75= 03:41:15
130+T1= 03:42:10
Using sum([T1,T2,T3,T4]): 22:31:15

 Working of above program is explained here under –


 The class Time has init () method for initialization of instance attributes hour, min and sec.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 37


Application Development Using Python (18CS55) Module IV

The default values of all these are being zero.


 The method time_to_int() is used convert a Time object (hours, min and sec) into single integer
representing time in number of seconds.
 The method int_to_time() is written to convert the argument secondsinto time object in the form of
hours, min and sec. The built-in method divmod() gives the quotient as well as remainder after
dividing first argument by second argument given to it.
 Special method eq ()is for overloading equality (==) operator. We can say one Time object is equal to
the other Time object if underlying hours, minutes and seconds are equal respectively. Thus, we are
comparing these instance attributes individually and returning either True of False.
 When we try to perform addition, there are 3 cases –
o Adding two time objects like T3=T1+T2.
o Adding integer to Time object like T4=T1+75
o Adding Time object to an integer like T5=130+T1
 Each of these cases requires different logic. When first two cases are considered, the first
argument will be T1 and hence self will be created and passed to add () method.
 Inside this method, we will check the type of second argument using isinstance() method.
 If the second argument is Time object, then we call addTime()method. In this method, we will first
convert both Time objects to integer (seconds) and then the resulting sum into Time object again
 So, we make use time_to_int() and int_to_time() here. When the 2nd argument is an integer it is
obvious that it is number of seconds. Hence, we need to call increment() method.
 Thus, based on the type of argument received in a method, we take appropriate action. This is
known as type-based dispatch.
 In the 3rd case like T5=130+T1, Python tries to convert first argument 130 into self, which is not
possible. Hence, there will be an error. This indicates that for Python, T1+5 is not same as 5+T1
(Commutative law doesn’t hold good!!).
 The Error is :TypeError: unsupported operand type(s) for +: 'int' and 'instance'
 The problem is, instead of asking the Time object to add an integer, Python is asking an integer
to add a Time object, and it doesn’t know how.
 Python provides a clever solution for this problem: the special method radd , which stands
for “right-side add”.
 This method is invoked when a Time object appears on the right side of the + operator.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 38


Application Development Using Python (18CS55) Module IV

 We need to implement right-side addition method radd (). Inside this method, we can call
overloaded method add ().
 The following are some of the reverse operator overloading special methods:

 Polymorphism
 Type-based dispatch is useful when it is necessary, but (fortunately) it is not always necessary.
 Often we can avoid it by writing functions that work correctly for arguments with different
types.
 Many of the functions we wrote for strings also work for other sequence types.
 For example, in Module 2 we used histogram to count the number of times each letter appears in
a word.
def histogram(s):
d = dict()
for c in s:
if c not in d:
d[c] = 1
else: d[c] = d[c]+1

return d
 This function also works for lists, tuples, and even dictionaries, as long as the elements of s are
hashable, so they can be used as keys in d.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 39


Application Development Using Python (18CS55) Module IV

>>> t = ['spam', 'egg', 'spam', 'spam', 'bacon', 'spam']


>>> histogram(t)
{'bacon': 1, 'egg': 1, 'spam': 4}
 Functions that work with several types are called polymorphic.
 Polymorphism can facilitate code reuse.
 The beauty of Python lies in surprising the programmer with more facilities!! As we have
implemented add () method (that is, overloading of + operator), the built- in sum() will is
capable of adding multiple objects given in a sequence. This is due to Polymorphism in Python.
 Consider a list containing Time objects, and then call sum()on that list as –
T6=sum([T1,T2,T3,T4])
 The sum() internally calls add () method multiple times and hence gives the appropriate result.
Note down the square-brackets used to combine Time objects as a list and then passing it to
sum().
 Thus, the program given here depicts many features of OOP concepts.

 Interface and implementation


 One of the goals of object-oriented design is to make software more maintainable, which means that
we can keep the program working when other parts of the system change, and modify the program to
meet new requirements.
 A design principle that helps achieve that goal is to keep interfaces separate from implementations.
 For objects, that means that the methods a class provides should not depend on how the attributes are
represented.
 For example, in this chapter we developed a class that represents a time of day. Methods provided by
this class include time_to_int, is_after, and add_time.
 We could implement those methods in several ways. The details of the implementation depend on
how we represent time.
 In this chapter, the attributes of a Time object are hour,minute, and second. As an alternative, we
could replace these attributes with a single integer representing the number of seconds since
midnight. This implementation would make some methods, like is_after, easier to write, but it makes
other methods harder.
 After we deploy a new class, we might discover a better implementation. If other parts of the
program are using the class, it might be time-consuming and error-prone to change the interface.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 40


Application Development Using Python (18CS55) Module IV

 But if we designed the interface carefully, we can change the implementation without changing the
interface, which means that other parts of the program don’t have to change.

 Debugging
 We have seen earlier that hasattr() method can be used to check whether an object has particular
attribute.
 There is one more way of doing it using a method vars(). This method maps attribute names and
their values as a dictionary.
 For example, for the Point class defined earlier, use the statements
>>> p = Point(3, 4)
>>> vars(p) #output is {'y': 4, 'x': 3}
 For purposes of debugging, you might find it useful to keep this function handy:
def print_attributes(obj):
for attr in vars(obj):
print(attr, getattr(obj, attr))

 Here, print_attributes() traverses the dictionary and prints each attribute name and its
corresponding value.
 The built-in function getattr() takes an object and an attribute name (as a string) and returns the
attribute values

4.4 INHERITANCE
 Inheritance is the ability to define a new class from an existing class.
 To define a new class that inherits from an existing class, you put the name of the existing class in
parentheses
 When a new class inherits from an existing one, the existing one is called the parent/base/super
and the new class is called the child/derived/sub.
 Inheritance enables us to define a class that takes all the functionality from a parent class and
allows us to add more.
 Derived class inherits features from the base class where new features can be added to it. This

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 41


Application Development Using Python (18CS55) Module IV

results in re-usability of code.


 Types of Inheritance are:

 Class Diagrams are represented below:

 Inheritance and composition are two major concepts in object oriented programming that model
the relationship between two classes.
 Both of them enable code reuse, but they do it in different ways.
 Inheritance models what is called an is a relationship. This means that when you have
a Derived class that inherits from a Base class, you created a relationship where Derived is

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 42


Application Development Using Python (18CS55) Module IV

a specialized version of Base.


 A base class Animal and we derive from it to create a Horse class. The inheritance relationship
states that a Horse is an Animal

 Composition is a concept that models a has a relationship.


 It enables creating complex types by combining objects of other types.
 This means that a class Composite can contain an object of another class Component. This
relationship means that a Composite has a Component.
 Composition is represented through a line with a diamond at the composite class pointing to the
component class.
 The composite side can express the cardinality of the relationship. The cardinality indicates the
number or valid range of Component instances the Composite class will contain.
 In the diagram , the 1 represents that the Composite class contains one object of type Component

 Classes that contain objects of other classes are usually referred to as composites, where classes
that are used to create more complex types are referred to as components.
 For example, Horse class can be composed by another object of type Tail.
 Composition allows you to express that relationship by saying a Horse has a Tail.
 Horse and Dog classes can leverage the functionality of Tail through composition without

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 43


Application Development Using Python (18CS55) Module IV

deriving one class from the other.

Prof. Manjusha, Asst. Professor, Dept of CSE, SVIT Page 44

You might also like