Module 3
Module 3
✓ Classes
✓ Objects
✓ Encapsulation
✓ Data Hiding
✓ Inheritance
✓ Polymorphism
1
Re-usability: Objects can be reused in different programs. The class definitions can be reused
in various applications. Inheritance makes it possible to define subclasses of data objects that
share some or all of the main class characteristics. It forces a more thorough data analysis,
reduces development time and ensures more accurate coding.
Security: Since a class defines only the data it needs to be concerned with, when an instance of
that class (an object) is run, the code will not be able to accidentally access other program data.
This characteristic of data hiding provides greater system security and avoids unintended data
corruption.
1. CLASS DEFINITION
The class definition in Python begins with the keyword class. The first statement after class
definition will be the docstring which gives a brief description about the class. The following
shows the syntax for defining a class.
Syntax
Class ClassName:
„Optional class documentation string'
class suite
A class creates a new local namespace where all its attributes are defined. Attributes may be
data or functions. There are also special attributes in it that begins with double underscores ( ).
For example, doc gives us the docstring of that class. As soon as we define a class, a new
class object is created with the same name. This class object allows us to access the different
attributes as well as to instantiate new objects of that class.
Example Program
class Student:
"Common base class for al1l students"
studentcount = 0
def init (self, rollno, name, course):
self.rollno=rollno
self. name = name
self.course= course
Student.studentcount + =1
def displayCount (self) :
Print ("Total students=", Student.studentcount )
def displayStudent (self) :
2
print ("Roll Number: ", self.rollno)
print ( "Name:”,self.name)
print ("Course: , self.course)
2. CREATING OBJECTS
An object is created by calling the class name with the arguments defined in the init
method. We can access a method by using the dot operator along with the object. Similarly a
class name can be accessed by specifying the method name with the dot operator with the class.
Example Program
# First student object is created
stud1=Student (10, Jack", "MS" )
# Second student object is created.
stud2 =Student (20, "Jill ", "BE")
# Displays the details of First Student
stud1. displayStudent()
# Displays the details of Second Student.
stud2. displayStudent ()
print ("Total Number of Students: " Student.studentcount)
3. ATTRIBUTES
Attributes are the variables and methods associated with an object. They represent the state (data)
and behavior (functions) of an object in object-oriented programming. Attributes are typically
defined in the class definition and can be accessed and modified using the . (dot) operator.
3
3.1.BUILT-IN ATTRIBUTE METHODS
There are built-in functions to access the attributes. We can access the attribute value, check
whether an attribute exists or not, modify an attribute value or delete an attribute.
The following gives the built-in attribute methods.
1. getattr(obj, name[, default]) : This method is used to access the attribute of object.
2. hasattr(obj,name): This attribute is used to check if an attribute exists or not.
3. setattr(obj,name,value) : This method is used to set an attribute. If attribute does not exist,
then it would be created.
4. delattr(obj, name) : This method is used to delete an attribute.
Example Program
class Student:
“Common base class for all students”
def init (self, rollno, name, course) :
self. rollno=rollno
self.name = name
self. course = course
def displayStudent (self) :
print ( "Roll Number:", self. rollno)
print ( "Name :”, self.name)
print ("Course:”,self.course)
studl=Student (10, "Jack",”MS”)
stud1.displayStudent ()
at=getattr (stud1, 'name')
print ("getattr (studl, 'name'):", at)
print ("hasattr (studl, age) :", hasattr(stud1,‟age‟)) #New
attribute inserted
print ("setattr (studl, age, 21) :", setattr (studl, 'age' , 21))
Stud1. displayStudent ()
print ("Age:", studl.age)
# Attribute age deleted
print(delattr (stud1. age) : ", delattr (studl, 'age'))
Stud1. displayStudent()
4
OUTPUT
Roll Number: 10
Name : Jack
Course : MS
getattr (studl, 'name‟): Jack
hasattr (studl, age) : False
setattr (studl, aqe, 21) : None
Roll Number: 10
Name : Jack
Course: MS
Age: 21
delattr (studl, age) : None
Roll Number: 10
Name : Jack
Course: MS
4. module :This contains the module name in which the class is defined. This attribute
is " main " in interactive mode.
5. bases : This contains an empty tuple containing the base classes, in the order of their
occurrence in the base class list.
The following program shows the usage of built-in class attributes.
Example Program
class Student:
"Common base class for all students"
def init (self, rollno, name , course):
self. rollno=rollno
self. name = name
5
self. course = course
def displayStudent (self) :
print ( "Roll Number:", self.rollno)
print ("Name : ", self .name)
print ("Course:”,self.course)
studl=Student (10, "Jack", "MS")
studl.displayStudent ( )
print ("Student. doc :”,Student. doc )
print ( "Student. name :”,Student. name )
nrint ("Student. module :”, Student. module )
print ("Student bases :”,Student. bases )
print ("Student. dict :”,Student. dict )
Output
Roll number : 10
Name: Jack
Course: MS
Student. doc : Common base class for all students
Student. name : Student
Student. module : main
Student. bases : ()
Student. dict :{„displayStudent‟:<function displayStudent at 0x7efdcc04 7758>,
4. DESTRUCTORS IN PYTHON
Python automatically deletes an object that is no longer in use. This automatic destroying of
objects is known as garbage collection. Python periodically performs the garbage collection to
free the blocks off memory that are no longer in use. But a class can implement the special
method del () called a destructor, that is invoked when the instance is about to be destroyed.
This method might be used to clean up any non memory resources used by an instance. The
following program shows the destructors in Python.
6
Example program
Class Student:
“Common base class for all students”
def init (self, rollno, name , course):
self. rollno=rollno
self. name = name
self. course = course
def displayStudent (self) :
print ( "Roll Number:", self.rollno)
print ("Name : ", self.name)
print ("Course:”,self.course)
Output
Roll Number: 10
Name: Jack
Course:MS
Student destroyed
5. ENCAPSULATION
Encapsulation is the most basic concept of OOP. It is the combining of data and the functions
associated with that data in a single unit. In most of the languages including Python, this unit is
called a class. In simple terms we can say that encapsulation is implemented, through classes.
In fact the data members of a class can be accessed through its member functions only. It keeps
the data safe from any external interference and misuse. The only way to access the data is
through the functions of the class. In the example of the class Student, the class encapsulates the
data (rollno, name, course) and the associated functions into a single independent unit.
7
6. DATA HIDING
We can hide data in Python. For this we need to prefix double underscore for an attribute. Data
hiding can be defined as the mechanism of hiding the data of a class from the outside world or
to be precise, from other classes. This is done to protect the data from any accidental or
intentional access. In most of the object oriented programming languages, encapsulation is
implemented through classes. In a class, data may be made private or public. Private data or
function of a class cannot be accessed from outside the class while public data or functions can
be accessed from anywhere. So data hiding is achieved by making the members of class private.
Access to private members is restricted and is only available to the member functions of the
same class. However, the public part of the object is accessible outside the class. Once the
attributes are prefixed with the double underscore, it will not be visible outside the class. The
following program shows an example for data hiding in Python.
Example program
Class HidingDemo:
"Program for Hiding Data"
num=0
def numbercount (self) :
self___num+=1
print ("Number Count=", self. num)
number=HidingDemo ()
number. numbercount ()
print (number. num)
Output
Number Count= 1
Traceback (most recent call last):
File " main.py", line 9, in <module>
Print number. num
AttributeError: HidingDemo instance has no attribute „ num‟
The output shows that numbercount is displayed once,. When it is attempted to call the variable
number. num from outside the function, it resulted in an error.
8
7. INHERITANCE
The mechanism of deriving a new class from an old class is known as inheritance. The old class
is known as base class or super class or parent class. The new one is called the subclass or
derived class or child class. Inheritance allows subclasses to inherit all the variables and
methods to their parent class. The advantage of inheritance is the reusability of code. Fig. 7.1
illustrates the single inheritance. The attributes and methods of parent class will be available in
child class after inheritance.
Parent
Child
Example program
Class Student:
"Common base class for all students"
def getData (self, rollno, name, course):
self. rollno=rollno
self. name = name
self. course = course
Output
Enter Roll Number: 20
Enter Name:Smith
Enter Course Name: MS
Enter Marks:200
Result
Roll Number: 20
Name: Smith
Course: MS
Total Marks: 200
7.1.Multilevel Inheritance
We have already discussed the mechanism of deriving a new class from one parent class. We
can further inherit the derived class to form a new child class. Inheritance which involves more
than one parent class but at different levels is called multilevel inheritance. Figure 7.2 illustrates
multilevel inheritance.
#Main Program
r= int (input (" Enter Roll Number: "))
n= input ("Enter Name:)
r= input ("Enter Course Name:")
m= int (input (Enter Marks; "))
#creating the object
print ("Result" )
studl.getData(r, n, c)
studl=Result () #instance of child
11
studl.getMarks (m)
studl. displayStudent ()
stud1. displayMarks ()
stud1. calculateGrade()
Output
Enter Roll Number: 12
Enter Name:Jones
Enter Course Name: MS
Bnter Marks:400
Result
Roll Number: 12
Name:Jones
Course: MS
Total Marks : 400
Result: First Class
7.2.Multiple Inheritance
It is possible to inherit from more than one parent class. Such type of inheritance is called
multiple inheritance. In this case all the attributes and methods of both the parent class will
be available in the child class after inheritance. Fig 7.3 illustrates multiple inheritance.
A B
class Sports:
def getSportsMarks (self, spmarks) :
self.spmarks=spmarks
def displaySportsMarks (self) :
print ("Sports Marks:", self.spmarks)
#Multiple Inheritance
class Result (Test, Sports) :
def calculateGrade (self):
m=self.marks+self. Spmarks
if m>480:self.grade=”Distinction”
elif m>360: self.grade=”First Class"
elif m>480: self ,qrade="Distinction"
elif m>240: self.grade= " Second Class"
else: self.grade=" Failed”
Print ("Result : ",self.grade)
#Main Program
r = int (input ( "Enter Roll Number: "))
n= input ( "Enter Name: ")
c= input ("Enter Course Name:")
m=int (input ("Enter Marks : ") )
s=int (input ( "Enter Sports marks:"))
#creating the object
13
print ("Result")
studl=Result() #instance of child
studl.getData (r,n,c)
studl.getMarks (m)
studl.getSportsMarks (s)
studl.displayStudent ()
studl.displayMarks ()
studl.displaySportsMarks ()
studl. calculateGrade ()
Output
Enter Roll Number: 10
Enter Name: Bob
Enter Course Name:MS
Enter Marks:190
Enter Sports marks: 200
Result
Roll Number: 10
Name: Bob
Course : MS
Total Marks: 190
8. METHOD OVERRIDING
Polymorphism is an important characteristic of Object Oriented Programming language. In
Object oriented Programming, polymorphism refers to a programming language's ability to
process objects differently depending on their data type or class. More specifically, it is the
ability to redefine methods for derived classes. We can override methods in the parent class.
Method overriding is required when we want to define our own functionality in the child class.
This is possible by defining a method in the child class that has the same name, same arguments
and same return type as a method in the parent class. When this method is called, the method
defined in the child class is invoked and executed instead of the one in the parent class. The
following shows an example program for method overriding.
14
Example program
class Parent:
"Base class”
def init (self, name) :
self. name= name
def displayName (self) :
print ( "Name : ",self.name)
def del (self):
class name = self. class . name
#Main Program
n=input ("Enter Name:")
a=input ("Enter Address:”)
obj=Child (n, a) #instance of child
obj.displayName () #Calling child' s method
del obj
Output
Enter Name :Jill
Enter Address : Klos
Name : Jill
15
Address: Klos
Child destroyed
9. POLYMORPHISM
The word Polymorphism is formed from two words - poly and morph where poly means many
and morph means forms. So polymorphism is the ability to use an operator or function in
various forms. That is a single function or an operator behaves differently depending upon the
data provided to them. Polymorphism can be achieved in two ways: operator overloading and
function overloading. Unlike in C++ and Java, Python does not support function or method
overloading.
Operator Overloading
Operator overloading is one of the important features of object oriented programming. C++ and
Python supports operator overloading, while Java does not support operator overloading. The
mechanism of giving special meanings to an operator is known as operator overloading. For
example the operator + is used for adding two numbers. In Python this operator can also be
used for concatenating two strings. This + operator can be used for adding member variables of
two different class. The following example shows how „+‟ operator can be overloaded.
16
Example program
class Abc:
def init (self,a,b):
self.a=a
self.b= b
10.1.BUILT-IN EXCEPTIONS
Python has a collection of built-in exception classes. If the runtime error belongs to of the
pre-defined built-in exception, it will throw the object of the appropriate exception.
10.2.HANDLING EXCEPTIONS
Python uses a keyword try to prepare a block of code that is likely to cause an error and
throw an exception. An except block is defined which catches the exception thrown by the try
block and handles it. The try block can have one or more statements that could generate an
exception. If anyone statement generates an exception, then the remaining statements in the
block are skipped and execution jumps to the except block that is placed next to the try block.
17
The except block can have more than one statement and if the except parameter matches with
the type of the exception object, then the exception is caught and statements in the except
block will be executed. Every try block should be followed by atleast one except statement.
a. try... except
The following gives the syntax of try ...except statement
Syntax
try:
suite
except Exception1:
Exceptionl_suite #Executes when Exceptionl occurs.
except Exception2:
Exception2_suite #Executes when Exception2 Occurs
else:
else_suite #Executes if there is no Exception in the try block.
Example program
#Exception Handling
try:
a=int (input ("First Number: "))
b=int (input ("Second Number: "))
result=a/b
print ("Result=", result)
except ZeroDivisionError:
print ("Division by Zero")
else:
print ( "Successful Division")
Output
First Number: 10
Second Number:0
Division by Zero
18
b. Except clause with no Exception
We can use except statement with no exceptions. This kind of try-except statement catches
all the Exceptions. Since it catches all the exceptions, it will not help the programmer to
exactly identify what is the cause for the error occurred. Hence it is not considered as a good
programming practice. The following shows the syntax for except clause with no exception.
Syntax
try:
Suite
except:
Exception_suite #Executes when whatever Exception occurs.
else:
else_suite #Executes 1f there is no Exception in the try block
Example program
#Exception Handling
try:
a=int (input(“First Number; ") )
b=int (input (“Second Number; ") )
result=a/b
print (“Result=" , result)
except :
print (“Error Occured")
else:
print ("Successful Division")
Output
First Number : 2
Second Number : 0
Error Occurred
19
c. Except clause with multiple Exceptions
This is used when we want to give multiple exceptions in one except statement. The
following shows the syntax of the except clause with multiple exceptions.
Syntax
try:
suite
except (Exceptionl [, Exception2 [, . . . ExceptionN] ]]):
Exception_suite #Executes when whatever Exception specified occurs.
else:
else _suite # Executes if there 1s no Exception in the try block.
Example program
# Exception Handling
try:
a=int (input ("First Number: "))
b=int (input ("Second Number: "))
result=a/b
print ("Result=",result)
except (ZeroDivisionError , TypesError):
print ("Error Occured")
else:
print(“Successful Division")
Output
First Number: 10
Second Number: 0
Error Occurred
d. Try...finally
A finally block can be used with a try block. The code placed in the finally block is executed
no matter exception is caused or caught. We cannot use except clause and finally clause
together with a try block. It is also not possible to use else clause and finally together with a
try block. The following gives the syntax for a try..finally block.
20
Syntax
try:
suite
finally:
finally_suite #Executed always after the try block.
Example program 1
#Exception Handling
try:
a=int (input ("First Number: "))
b=int (input ("Second Number: "))
result=a/b
print ("Result=" , result)
finally:
print (“Executed Always")
Output
First Number :20
Second Number: 0
Executed Always
Traceback (most recent call last):
File "main.py" Line 5, in <module>
result=a/b
ZeroDivisionError: integer division or modulo by zero
21
Syntax
Try:
suite
except ExceptionType As argument:
except_suite #Executed when exception occurs.
Example program
def display (a) :
try:
return int (a)
Output
Argument does not contain numbers invalid literal for int () with base 10:‟a‟
10.4.RAISING AN EXCEPTION
We have discussed about raising built-in exceptions. It is also possible to define a new
exception and raise it if needed. This is done using the raise statement. The following shows
the syntax of raise statement. An exception can be a string, a class or an object. Most of the
exceptions that the Python raises are classes, with an argument that is an instance of class.
This is equivalent to throw clause in Java.
Syntax
raise [Exception [, argument [, traceback] ]
Example Program
# Raising an Exception
a=int (input ("Enter the parameter value: "))
try:
if a<=0 :
raise ValueError ("Not a Positive Integer")
except ValuError as err:
print (err)
else:print ("Positive Integer=", a)
22
Output
Enter the parameter value:-9
Not a Positive Integer
10.5.USER-DEFINED EXCEPTION
Python also allows us to create our own exceptions by deriving classes from the standard built-in
exceptions. In the try block, the user-defined exception is raised and caught in the except block.
This is useful when we need to provide more specific information when an exception is caught.
The following shows an example for user-defined exception.
Example Program
# define Python user-defined exceptions
class Error (Exception):
“” "Base class for other exceptions""”
pass
class ValueTooSmallError (Error):
“” "Raised when the input value is too small"""
pass
class Value TooLargeError (Error):
“”” Raised when the input value is too large”””
pass
#Main Program
number=10
while True:
try:
i_num=int (“Input ("Enter a number:”))
if i_num< number:
raise ValueTooSmallError
elif i_ num> number:
raise ValueTooLargeError
break
except ValueTooSmallError:
23
print (This value is too small, try again!")
exceptValueTooLargeError:
print ("This value is too large, try again! ")
print ("Congratulations ! You guessed it correctly. ")
Output
Enter a number: 13
This value is too large, try again!
Enter a number: 9
This value is too small, try again!
Enter a number: 10
Congratulations! You guessed it correctly.
Syntax
Assert Expression [,Arguments]
traceback.
Example Program
#Python Assertions
def sum (a,b) :
sum=a+b
assert (sum>0), "Too low value”
return (sum)
24
a=int (input ("First Number: "))
b=int (input ("Second Number:”))
print (sum (a, b))
Output
First Number: -8
Second Number:-2
Traceback (most recent call last):
File “main.py", line 8, in <module>
print sum (a,b)
File "main.py", line 4, in sum
assert (sum>0), "Too low value"
AssertionError: Too low value
Regular expressions (called REs, or regexes, or regex patterns) are essentially a tiny, highly
specialized programming language embedded inside Python and made available through the re
module. A regular expression helps to match or find other strings or sets of strings, using à
specialized syntax held in a pattern. They are widely used in UNIX world.
The re module raises the exception re.error if an error occurs while compiling or using a regular
expression. There are various characters, which have special meaning when they are used in
regular expression. While dealing with regular expressions, we use raw strings as r „expression.
Syntax
re.match (pattern, string, flags= 0)
where pattern is the regular expression to be matched, string is searched to match the pattern at
the beginning of string, flags are modifiers specified using bitwise OR(|). The re.match() returns
a match object if the matching was success and returns None, if matching was a failure.
Two functions group(n) and groups() of match object are used to get matched expression. The
25
group(n) method returns entire match (or specific subgroup n) and groups() method returns all
matching subgroups in a tuple or empty if there weren't any matches.
Example Program
#Example program for match() function
import re
line=”Python programming is fun”
matchObj= re .match( r‟fun', line, re.M|re.I) if
matchObj:
print ( "match ->matchObj .group () :", matchObj.group ())
else:
print ("No match! !”)
Output
No match! !
The match() function always checks the beginning of the string. Even though the keyword "fun"
is there in the string it is not considered as a match since it does not appear at the beginning of
the string. Consider the below example.
Example Program
#Example program for difference between match () & search () func
import re
line ="Python programming is fun"
26
matchObj = re .match( r'fun', line, re.M|re.I)
if matchobj :
print ( "match -> matchObj .group (): ", matchObj.group ())
else:
print ( "No match! !")
searchObj=re.search(r‟fun‟,line,re.M|re.I) if
searchObj:
print ( "search -> searchObj .group (): ", searchObj.group ( ))
else:
print(“Nothing found!!”)
Output
No match!!
Search->searchObj.group():fun
In the above example, match() function returns nothing while search() function searches the
entire string to find a match.
Syntax
re.sub (pattern, repl, string, max=0)
This method replaces all occurrences of the regular expression pattern in string with repl,
substituting all occurrences. If value for max is provided, it will replace only the number of
occurrences specified in max. This method returns modified string. The following example
shows the application of sub method.
Example program
import re
zipcode=”2004-959-559 # This is zipcode"
# Remove anything other than digits
num = re.sub(r‟\D‟,””,zipcode) print
("Zip Code:”,num)
27
Output
Zip Code: 2004959559
28
Character Classes
29
Special Character Classes
Repetition Cases
findall() METHOD
The findall() method searches all patterns and returns a list. The following shows an example
for findall() method.
Example program
import re
a = "hello 234789 world 63678 ok 1 ok 1115 alpha 88 beta 999g"
print (re.findall ("\d+", a) )
Output
['234789' , '63678', 1','1115', '88', 999]
In the above example, \d is any numeric characters ie 0,1,2,3,4,5,6,7,8,9, "+" represents one or
more previous character. Hence the regular expression searches for only numeric characters.
30
Compile() METHOD
The compile method compiles a regular expression pattern into a regular expression object
which can be used for matching using its match() and search() methods. The syntax of compile
is as follows.
re. compile (pattern, flags=0)
The expression's behaviour can be modified by specifying a flags value. Values can be any of
the following variables, combined using bitwise OR (the | operator). The sequence
prog=re.compile(pattern)
result=prog.match(string)
is equivalent to result = re.match (pattern, string). Similarly the sequence
prog =re.compile(pattern)
result = prog.search(string) is equivalent to result=re.search(pattern,string)
Using re.complie() and saving the resulting regular expression object for reuse is more efficient
when the expression will be used several times in a single progam.
Example program
import re
file = open ("Abc. txt", "r")
text=file.readlines()
file.close()
# compiling the regular expression:
kevword = re. compile (r‟a‟) #searching
the file content line by line: for line in
text:
if keyword . search (line) :
print (line)
Output
#Only lines containing a is displayed
Ram is a boy
Geeta is a girl
31