0% found this document useful (0 votes)
28 views41 pages

3.FPP Class Note Unit-Iii

Uploaded by

NIRANJAN BEHERA
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)
28 views41 pages

3.FPP Class Note Unit-Iii

Uploaded by

NIRANJAN BEHERA
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
You are on page 1/ 41

pointer exists at the beginning of the file.

PYTHON 5 w
It opens the file to write only. It overwrites the file if previously
exists or creates a new one if no file exists with the same name.
UNIT-III The file pointer exists at the beginning of the file.
It opens the file to write only in binary format. It overwrites the file
6 wb if it exists previously or creates a new one if no file exists with the
same name. The file pointer exists at the beginning of the file.

Python File Handling 7 w+


It opens the file to write and read both. It is different from r+ in the
sense that it overwrites the previous file if one exists whereas r+
doesn't overwrite the previously written file. It creates a new file if
Till now, we were taking the input from the console and writing it back to the no file exists. The file pointer exists at the beginning of the file.
console to interact with the user. It opens the file to write and read both in binary format. The file
8 wb+
pointer exists at the beginning of the file.
Sometimes, it is not enough to only display the data on the console. The data to It opens the file in the append mode. The file pointer exists at the
be displayed may be very large, and only a limited amount of data can be 9 a end of the previously written file if exists any. It creates a new file
displayed on the console, and since the memory is volatile, it is impossible to if no file exists with the same name.
recover the programmatically generated data again and again.
It opens the file in the append mode in binary format. The pointer
10 ab exists at the end of the previously written file. It creates a new file
However, if we need to do so, we may store it onto the local file system which is
in binary format if no file exists with the same name.
volatile and can be accessed every time. Here, comes the need of file handling.
It opens a file to append and read both. The file pointer remains at
file handling in python including, creating a file, opening a file, closing a file, 11 a+ the end of the file if a file exists. It creates a new file if no file exists
with the same name.
writing and appending the file, etc.
It opens a file to append and read both in binary format. The file
12 ab+
pointer remains at the end of the file.
Opening a file

Python provides the open() function which accepts two arguments, file name and open() : it is to open a file.
access mode in which the file is accessed. The function returns a file object Example: To open a file named "file.txt" (stored in the same directory) in read
which can be used to perform various operations like reading, writing, etc. mode.
#opens the file file.txt in read mode
fileptr = open("file1.txt","r")
The syntax to use the open() function is given below. if fileptr:
file object = open(<file-name>, <access-mode>, <buffering>) print("file is opened successfully")
The files can be accessed using various modes like read, write, or append.
The following are the details about the access mode to open a file.
Output:
Access
SN Description
mode <class '_io.TextIOWrapper'>
file is opened successfully
It opens the file to read-only. The file pointer exists at the
1 r beginning. The file is by default open in this mode if no access
mode is passed. close() : it is used to close an opened file.
It opens the file to read only in binary format. The file pointer
2 rb it is good practice to close the file once all the operations are done.
exists at the beginning of the file.
It opens the file to read and write both. The file pointer exists at The syntax to use the close() method is given below.
3 r+
the beginning of the file.
4 rb+ It opens the file to read and write both in binary format. The file Ex: fileobject.close()
Example Example

# opens the file file.txt in read mode #open the file.txt in read mode. causes error if no such file exists.
fileptr = open("file.txt","r") fileptr = open("file.txt","r");

if fileptr: #stores all the data of the file into the variable content
print("file is opened successfully") content = fileptr.readline();

#closes the opened file # prints the type of the data stored in the file
fileptr.close() print(type(content))

read() : it is used to read data content of a file. It can also read data in binary format. #prints the content of the file
Syntax: print(content)
fileobj.read(<count>)
#closes the opened file
fileptr.close()
Here, the count is the number of bytes to be read from the file starting from the
beginning of the file. If the count is not specified, then it may read the content of
the file until the end. Output:

<class 'str'>
Consider the following example.
Hi, I am the file and being used as
Example
Looping through the file :
#open the file.txt in read mode. causes error if no such file exists.
fileptr = open("file.txt","r");
By looping through the lines of the file, we can read the whole file.
#stores all the data of the file into the variable content
content = fileptr.read(9); Example
# prints the type of the data stored in the file
#open the file.txt in read mode. causes an error if no such file exists.
print(type(content))
fileptr = open("file.txt","r");
#prints the content of the file
#running a for loop
print(content)
for i in fileptr:
print(i) # i contains each line of the file
#closes the opened file
fileptr.close()
Output:
Output:
Hi, I am the file and being used as
an example to read a
<class 'str'>
Hi, I am file in python.

Read Lines of the file : Writing the file

The readline() method reads the lines of the file from the beginning, i.e., if we To write some text to a file, we need to open the file using the open method with
use the readline() method two times, then we can get the first two lines of the one of the following access modes.
file.
a: It will append the existing file. The file pointer is at the end of the file. It Consider the following example.
creates a new file if no file exists.
Example
w: It will overwrite the file if any file exists. The file pointer is at the beginning of #open the file.txt in read mode. causes error if no such file exists.
the file. fileptr = open("file2.txt","x");
Consider the following example. print(fileptr)
Example 1
#open the file.txt in append mode. Creates a new file if no such file exists.
if fileptr:
fileptr = open("file.txt","a"); print("File created successfully");
Output:
#appending the content to the file File created successfully
fileptr.write("Python is the modern day language. It makes things so simple.")

#closing the opened file


fileptr.close(); Using with statement with files

Example 2 The with statement is useful in the case of manipulating the files.
#open the file.txt in write mode.
fileptr = open("file.txt","w"); Syntax:
with open(<file name>, <access mode>) as <file-pointer>:
#overwriting the content of the file
fileptr.write("Python is the modern day language. It makes things so simple.")
It is always suggestible to use the with statement in the case of files
because, It doesn't let the file to be corrupted.
#closing the opened file
fileptr.close(); Example:
Now, we can check that all the previously written content of the file is overwritten with the
new text
with open("file.txt",'r') as f:
content = f.read();
print(content)
Creating a new file
tell():
The new file can be created by using one of the following access modes
with the function open() method which is used to print the byte number at which the file pointer
exists. Consider the following example.
x: it creates a new file with the specified name. It causes an error a file
Example
exists with the same name.
# open the file file2.txt in read mode
a: It creates a new file with the specified name if no such file exists. It
appends the content to the file if the file already exists with the specified fileptr = open("file2.txt","r")
name.
#initially the filepointer is at 0
print("The filepointer is at byte :",fileptr.tell())
w: It creates a new file with the specified name if no such file exists. It
overwrites the existing file.
#reading the content of the file
content = fileptr.read();
print(txt.read())
#after the read operation file pointer modifies. tell() returns the location of
the fileptr. file_read('test.txt')
print("After reading, the filepointer is at:",fileptr.tell())
Output: Program1: to read a sample file from the present working directory by
The filepointer is at byte : 0 default:
After reading, the filepointer is at 26 fileptr = open(r"c:\\users\\mural\\file1.txt","r")
if fileptr:
seek(): This method which enables us to modify the file pointer position print("file is opened successfully")
externally. content = fileptr.read();
The seek() method accepts two parameters: print(type(content))
offset: It refers to the new position of the file pointer within the file. print(content)
fileptr.close()
from: It indicates the reference position from where the bytes are to be
moved. If it is set to 0, the beginning of the file is used as the reference o/p:
position. If it is set to 1, the current position of the file pointer is used as file is opened successfully
the reference position. If it is set to 2, the end of the file pointer is used as <class 'str'>
the reference position. hello this is a sample file
this is 2nd line
Consider the following example. this is 3rd line or sentence
Example program2: to open a file and reading line by line and then display it.
# open the file file2.txt in read mode fileptr = open("file1.txt","r");
fileptr = open("file2.txt","r") content = fileptr.readline();
print(content)
#initially the filepointer is at 0
print("The filepointer is at byte :",fileptr.tell()) content = fileptr.readline();
print(content)
#changing the file pointer location to 10.
fileptr.seek(10); content = fileptr.readline();
print(content)
#tell() returns the location of the fileptr.
print("After reading, the filepointer is at:",fileptr.tell()) #closes the opened file
fileptr.close()
Output:
o/p:
hello this is a sample file
The filepointer is at byte : 0
After reading, the filepointer is at 10 this is 2nd line
this is 3rd line or sentence
Exercises:
Program3: reading all the content using loop control:
1. Write a Python program to read an entire text file. fileptr = open("file1.txt","r");
def file_read(fname):
txt = open(fname) #running a for loop
for i in fileptr:
print(i) Program7: write a program to input a sample paragraph from user.
else: fileptr = open("file2.txt","a");
print("EOF") fileptr.write(input("enter a sentence"))
o/p: fileptr.close();
hello this is a sample file with open("file2.txt",'r') as f:
this is 2nd line content = f.read();
this is 3rd line or sentence print(content)
EOF fileptr.close()

Program4: for appending more content into file1.txt o/p:


fileptr = open("file1.txt","a"); enter a sentencehi hi hi
#appending the content to the file 345asdhello friendshello89374hello friendhi hi hi
fileptr.write("Python is the modern day language. It makes things so
simple.") (OR)
fileptr = open("file2.txt","a");
#closing the opened file fileptr.write(input("enter a sentence"))
fileptr.close(); fileptr.seek(0) # it rewinds the pointer to the beginning
with open("file2.txt",'r') as f:
fileptr = open("file1.txt","r"); content = f.read();
#running a for loop print(content)
for i in fileptr: fileptr.close()
print(i)
else: program8: write a program to copy the content of file1.txt into file3.txt
print("EOF") fp1 = open("file1.txt","r");
fileptr.close(); fp2=open("file2.txt","w+");
x=fp1.read()
program5: create a new empty file, show error if file already exist. fp2.write(x)
fileptr = open("file2.txt","x"); fp1.seek(0)
print(fileptr) print("content in file1 is: ")
if fileptr: c1=fp1.read()
print("File created successfully"); print(c1)
Output: print("content in file2 is: ")
File created successfully fp2.seek(0)
c2=fp2.read()
Program6: display the content of a file using with statement. print(c2)
with open("file1.txt",'r') as f: fp1.close()
content = f.read(); fp2.close()
print(content)
o/p: o/p:
hello this is a sample file content in file1 is:
this is 2nd line hi friend
this is 3rd line or sentencePython is the modern day language. It makes content in file2 is:
things so simple. hi friend
program9: input a sequence of numbers into a file. enter a paragraphhello madam do you know malayalam
fp1=open("num1.txt","w+") ['hello', 'madam', 'do', 'you', 'know', 'malayalam']
fp1.write(input("enter numbers")) ['olleh', 'madam', 'od', 'uoy', 'wonk', 'malayalam']
fp1.seek(0) the palindromes are:
x=fp1.read() madam
print(x) malayalam
o/p: total no of palindromes 2
enter numbers10 20 30
10 20 30
The file related methods
Program10: write a program to input a sequence of number and find their
sum: The file object provides the following methods to manipulate the files on various
fp1=open("num1.txt","w+") operating systems.
fp1.write(input("enter numbers"))
fp1.seek(0) SN Method Description
x=0 It closes the opened file. The file once closed, it
st=fp1.read() 1 file.close()
can't be read or write any more.
list1=st.split()
2 File.flush() It flushes the internal buffer.
for i in list1:
3 File.next() It returns the next line from the file.
x=x+int(i)
print(x) 4 File.read([size]) It reads the file for the specified size.
o/p: It reads one line from the file and places the file
5 File.readline([size])
enter numbers10 20 30 pointer to the beginning of the new line.
60 It returns a list containing all the lines of the file. It
6 File.readlines([sizehint]) reads the file until the EOF occurs using readline()
Program11: enter a paragraph in to a file. Find how many palindromes function.
exist within the file and then display them. It modifies the position of the file pointer to a
7 File.seek(offset[,from)
fp1=open("sample.txt","w+") specified offset with the specified reference.
fp1.write(input("enter a paragraph")) 8 File.tell()
It returns the current position of the file pointer within
fp1.seek(0) the file.
x=fp1.read() 9 File.write(str) It writes the specified string to a file
list1=x.split() 10 File.writelines(seq) It writes a sequence of the strings to a file.
revlist=list(map(lambda x:x[::-1], list1))
print(list1)
print(revlist)
count=0 Python os module
print("the palindromes are: ")
for x in range(len(list1)): The os module provides us the functions that are involved in file processing
if list1[x]==revlist[x]: operations like renaming, deleting, etc.
count=count+1
print(list1[x]) Let's look at some of the os module functions.
print("total no of palindromes ",count)
Renaming the file
o/p:
The os module provides us the rename() method which is used to rename the #changing the current working directory to new
specified file to a new name. The syntax to use the rename() method is given os.chdir("new")
below.
Deleting directory
1. rename(?current-name?, ?new-name?)
The rmdir() method is used to delete the specified directory.
Example
import os;
The syntax to use the rmdir() method is given below.
#rename file2.txt to file3.txt
os.rename("file2.txt","file3.txt")
1. os.rmdir(?directory name?)
Removing the file
Example
import os;
The os module provides us the remove() method which is used to remove the #removing the new directory
specified file. The syntax to use the remove() method is given below. os.rmdir("new")

1. remove(?file-name?) Python IDEs


IDE stands for Integrated Development Environment is defined as a coding tool that helps
Example to automate the process of editing, compiling, testing, etc.
import os;
#deleting the file named file3.txt There are some Python IDEs which are as follows:
os.remove("file3.txt") PyCharm
Spyder
PyDev
Creating the new directory Atom
Wing
The mkdir() method is used to create the directories in the current working Jupyter Notebook
directory. The syntax to create the new directory is given below. Thonny
Rodeo
Microsoft Visual Studio
1. mkdir(?directory name?) Eric

Example
import os; Object Oriented Programming:
#creating a new directory with the name new
It allows to create their own objects that have methods and attributes.
os.mkdir("new")
The commonly repeated tasks and objects can be defined with OOP to create
code that is more usable.
Changing the current working directory class: the basic way to define an object is using class keyword.
Major principles of OOP system are:
The chdir() method is used to change the current working directory to a specified 1) object
directory. 2) class
3) method
The syntax to use the chdir() method is given below. 4) inheritance
5) polymorphism
6) data abstraction
1. chdir("new-directory")
7) encapsulation
Example
import os; class: A class is a blue print for the object.
It is a virtual entity. It comes into existence when its object is created.
Syntax: * Here x is an object which allows to call a function. Such as x.display(). When
class classname: an object calls its method the object itself is passed as the 1st argument to it. So,
#statements or members x.display() is converted as:
Ex1:Create a class named MyClass, with a property named x: emp.display(x)
class MyClass:
x=5 So, for this reason the 1st argument of the function in the class must be the
object itself referred by self-variable.
Ex4:
Object: It is an instance of a class class lib:
Syntax:
Object name=<class name> (<arguments>)
bookid=1
Ex1: Now we can use the class named myClass to create objects. bookname="a"
Create an object named p1, and print the value of x: bookauthor="b"
p1 = MyClass() bookcost=1.1
print(p1.x) bookqty=1
def accept(self):
ex1: bookid=int(input("enter book id"))
class myclass: self.bookname=input("enter book name")
x=25 self.bookauthor=input("enter book author")
obj=myclass() self.bookcost=float(input("enter book cost"))
print(obj.x) self.bookqty=int(input("enter quantity"))
def display(self):
ex2: print("the book details are\n")
class emp: print(self.bookid,self.bookname,self.bookauthor, self.bookcost,self.bookqty)
empid=1
ename="alok" obj=lib()
def display(self): obj.accept()
print(self.empid,self.ename) obj.display()
obj=emp()
obj.display() ex5:wap to create a class having member data a,b,c and member functions:
obj.empid=2 accept(), sum() and display()
obj.ename="sam" class myclass:
obj.display() a=0
b=0
o/p: c=0
1 alok result=0
2 sam
def accept(self, x,y,z):
self.a=x
Ex3: self.b=y
class emp: self.c=z
id=1 def sum(self):
name="abc" self.result=self.a+self.b+self.c
def display(self): def display(self):
print(self.id, self.name) print("sum is",self.result)
x=emp() obj=myclass()
x.display() n1=int(input("enter 1st no"))
n2=int(input("enter 2nd no"))
o/p: n3=int(input("enter 3rd no"))
1 abc
print("addition is",obj.add())
obj.accept(n1,n2,n3)
obj.sum() o/p:
obj.display() enter 1st no12
enter 2nd no13
addition is 25

self Parameter example3:


The self parameter is a reference to the current instance of the class, and is used to write a program to create a class having members for product no, name, cost
access variables that belongs to the class. and quantity, total amount
methods: input(), calculate(), display()
It does not have to be named self , you can call it whatever you like, but it has to be the
calculate() is to find total amount=cost*quantity
first parameter of any function in the class:

Example: solution:
class person: class product:
def input(obj, name, age): pno=0
obj.name = name pname=" "
obj.age = age cost=qty=amt=0
def input(self,p,q,r,name):
def myfunc(abc): self.pno=p
print("Hello my name is " + abc.name)
self.cost=q
p1=person()
self.qty=r
p1.input(“murali”,32) self.pname=name
p1.myfunc() def calc(self):
self.amt=self.cost*self.qty
when a function is called using the object, actually it is passed as the 1st def display(self):
argument to the function. print("product no is :",self.pno)
Ex: print("product name is :", self.pname)
p1.myfunc() print("product cost is : ",self.cost)
is modified by interpreter as: print("product quantity is :", self.qty)
person.myfunc(p1) print("product amount is :",self.amt)

So, for this reason the 1st argument of the function in class must be the object ob=product()
itself referred by self variable. p=int(input("product no"))
q=int(input("product quantity"))
Example2: input two numbers and perform addition r=int(input("product cost"))
class A: name=input("product name")
def input(self, x,y): ob.input(p,q,r,name)
self.a=x ob.calc() # product.calc(ob)
self.b=y ob.display() # product.display(ob)
def add(self):
return self.a+self.b;
def display(self): o/p:
product no1
print(self.a, self.b); product quantity25
product cost10
obj=A() product namelux
t1=int(input("enter 1st no")) product no is :1
product name is : lux
t2=int(input("enter 2nd no")) product cost is : 25
obj.input(t1,t2) or it means A.input(obj,t1,t2) product quantity is : 10
product amount is : 250 count=0
def _ _init_ _(self):
python constructor: student.count=student.count+1
A constructor is a special type of method which is used to initialize the object s1.student()
members of the class. s2.student()
s3.student()
creating the constructor in python: print(“no. of students are “,student.count)
In python the method _ _init_ _ simulates the constructor of the class. This o/p:
method is called automatically when the class is initiated. no. of students are 3
So, the __init__ function used to initialize the class attributes. So, every class
should have a constructor. Parameterized constructor:
Ex: The constructor needs parameters to be passed when it is invoked.
class emp:
def __init __(self, name, id): Example1:
self.id=id Create a class named Person, use the __init__() function to assign values for
self.name=name name and age:
def display(self): class Person:
print(self.id, self.name) def __init__(self, name, age):
emp1=emp(“john”,101) self.name = name
emp2=emp(“David”,102) self.age = age
emp1.display()
def myfunc(self):
emp2.display()
print("Hello my name is " + self.name)
o/p: p1 = Person("murali", 32)
101 john p1.myfunc()
102 david
example2: write a program to store N persons details using class concept.
Constructors can be of two types: class student:
1) non-parameterized constructor def __init__(self,name,age):
2) parameterized constructor self.name=name
self.age=age
# def display(self):
Non-parameterized constructor: # print(self.name,self.age)
A constructor invoked without parameters during declaring an object. list1=[]
Example1:
class student: for i in range(1,4):
n=input("enter name")
def __init__(self):
a=int(input("enter age"))
print(“it is not parametrised constructor”) # obj=student(n,a)
def show(self, name): list1.append(student(n,a))
print(“hello”,name) for obj in list1:
s1=student() print(obj.name,obj.age)
s1.show(“john”)
o/p: o/p:
This is not a parametrized constructor enter nameaa
enter age1
Hello John enter namebb
enter age2
Example2: enter namecc
Counting the no. of objects of a class. enter age3
aa 1
class student: bb 2
cc 3 print("age attribute exist?",hasattr(s,"age"))
o/p:
python built-in class functions: age attribute exist? True
age attribute exist? False
They are:
getattr(obj,name,default)
It is used to access the attribute of the object. built-in class attributes:
setattr(obj,name,value) along with other attributes python also contains some built in class attributes
it is used to set a particular value to the specific attribute of an object. If attribute which provides information about the class. They are accessed using objects.
does not exist, then it would create. They are:
delattr(obj,name) _ _dict_ _
it is used to delete a specific attribute. It is dictionary containing the class’s namespace
hasattr(obj,name) _ _doc_ _
it returns TRUE if the object contains some specific attribute. It contains a string which have the class document
Example1: _ _name_ _
class student: It is used to access the class name.
def __init__(self,name,id ,age): _ _module_ _
self.name=name It is used to access the module in which the class is defined.
self.id=id _ _bases_ _
self.age=age It contains a tuple including all base classes. It is possibly an empty tuple.
s=student("john",101,22)
print(getattr(s,"id")) Example1:
print(getattr(s,"name")) class student:
o/p: def __init__(self,name,age):
101 self.name=name
john self.age=age
def display(self):
example2: print("name %s and age %d"%(self.name,self.age))
class student: s=student("john",21)
def __init__(self,name,id ,age): print(s._ _dict_ _)
self.name=name print(s._ _doc_ _)
self.id=id print(s._ _module_ _)
self.age=age
s=student("alok",101,21) o/p:
setattr(s,"age",25) {'name': 'john', 'age': 21}
print(getattr(s,"name")) None
print(getattr(s,"age")) _ _main_ _
o/p:
alok
25
_ _name_ _ (A Special variable) in Python
Example3: Since there is no main() function in Python, when the command to run a python
class student: program is given to the interpreter, the code that is at level 0 indentation is to be
def __init__(self,name,id ,age): executed. However, before doing that, it will define a few special variables.
self.name=name __name__ is one such special variable. If the source file is executed as the main
self.id=id program, the interpreter sets the __name__ variable to have a value “__main__”.
self.age=age If this file is being imported from another module, __name__ will be set to the
s=student("alok",101,21) module’s name.
print("age attribute exist?",hasattr(s,"age")) __name__ is a built-in variable which evaluates to the name of the current
delattr(s,"age") module. Thus it can be used to check whether the current script is being run on
its own or being imported somewhere else by combining it with if statement, as These are the variables which are common for all instances or objects of a class.
shown below. Example:
Class employes:
Consider two separate files File1 and File2. Count=0
Def __init__(self, name, salary):
# File1.py Self.name=name
Self.salary=salary
print "File1 __name__ = %s" %__name__
Employee.count=employee.count+1
Def displaycount(self):
if __name__ == "__main__":
Print(“total employees”,employee.count)
print "File1 is being run directly"
else: Def display(self):
Print(self.name, self.salary)
print "File1 is being imported"
o/p:
# File2.py

import File1 The count variable is a class variable whose value is shared among all objects of
the class. It can be accessed using class name or using object either inside or
outside the class.
print "File2 __name__ = %s" %__name__
Emp1=employee(“Zam”,2000)
if __name__ == "__main__":
print "File1 is being run directly" Emp2=employee(“mani”,5000)
Emp1.display()
else:
Emp2.display()
print "File1 is being imported"
Print(“total employees “,employee.count)
o/p:
Now the interpreter is given the command to run File1.py.
python File1.py
Output : destructor:
File1 __name__ = __main__ A class can implement a special method __del__() called a destructor. It is
File1 is being run directly invoked when the instance or object of a class is to be destroyed.
Example1:
class point:
And then File2.py is run. def __init__(self, x=1, y=2):
python File2.py self.x=x
Output : self.y=y
File1 __name__ = File1 print("created")
File1 is being imported def __del__(self):
File2 __name__ = __main__ print(point, "destroyed")
File2 is being run directly p1=point()
p2=p1
As seen above, when File1.py is run directly, the interpreter sets the __name__ p3=p1
variable as __main__ and when it is run through File2.py by importing, the print(p1.x,p1.y)
__name__ variable is set as the name of the python script, i.e. File1. Thus, it can del p1
be said that if __name__ == “__main__” is the part of the program that runs print(p2.x,p2.y)
when the script is run from the command line using a command like del p2
python File1.py. print(p3.x,p3.y)
del p3
Class variables: o/p:
created Class baseclass:
12 Body of the baseclass
12 Class derivedclass(baseclass):
Body of the derivedclass
12
Types of inheritance:
<class '__main__.point'> destroyed 1) single inheritance
2) multiple inheritance
The destroyer will be called after the program ended. When all the references to 3) multilevel inheritance
object are deleted.

The __del__ () method is the destructor method which is used for garbage single inheritance:
collection for handling memory management automatically. It is called
automatically when all the references to the object has been deleted. In python, a derived class can inherit base class by just mentioning the base in
By using del keyword we delete the references, there by destructor is invoked the bracket after the derived class name. Consider the following syntax to inherit
automatically. a base class into the derived class.

Example2:
class emp:
def __init__(self):
print("employee initialized: constructor called")
def display(self):
print("display method executing")
def __del__(self):
print("destructor called")

def create_obj():
print("making object") Syntax
inobj=emp()
print("function ends")
class derived-class(base class):
return inobj
<class-suite>
print("calling create_obj function")
example:
outobj=create_obj()
class base:
outobj.display()
def __init__(self, fname, lname):
del outobj
self.firstname = fname
print("end")
self.lastname = lname
def printname(self):
o/p:
print(self.firstname, self.lastname)
calling create_obj function
making object
#Use the base class to create an object, and then execute the #printname
employee initialized: constructor called
method:
function ends
x = Person("John", "Doe")
display method executing
x.printname()
destructor called
class Student(Person):
end
def disp(self):
print(“derived class function”)
python inheritance: x = Student("Mike", "Olsen")
It enables us to define a class that takes all the functionality from parent class. Here the x.printname()
parent class is also called base class and the new class is called derived class. x.disp()
Syntax: o/p:
John Doe print("Animal Speaking")
Mike Olsen
Derived class function #The child class Dog inherits the base class Animal
Example2: class Dog(Animal):
class Animal: def bark(self):
def speak(self): print("dog barking")
print("Animal Speaking")
#child class Dog inherits the base class Animal #The child class Dogchild inherits another child class Dog
class Dog(Animal): class DogChild(Dog):
def bark(self): def eat(self):
print("dog barking") print("Eating bread...")
d = Dog()
d.bark() d = DogChild()
d.speak() d.bark()
d.speak()
o/p: d.eat()
dog barking
Animal Speaking o/p:
dog barking
Animal Speaking
Python Multi-Level inheritance Eating bread...

Multi-level inheritance is archived when a derived class inherits another derived


class. There is no limit on the number of levels up to which, the multi-level
inheritance is archived in python. Python Multiple inheritance
Python provides us the flexibility to inherit multiple base classes in the child
class.

Syntax Syntax

class bclass1: class Base1:


<class-suite> <class-suite>
class dclass2(bclass1): class Base2:
<class suite> <class-suite>
class dclass3(dclass2): .
<class suite> .
.
Example1: class BaseN:
class Animal: <class-suite>
def speak(self):
class Derived(Base1, Base2, ...... BaseN): Output:
<class-suite>
Example True
class Calculation1: False
def Summation(self,a,b):
return a+b; The isinstance (obj, class) method
class Calculation2: The isinstance() method is used to check the relationship between the objects
def Multiplication(self,a,b): and classes. It returns true if the first parameter, i.e., obj is the instance of the
return a*b; second parameter, i.e., class.
class Derived(Calculation1,Calculation2): Consider the following example.
def Divide(self,a,b): Example:
return a/b; class Calculation1:
d = Derived() def Summation(self,a,b):
print(d.Summation(10,20)) return a+b;
print(d.Multiplication(10,20)) class Calculation2:
print(d.Divide(10,20)) def Multiplication(self,a,b):
return a*b;
Output:
class Derived(Calculation1,Calculation2):
30 def Divide(self,a,b):
200 return a/b;
0.5
d = Derived()
print(isinstance(d,Derived))
Output:
The issubclass(sub,sup) method True
The issubclass(sub, sup) method is used to check the relationships between the
specified classes. It returns true if the first class is the subclass of the second Method Overriding
class, and otherwise returns false. When the method name in base class and in derived class are same.
Then while creating object for derived class, by default the method of derived class
Consider the following example. will override the method of base class.
Example
When the parent class method is defined in the child class with some specific
class Calculation1:
implementation, then the concept is called method overriding.
def Summation(self,a,b): We may need to perform method overriding in the scenario where the different definition
return a+b; of a parent class method is needed in the child class.
class Calculation2: Consider the following example to perform method overriding in python.
def Multiplication(self,a,b): Example
return a*b; class Animal:
def speak(self):
class Derived(Calculation1,Calculation2): print("speaking")
def Divide(self,a,b): class Dog(Animal):
return a/b; def speak(self):
print("Barking")
d = Derived() d = Dog()
print(issubclass(Derived,Calculation2)) d.speak()
print(issubclass(Calculation1,Calculation2)) b=Animal()
b.speak()
Animal.speak() Python constructs the order in which it will look for a method in the hierarchy of
Dog.speak() classes. It uses this order, known as MRO, to determine which method it actually
calls.
Output: It is possible to see MRO of a class using mro() method of the class.
Barking
Speaking
Speaking
Barking

Real Life Example of method overriding


class Bank:
def getroi(self): class A:
return 10; def process(self):
print('A process()')
class SBI(Bank):
def getroi(self): class B:
return 7; pass

class ICICI(Bank): class C(A, B):


pass
def getroi(self):
return 8; obj = C()
obj.process()
b1 = Bank() print(C.mro()) # print MRO for class C
b2 = SBI()
b3 = ICICI() The above diagram illustrates hierarchy of classes.
print("Bank Rate of interest:",b1.getroi()); When run, the above program displays the following output:
print("SBI Rate of interest:",b2.getroi()); A process()
print("ICICI Rate of interest:",b3.getroi()); [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
From MRO of class C, we get to know that Python looks for a method
Output: first in class C. Then it goes to A and then to B. So, first it goes to super
class given first in the list then second super class, from left to right order.
Bank Rate of interest: 10
Then finally Object class, which is a super class for all classes.
SBI Rate of interest: 7
ICICI Rate of interest: 8
Case 2
Method Resolution Order (MRO) in Python Now, let’s make it a little more complicated by adding process() method
Method Resolution Order (MRO) is the order in which Python looks for a method to class B also.
in a hierarchy of classes. Especially it plays vital role in the context of multiple class A:
inheritance as single method may be found in multiple super classes. def process(self):
To understand the concept of MRO and its need, lets examine a few cases. print('A process()')

class B:
Case 1 def process(self):
print('B process()')
This is a simple case where we have class C derived from both A and B. When class C(A, B):
method process() is called with object of class C then process() method in class pass
A is called.
obj = C()
obj.process()
Case 4
When you run the above code, it prints the following:
A process() Now, lets change the hierarchy. We create B and C from A and then D from B
Python calls process() method in class A. According to MRO, it searches and C. Method process() is present in both A and C.
A first and then B. So if method is found in A then it calls that method.
However, if we remove process() method from class A then process()
method in class B will be called as it is the next class to be searched
according to MRO.
*The ambiguity that arises from multiple inheritance is handled by
Python using MRO.

Case 3
class A:
def process(self):
In this case, we create D from C and B. Classes C and B have process() method print('A process()')
and as expected MRO chooses method from C. Remember it goes from left to
right. So it searches C first and all its super classes of C and then B and all its class B(A):
super classes. We can observe that in MRO of the output given below. pass

class C(A):
def process(self):
print('C process()')

class D(B,C):
pass

class A: obj = D()


def process(self): obj.process()
print('A process()') Output of the above program is:
C process()
class B: [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class
def process(self): '__main__.A'>, <class 'object'>]
print('B process()')
Ex2:
class C(A, B): class A:
def process(self): def process(self):
print('C process()') print('A process()')

class D(C,B): class B(A):


pass pass

obj = D() class C(A):


obj.process() pass

print(D.mro()) class D(B,C):


pass
Running the above program will produce the following output:
C process() obj = D()
[<class '__main__.D'>, <class '__main__.C'>, <class '__main__.A'>, <class obj.process()
'__main__.B'>, <class 'object'>] print(D.mro())
print('B process()')
o/p:
A process() class C(A, B):
pass
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class
'__main__.A'>, <class 'object'>] obj = C()
obj.process()
When you run the above code, the following error is shown:
When we call process() with an object of class D, it should start with first TypeError: Cannot create a consistent method resolution
Super class – B (and its super classes) and then second super class – C order (MRO) for bases A, B
(and its super classes). If that is the case then we will call process() The problem comes from the fact that class A is a super class for both C and B.
If you construct MRO then it should be like this:
method from class A as B doesn’t have it and A is super class for B. C -> A -> B -> A
However, that is contradictory to rule of inheritance, as most specific Then according to the rule (good head) A should NOT be ahead of B as A is
version must be taken first and then least specific (generic) version. So, super class of B. So new MRO must be like this:
calling process() from A, which is super class of C, is not correct as C is a C -> B -> A
direct super class of D. That means C is more specific than A. So method But A is also direct super class of C. So, if a method is in both A and B classes
must come from C and not from A. then which version should class C call? According to new MRO, the version in B
is called first ahead of A and that is not according to inheritance rules (specific to
This is where Python applies a simple rule that says (known as good
generic) resulting in Python to throw error.
head question) when in MRO we have a super class before subclass Understanding MRO is very important for any Python programmer. I strongly recommend
then it must be removed from that position in MRO. trying more cases until you completely understand how Python constructs MRO. Do not
So the original MRO will be: confuse yourself by taking old way of constructing MRO used in earlier versions of
D -> B -> A -> C -> A Python. It is better to consider only Python 3.
If you include object class also in MRO then it will be:
D -> B-> A -> object -> C -> A -> object METHOD/FUNCTION OVERLOADING:
But as A is super class of C, it cannot be before C in MRO. So, Python Python does not support method overloading. We may overload the methods but
removes A from that position, which results in new MRO as follows: can only use the latest defined method.
D -> B -> C -> A -> object Ex1:
The output of the above program proves that. class A:
def fun1():
print(“sample message1”)
Case 5 def fun1(a):
print(“the data is”,a)
There are cases when Python cannot construct MRO owing to complexity of def fun1(a,b):
hierarchy. In such cases it will throw an error as demonstrated by the following print(“the data are”,a,b)
code. x=A()
x.fun1() //error
x.fun1(10) //error
x.fun1(10,20) //executed
x.fun1(‘A’,’B’) //executed

o/p:
the data are 10 20
the data are A B

class A: ex:
def process(self):
print('A process()')
#!/usr/bin/env python

class B(A): class Human:


def process(self):
def sayHello(self, name=None): def add(datatype, *args):

if name is not None: # if datatype is int


print('Hello ' + name) # initialize answer as 0
else: if datatype =='int':
print('Hello ') answer = 0

# Create instance # if datatype is str


obj = Human() # initialize answer as ''
if datatype =='str':
# Call the method answer =''
obj.sayHello()
# Traverse through the arguments
# Call the method with a parameter for x in args:
obj.sayHello('Guido')
# This will do addition if the
Output: # arguments are int. Or concatenation
# if the arguments are str
Hello answer = answer + x
Hello Guido
print(answer)
ex2;
# First product method. # Integer
# Takes two argument and print their add('int', 5, 6)
# product
def product(a, b): # String
p=a*b add('str', 'Hi ', 'Alok')
print(p)

# Second product method Output:


# Takes three argument and print their
# product 11
def product(a, b, c): Hi Alok
p = a * b*c
print(p) Data abstraction in python
Abstraction is an important aspect of object-oriented programming. In python, we can also
# Uncommenting the below line shows an error perform data hiding by adding the double underscore (___) as a prefix to the attribute
# product(4, 5) which is to be hidden. After this, the attribute will not be visible outside of the class
through the object.
# This line will call the second product method
product(4, 5, 5) Consider the following example.
Output: Example1:
100
class Employee:
__count = 0;
Ex3:
def __init__(self):
However we may use other implementation in python to make the same function Employee.__count = Employee.__count+1
work differently i.e. as per the arguments. def display(self):
Program: print("The number of employees",Employee.__count)
# Function to take multiple arguments emp = Employee()
emp2 = Employee() self.y = y
try:
print(emp.__count) p1 = Point(1, 2)
p2 = Point(3, 4)
finally:
emp.display() print(p1+p2)

Output:
The number of employees 2 Output
AttributeError: 'Employee' object has no attribute '__count'
Traceback (most recent call last):
File "F:/NETJS/NetJS_2017/Python/Test/Test.py", line 9, in <module>
OPERATOR OVERLOADING: print(p1+p2)
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'

What is operator overloading


For all operators internally Python defines methods to provide functionality for
Operator overloading as evident from the name itself means the ability to overload the
operator to provide extra functionality in addition to its real operational meaning. For those operators. For example functionality for ‘+’ operator is provide by special
example ‘+’ operator which is used with numbers to perform addition operation. But ‘+’ method __add__(). Whenever ‘+’ operator is used internally __add__() method
operator when used with two strings concatenate those Strings and merge two lists when is invoked to do the operation.
used with lists in Python. It is possible because ‘+’ operator is overloaded in str and list
class to provide extended functionality. Internal methods that provide functionality for the operators are known as magic
methods in Python. These magic methods are automatically invoked when
Python Operator overloading for ‘+’ operator corresponding operators are used.

#using + operator with integers to add them Overloading ‘+’ operator to work with custom objects
print(5 + 7)
#using + operator with Strings to concatenate them
print('hello ' + 'world') class Point:
a = [1, 2, 3] def __init__(self, x, y):
b = [4, 5, 6] self.x = x
# using + operator with List to concatenate them self.y = y
print(a + b) def __add__(self, other):
return self.x + other.x, self.y + other.y
Output p1 = Point(1, 2)
p2 = Point(3, 4)
12 print(p1+p2)
hello world
[1, 2, 3, 4, 5, 6]
Output
When is Operator overloading required? (4, 6)

if you want to use operator with custom objects. For example if you want to use What actually happens is that, when you do p1 + p2, Python will call p1.__add__(p2)
‘+’ operator with your custom class objects. which in turn is Point.__add__(p1,p2). Similarly, we can overload other operators as
well. The special function that we need to implement is tabulated below.
In the example there is a class Point with two variables x and y. Two objects of
Point class are instantiated and you try to add those objects with the intention to
Operator Overloading Special Functions in Python
add the data (p1.x + p2.x) and (p1.y + p2.y) of these two objects.
Operator Expression Internally
class Point: Addition p1 + p2 p1.__add__(p2)
def __init__(self, x, y):
self.x = x Subtraction p1 - p2 p1.__sub__(p2)
Multiplication p1 * p2 p1.__mul__(p2) __ifloordiv__(self, Division with integer result, discarding any
//=
Power p1 ** p2 p1.__pow__(p2) other) fractional part

Division p1 / p2 p1.__truediv__(p2) __ipow__(self,


**= Return a to the power b, for a and b numbers.
other)
Floor Division p1 // p2 p1.__floordiv__(p2)
__imatmul__(self,
Remainder (modulo) p1 % p2 p1.__mod__(p2) @= Matrix Multiplication.
other)
Bitwise Left Shift p1 << p2 p1.__lshift__(p2)
Bitwise Right Shift p1 >> p2 p1.__rshift__(p2)
Bitwise AND p1 & p2 p1.__and__(p2)
Overloading ‘*’ operator in Python
Bitwise OR p1 | p2 p1.__or__(p2) class Point:
Bitwise XOR p1 ^ p2 p1.__xor__(p2) def __init__(self, x):
self.x = x
Bitwise NOT ~p1 p1.__invert__() #overriding magic method
Matrix Multiplication. @ __matmul__(self, other) def __mul__(self, other):
return self.x * other.x

p1 = Point(12)
Comparison Operator Overloading in Python p2 = Point(5)
print(p1*p2)
Operator Expression Internally
Less than p1 < p2 p1.__lt__(p2) Output
Less than or equal to p1 <= p2 p1.__le__(p2)
Equal to p1 == p2 p1.__eq__(p2) 60

Not equal to p1 != p2 p1.__ne__(p2)


Overloading comparison operator (>) in Python
Greater than p1 > p2 p1.__gt__(p2)
Greater than or equal to p1 >= p2 p1.__ge__(p2) class Person:
def __init__(self, name, salary):
self.name = name
self.salary = salary
Magic methods for compound assignment operators #overriding magic method
def __gt__(self, other):
return self.salary > other.salary
Operator Magic Method Description obj1 = Person('John', 4500)
__iadd__(self, obj2 = Person('Natasha', 6000)
+= Addition assignment print(obj1.name, 'earns more than', obj2.name, '-', obj1 > obj2)
other)
Output
–=
__isub__(self, John earns more than Natasha – False
Subtraction assignment
other)
__imul__(self,
*= Multiplication assignment
other)
MATRIX PROGRAMS:
__itruediv__(self, Add Two Matrices
/= Division assignment
other) X = [[1,2,3], [4,5,6], [7,8,9]]
__imod__(self, Y = [[10,11,12],
%= Modulus assignment [13,14,15],
other)
[16,17,18]]
Result = [[0,0,0],
[0,0,0],
[0,0,0]]
# iterate through rows
for i in range(len(X)):
# iterate through columns
for j in range(len(X[0])):
result[i][j] = X[i][j] + Y[i][j]
for r in result:
print(r)

O/P:

Transpose a Matrix
X = [[1,2],
[4,5],
[7,8]]
Result = [[0,0,0],
[0,0,0]]
# iterate through rows
for i in range(len(X)):
for j in range(len(X[0])):
result[j][i] = X[i][j]

for r in result:
Multiply Two Matrices print(r)
X = [[1,2,3], Output:
[4,5,6],
[7,8,9]]
Y = [[10,11,12],
[13,14,15],
[16,17,18]]

Result = [[0,0,0],
[0,0,0],
[0,0,0]]

# iterate through rows of X


for i in range(len(X)):
for j in range(len(Y[0])):
for k in range(len(Y)):
result[i][j] += X[i][k] * Y[k][j] Sort Words in Alphabetic Order
for r in result: my_str = input("Enter a string: ")
print(r) # breakdown the string into a list of words
words = my_str.split()
# sort the list
words.sort()
# display the sorted words
for word in words:
print(word)

NumPy Arrays
NumPy is a package for scientific computing which has support for
a powerful N-dimensional array object.

NumPy provides multidimensional array of numbers (which is actually an object).


Let's take an example:

import numpy as np
a = np.array([1, 2, 3])
print(a) # Output: [1, 2, 3]
print(type(a)) # Output: <class 'numpy.ndarray'>

As you can see, NumPy's array class is called ndarray.


Remove Punctuation from a String
1. Array of integers, floats and complex Numbers
# define punctuation
punctuation = '''''!()-[]{};:'"\,<>./?@#$%^&*_~''' import numpy as np
# take input from the user
my_str = input("Enter a string: ") A = np.array([[1, 2, 3], [3, 4, 5]])
# remove punctuation from the string print(A)
no_punct = ""
for char in my_str: A = np.array([[1.1, 2, 3], [3, 4, 5]]) # Array of floats
if char not in punctuation: print(A)
no_punct = no_punct + char
# display the unpunctuated string A = np.array([[1, 2, 3], [3, 4, 5]], dtype = complex) # Array of complex numbers
print(no_punct) print(A)

When you run the program, the output will be:

[[1 2 3]
[3 4 5]]

[[1.1 2. 3. ]
[3. 4. 5. ]]

[[1.+0.j 2.+0.j 3.+0.j]


[3.+0.j 4.+0.j 5.+0.j]]

2. Array of zeros and ones

import numpy as np

zeors_array = np.zeros( (2, 3) )


print(zeors_array)
import numpy as np
''' A=np.arange(10)
Output: print(A)
[[0. 0. 0.]
B=np.arange(2, 10, dtype=float)
[0. 0. 0.]]
'''
print(B)
C=np.arange(2, 3, 0.1)
ones_array = np.ones( (1, 5), dtype=np.int32 ) # specifying dtype print(C)
print(ones_array) o/p:
# Output: [[1 1 1 1 1]] [0 1 2 3 4 5 6 7 8 9]
[2. 3. 4. 5. 6. 7. 8. 9.]
[2. 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9]
Here, we have specified dtype to 32 bits (4 bytes).

Hence, this array can take values from -2-31 to 2-31-1.


Shape of NumPy array
arange():
A shape is a tuple of the format (n_rows, n_cols)
It will create arrays with regularly incrementing values.
Ex1:
np.arange() can generate a sequence of numbers given the start and end. x=np.array([np.arange(0,5), np.arange(5,10)])
print(x)
## Generated a NumPy array from 0 to 4 print(x.shape)
print(np.arange(0,5)) o/p:
[[0 1 2 3 4]
[5 6 7 8 9]]
Ex1: (2, 5)
import numpy as np
A = np.arange(4) Ex2:
print('A =', A) x=np.array([np.arange(0,5,.5), np.arange(5,10)])
B = np.arange(12) print(x)
print('B =', B) print(x.shape)
o/p: o/p:
A = [0 1 2 3] [array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
B = [ 0 1 2 3 4 5 6 7 8 9 10 11] array([5, 6, 7, 8, 9])]
(2,)
Ex2:
import numpy as np
Addition of Two Matrices
A = np.arange(4)
print('A =', A) We use + operator to add corresponding elements of two NumPy matrices.
B = np.arange(12).reshape(2,6) import numpy as np
print('B =', B)
o/p: A = np.array([[2, 4], [5, -6]])
A = [0 1 2 3] B = np.array([[9, -3], [3, 6]])
B = [[ 0 1 2 3 4 5] C=A+B # element wise addition
print(C)
[ 6 7 8 9 10 11]]
'''
Ex3: Output:
[[11 1] Ex1:
[ 8 0]] import numpy as np
'''
A= np.array([np.arange(0,3), np.arange(3,6)])
B = np.array([np.arange(0,2), np.arange(2,4), np.arange(4,6)])

Subtraction ## Print shapes and matrices


print("Matrix1: n ", A)
print("Matrix1 shape: n", A.shape)
Subtraction is similar to addition. We just need to change the operation from print("Matrix2: n ",B)
addition to subtraction. print("Matrix2 shape: n", B.shape)

Ex: ## Multiply each element by 2 in mat_2d_1 and print it


import numpy as np print("Scalar Product: n ")
print(A * 2)
## Generate two matrices
## Find product of two matrices above using dot product
A= np.array([np.arange(0,3), np.arange(3,6)]) print("Dot Product: n ")
B = np.array([np.arange(6,9), np.arange(9,12)]) print(np.dot(A, B))
o/p:
print("Matrix1: n ", A) Matrix1: n
print("Matrix2: n ", B) [[0 1 2]
[3 4 5]]
Matrix1 shape: n (2, 3)
## Subtract 1 from each element in mat_2d_1 and print it Matrix2: n
print("Scalar subtraction: n ", A - 1) [[0 1]
[2 3]
[4 5]]
## Subtract two matrices above elementwise Matrix2 shape: n (3, 2)
print("Element wise subtraction of two matrices of same size: n ") Scalar Product: n
print(A- B) [[ 0 2 4]
o/p: [ 6 8 10]]
Matrix1: n Dot Product: n
[[10 13]
[[0 1 2] [28 40]]
[3 4 5]]
Matrix2: n
[[ 6 7 8]
[ 9 10 11]] Transpose of a Matrix
Scalar subtraction: n
[[-1 0 1] We use numpy.transpose to compute transpose of a matrix.
[ 2 3 4]]
Element wise subtraction of two matrices of same size: n
import numpy as np
[[-6 -6 -6]
[-6 -6 -6]] A = np.array([[1, 1], [2, 1], [3, -3]])
print(A.transpose())

'''
Product Output:
[[ 1 2 3]
[ 1 1 -3]]
Two types of multiplication or product operation can be done on NumPy matrices '''

 Scalar product: A scalar value is multiplied with all elements of a matrix


 Dot product: This is the product of two matrices as per the rules of matrix
multiplication.
Python Exception Exception Handling in Python using Try Block:
Here the code which might have exception have to place in try block. The
Types of errors
keywords used are try, except, finally
Errors in your Python programs can be categorized into
at least two types- Syntax:
try:
 Syntax errors
 Exceptions suspicious code

Syntax errors or compile time errors are the errors due to which your program except exception1:
fails to compile. Such errors are detected at the compile time itself, file name, block1 code
line number and error description is displayed so you know where to look for the except exception2:
error and how to correct it.
block2 code
For example if you don’t write colon after if statement- Finally:

def check_equality(str1, str2):


if str1 > str2 Other code
print(str1, 'is greater than', str2)
Ex1: example of ZeroDivisionError
try:
Exceptions x = int(input('Enter the first number: '))
y = int(input('Enter the second number: '))
Even if a statement or expression is syntactically correct it may result in an error at run print(x/y)
time. Errors detected during runtime are called exceptions and they disrupt the normal except ZeroDivisionError:
execution flow of the program.
print ('The second number cannot be zero!')
o/p:
For example in the following program there is an attempt to divide by zero which results in Enter the first number: 10
ZeroDivisionError at runtime. Enter the second number: 0
The second number cannot be zero!
def divide_num(num1, num2):
return num1/num2
Ex2:example of ZeroDivisionError
divide_num(10, 0) try:
x = int(input('Enter the first number: '))
An exception can be defined as an abnormal condition in a program y = int(input('Enter the second number: '))
resulting in the disruption in the flow of the program. z=(x/y)
print("a/b = %d"%z)
Exceptions are 5 types: except ZeroDivisionError:
1) Zero Division Exception print("cannot divide by zero")
2) Name Error else:
3) Indentation Error print("division successful")
4) IO Error print("end of program")
5) EOF Error o/p:
Enter the first number: 10 except IOError:
Enter the second number: 2
a/b = 5 print("the file error")
division successful else:
end of program
print("let us read")
finally:
ex3: Example of IOError fileptr.close()
try: #try block print("file closed")
fileptr=open("file7.txt","r")
except IOError: #except block
o/p:
print("the file is not found") this is file seven
else: #else block let us read
print("the file opened successfully") file closed
fileptr.close()
print("end of program") #other code block ex3: Example of IOError
o/p: try:
the file opened successfully fileptr=open("file7.txt","r")
end of program
fileptr.write("sample text")
except IOError:
Finally: print("the file error")
A final block will be executed regardless of an error. It is an optional else:
clause. It executes generally for external resources. It will execute even if print("let us read")
exception exist or else not exist. finally:
Ex1: Example of IOError fileptr.close()
try: print("file closed")
fileptr=open("file1.txt","r")
except IOError: o/p:
print("the file is not found") the file error
else: file closed

print("the file opened successfully")


fileptr.close() ex4: Example of ValueError
finally: def inputnumber():
print("i am finally") try:
print("end of program") r=int(input("enter a no"))
except ValueError:
o/p: print("wrong entry")
the file is not found else:
i am finally print("right entry")
end of program finally:
print("end of try")
ex2: Example of IOError inputnumber()
try:
fileptr=open("file7.txt","r") o/p:
#fileptr.write("sample text") enter a noAA
f=fileptr.read() wrong entry
print(f) end of try
ex5: Example of ValueError ex2: example of ZeroDivisionError
def inputnumber(): try:
while(True): a=int(input("enter a"))
try: b=int(input("enter b"))
r=int(input("enter a no")) if(b==0):
except ValueError: raise ZeroDivisionError;
print("wrong entry") else:
continue print("a/b =",a/b)
else: except ZeroDivisionError:
print("right entry") print("b cannot be 0")
break
finally: o/p:
print("end of exceptions") enter a12
inputnumber() enter b0
b cannot be 0
o/p:
enter a noA
wrong entry
end of exceptions
Some important built in exceptions are:
enter a noA AttributeError, EOFError, FloatingPointError, ImportError, IndexError,
wrong entry KeyError,MemoryError, NameError, OverlfowError, RuntimeError,
end of exceptions SyntaxError, IndentationError, TypeError, ValueError, ZeroDivisionError
enter a no2
right entry
end of exceptions Python Custom Exceptions/
User Defined Exception:
raise:
An exception can be raised using raise clause in python. In python we can create custom exceptions by creating a new class. This
Syntax: exception class ahs to be derived either directly or indirectly.
Raise exception_class <value> Ex1:
class error(Exception):
Ex1: example of ValueError pass
try: class Derived_smallvalue(error):
age=int(input("enter age")) pass
if(age<18): class Derived_largevalue(error):
raise ValueError; pass
else: n=10
print("the age is valid") while True:
except ValueError: try:
print("the age is invalid") i=int(input("enter no"))
finally: if(i<n):
print("end of exceptions") raise Derived_smallvalue
elif(i>n):
o/p: raise Derived_largevalue
enter age14 break
the age is invalid
except Derived_smallvalue: Here, we used re.match() function to search pattern within the test_string. The
print("it is less than 10") method returns a match object if the search is successful. If not, it returns None.
except Derived_largevalue:
print("it is greater than 10") Meta Characters
print("congrats, it is", 10)
Metacharacters are characters that are interpreted in a special way by a RegEx engine.
Here's a list of metacharacters:
o/p:
enter no 11
[] . ^ $ * + ? {} () \ |
It is greater than 10
[] - Square brackets

Python RegEx Square brackets specifies a set of characters you wish to match.

A Regular Expression (RegEx) is a sequence of characters that defines a search pattern.


For example,
Expression String Matched?
^a...s$ a 1 match
The above code defines a RegEx pattern. The pattern is: any five letter string starting ac 2 matches
with a and ending with s. [abc]
Hey Jude No match
abc de ca 5 matches
A pattern defined using RegEx can be used to match against a string.

Here, [abc] will match if the string you are trying to match contains any of the a,
Expression String Matched?
b or c.
abs No match
alias Match You can also specify a range of characters using - inside square brackets.
^a...s$ abyss Match
Alias No match  [a-e] is the same as [abcde].
An abacus No match  [1-4] is the same as [1234].
 [0-39] is the same as [01239].

Python has a module named re to work with RegEx. Here's an example: You can complement (invert) the character set by using caret ^ symbol at the
start of a square-bracket.
Ex:
import re  [^abc] means any character except a or b or c.
 [^0-9] means any non-digit character.
pattern = '^a...s$'  . - Period
test_string = 'abhas'  A period matches any single character (except newline '\n').
result = re.match(pattern, test_string)
Expression String Matched?
if result:
print("Search successful.") a No match
else: ac 1 match
..
print("Search unsuccessful.") acd 1 match
o/p: acde 2 matches (contains 4 characters)
Search Successful
^- Caret ?- Question Mark
The caret symbol ^ is used to check if a string starts with a certain The question mark symbol ? matches zero or one occurrence of the
character. pattern left to it.

Expression String Matched? Expression String Matched?


a 1 match mn 1 match
^a abc 1 match man 1 match
bac No match ma?n maaan No match (more than one a character)
abc 1 match main No match (a is not followed by n)
^ab
acb No match (starts with a but not followed by b) woman 1 match

$- Dollar {}- Braces
The dollar symbol $ is used to check if a string ends with a certain Consider this code: {n,m}. This means at least n, and at most m
character. repetitions of the pattern left to it.

Expression String Matched? Expression String Matched?


a 1 match abc dat No match
a$ formula 1 match abc daat 1 match (at daat)
a{2,3}
cab No match aabc daaat 2 matches (at aabc and daaat)
aabc daaaat 2 matches (at aabc and daaaat)
*- Star
The star symbol * matches zero or more occurrences of the pattern left
 Let's try one more example. This RegEx [0-9]{2, 4} matches at least 2 digits
to it.
but not more than 4 digits

Expression String Matched?


Expression String Matched?
mn 1 match
ab123csde 1 match (match at ab123csde)
man 1 match
[0-9]{2,4} 12 and 345673 2 matches (at 12 and 345673)
ma*n maaan 1 match
1 and 2 No match
main No match (a is not followed by n)

woman 1 match |- Alternation
Vertical bar | is used for alternation (or operator).
+ - Plus
The plus symbol + matches one or more occurrences of the pattern left Expression String Matched?
to it.
cde No match
a|b ade 1 match (match at ade)
Expression String Matched?
acdbea 3 matches (at acdbea)
mn No match (no a character)
man 1 match
 Here, a|b match any string that contains either a or b
ma+n maaan 1 match () - Group
main No match (a is not followed by n) Parentheses () is used to group sub-patterns. For example, (a|b|c)xz match
woman 1 match any string that matches either a or b or c followed by xz

Expression String Matched? Expression String Matched?
ab xz No match PythonRegEx No match
(a|b|c)xz abxz 1 match (match at abxz)
axz cabxz 2 matches (at axzbc cabxz)
\d - Matches any decimal digit. Equivalent to [0-9]
Special Sequences:
Expression String Matched?
\A - Matches if the specified characters are at the start of a string. 12abc3 3 matches (at 12abc3)
\d
Python No match
Expression String Matched?
the sun Match
\Athe
In the sun No match \D - Matches any non-decimal digit. Equivalent to [^0-9]

\b - Matches if the specified characters are at the beginning or end of a word. Expression String Matched?
1ab34"50 3 matches (at 1ab34"50)
Expression String Matched? \D
1345 No match
football Match
\bfoo a football Match
afootball No match w - Matches any alphanumeric character (digits and alphabets). Equivalent to [a-
the foo Match zA-Z0-9_]. By the way, underscore _ is also considered an alphanumeric character.
foo\b the afoo test Match
the afootest No match Expression String Matched?
12&": ;c 3 matches (at 12&": ;c)
\w
\B- Opposite of \b. Matches if the specified characters are not at the beginning or %"> ! No match
end of a word.

Expression String Matched? \W - Matches any non-alphanumeric character. Equivalent to [^a-zA-Z0-9_]


football No match
\Bfoo a football No match Expression String Matched?
afootball Match 1a2%c 1 match (at 1a2%c)
\W
the foo No match Python No match
foo\B
the afoo test No match
the afootest Match
RegEx Functions

The re module offers a set of functions that allows us to search a string for a match:

\s - Matches where a string contains any whitespace character. Equivalent to [


\t\n\r\f\v]. Function Description
findall Returns a list containing all matches
Expression String Matched? Returns a Match object if there is a match anywhere in the
search
\s Python RegEx 1 match string
split Returns a list where the string has been split at each match result = re.split(pattern, string)
print(result)
sub Replaces one or many matches with a string
# Output: ['Twelve:', ' Eighty nine:', '.']

re.findall()
re.sub()
The re.findall() method returns a list of strings containing all matches.
The syntax of re.sub() is:
Example 1: re.findall()
re.sub(pattern, replace, string)

# Program to extract numbers from a string The method returns a string where matched occurrences are replaced with the content of
replace variable.
import re
Example 3: re.sub()
string = 'hello 12 hi 89. Howdy 34'
pattern = '\d+'
# Program to remove all whitespaces
result = re.findall(pattern, string) import re
print(result)
# multiline string
# Output: ['12', '89', '34'] string = 'abc 12\
de 23 \n f45 6'

# matches all whitespace characters


Example
pattern = '\s+'

import re # empty string


txt = "The rain in Spain" replace = '~'
x = re.findall("ai", txt)
print(x) new_string = re.sub(pattern, replace, string)
o/p: print(new_string)
o/p:
['ai', 'ai']
abc~12de~23~f45~6

If the pattern is no found, re.sub() returns the original string.


re.split()
re.search()
The re.split method splits the string where there is a match and returns a list of strings
where the splits have occurred.
The re.search() method takes two arguments: a pattern and a string. The method looks
for the first location where the RegEx pattern produces a match with the string.
Example 2: re.split()
If the search is successful, re.search() returns a match object; if not, it returns None.
import re

string = 'Twelve:12 Eighty nine:89.' match = re.search(pattern, str)


pattern = '\d+'
Ex () Capture and group

import re
Special Sequences
string = "Python is fun"
A special sequence is a \ followed by one of the characters in the list below, and has a
# check if 'Python' is at the beginning special meaning:
match = re.search('\APython', string)

if match: Character Description Example Try it


print("pattern found inside the string") Returns a match if the
else: \A specified characters are at "\AThe"
print("pattern not found") the beginning of the string
Returns a match where the
# Output: pattern found inside the string
specified characters are at r"\bain"
\b
the beginning or at the end of r"ain\b"
Ex:
a word
import re
txt = "The rain in Spain" Returns a match where the
x = re.search("Portugal", txt) specified characters are
r"\Bain"
print(x) \B present, but NOT at the \B
r"ain\B"
beginning (or at the end) of a
o/p: word
None Returns a match where the
\d string contains digits "\d" \d
ex: (numbers from 0-9)
import re
txt = "The rain in Spain" Returns a match where the
x = re.search("Spain", txt) \D string DOES NOT contain "\D" \D
print(x) digits
o/p: Returns a match where the
<re.Match object; span=(12, 17), match='Spain'> \s string contains a white space "\s" \s
character
Returns a match where the
Metacharacters \S string DOES NOT contain a "\S" \S
white space character

Metacharacters are characters with a special meaning:

Character Description Example

[] A set of characters "[a-m]"

\ Signals a special sequence (can also be used to escape special characters) "\d" Returns a match where the
. Any character (except newline character) "he..o" string contains any word
\w characters (characters from "\w" \w
^ Starts with "^hello"
a to Z, digits from 0-9, and
$ Ends with "world$" the underscore _ character)
* Zero or more occurrences "aix*" Returns a match where the
+ One or more occurrences "aix+" \W string DOES NOT contain "\W" \W
{} Exactly the specified number of occurrences "al{2}" any word characters
| Either or "falls|stays" \Z Returns a match if the "Spain\Z" \Z
specified characters are myit = iter(mytuple)
at the end of the string
print(next(myit))
print(next(myit))
Sets print(next(myit))
o/p:
A set is a set of characters inside a pair of square brackets [] with a special meaning: apple
banana
Character Description Example
cherryTry it
Returns a match where one of the specified characters (a, r, or
[arn]
n) are present
example2:
Returns a match for any lower case character, alphabetically
[a-n]
between a and n Strings are also iterable objects, containing a sequence of characters:
[^arn] Returns a match for any character EXCEPT a, r, and n
Returns a match where any of the specified digits ( 0, 1, 2, or 3) mystr = "banana"
[0123]
are present myit = iter(mystr)
[0-9] Returns a match for any digit between 0 and 9
print(next(myit))
[0-5][0-9] Returns a match for any two-digit numbers from 00 and 59
print(next(myit))
Returns a match for any character alphabetically between a print(next(myit))
[a-zA-Z]
and z, lower case OR upper case
print(next(myit))
In sets, +, *, ., |, (), $,{} has no special meaning, so [+] means:
[+]
return a match for any + character in the string
print(next(myit))
print(next(myit))
o/p:
Match(): b
It contains: span(), string(), group() a
span() : It returns the tuple containing the starting and end position of the match. n
string() : it returns a string passed into the function a
group() : the part of the string is returned where the match is found. n
a

Looping Through an Iterator


ITERATOR:
Python Iterators are objects that can be iterated upon. We can also use a for loop to iterate through an iterable object:

What are iterators in Python? Example1: Iterate the values of a tuple:


Iterators are everywhere in Python. They are elegantly implemented within for
loops, comprehensions, generators etc. but hidden in plain sight. Iterator in
mytuple = ("apple", "banana", "cherry")
Python is simply an object that can be iterated upon.
for x in mytuple:
print(x)
Python iterator object must implement two special methods, __iter__() and
o/p:
__next__(), collectively called the iterator protocol. apple
An object is called iterable if we can get an iterator from it. Most of built-in banana
containers in Python like: list, tuple, string etc. are iterables. cherry

Example1: The __iter__() method acts similarly, we can do same operations , but it must always
mytuple = ("apple", "banana", "cherry") return the iterator object itself.
To prevent the iteration, we can use the StopIteration statement.

Example2: Create an iterator that returns numbers, starting with 1, and each In the __next__() method, we can add a terminating condition to raise an error.
sequence will increase by one (returning 1,2,3,4,5 etc.):
Example1:without StopIteration
class MyNumbers: class MyNumbers:
def __iter__(self): def __iter__(self):
self.a = 1 self.a = 1
return self return self
def __next__(self):
x = self.a def __next__(self):
self.a += 1 if self.a<=5:
return x x = self.a
self.a += 1
myobj= MyNumbers() return x
myiter = iter(myobj) myobj= MyNumbers()
print(next(myiter)) myiter = iter(myobj)
print(next(myiter))
print(next(myiter)) for i in range(10):
print(next(myiter)) print(next(myiter), end=",")
print(next(myiter)) o/p:
1,2,3,4,5,None,None,None,None,None,
o/p:
1
2
3
Example2:
4
5 Stop after 10 iterations:
Example3:
class MyNumbers: class MyNumbers:
def __iter__(self): def __iter__(self):
self.a = 1 self.a = 1
return self return self
def __next__(self): def __next__(self):
x = self.a
self.a += 1
if self.a <= 10:
return x x = self.a
self.a += 1
myobj= MyNumbers() return x
myiter = iter(myobj) else:
raise StopIteration
for i in range(10):
print(next(myiter), end=",") myclass = MyNumbers()
o/p:
myiter = iter(myclass)
1,2,3,4,5,6,7,8,9,10,
for x in myiter:
print(x,end=" ")

o/p:
******StopIteration 1 2 3 4 5 6 7 8 9 10
yield vs. return
The yield statement is responsible for controlling the flow of the generator
function.
GENERATOR
It pauses the function execution by saving all states and yielded to the caller.
Generators are the functions that return the traversal object and used to create iterators. Later it resumes execution when a successive function is called.
It traverses the entire items at once.

There is a lot of complexity in creating iteration in Python; we need to implement We can use the multiple yield statement in the generator function.
__iter__() and __next__() method to keep track of internal states. It is a lengthy process
to create iterators. The return statement returns a value and terminates the whole function and
only one return statement can be used in the function.
That's why the generator plays an essential role in simplifying this process. If there is no
value found in iteration, it raises StopIteration exception.
Using multiple yield Statement:

How to Create Generator function in Python? We can use the multiple yield statement in the generator function. Consider the
following example.
It is similar to the normal function defined by the def keyword and uses a yield
def multiple_yield():
keyword instead of return. str1 = "First String"
yield str1
Or we can say that if the body of any function contains a yield statement, it
automatically becomes a generator function. str2 = "Second string"
yield str2
Example: Write a program to print the table of the given number using the str3 = "Third String"
generator. yield str3
obj = multiple_yield()
def table(n): print(next(obj))
for i in range(1,11): print(next(obj))
yield n*i print(next(obj))
i = i+1
Output:
for x in table(15):
print(x) First String
Second string
o/p: Third String
15
30 Ex2: # A simple generator function
45 def my_gen():
60 n=1
75 print('This is printed first')
90
# Generator function contains yield statements
105
120
yield n
135
150 n += 1
print('This is printed second')
yield n
n += 1  StopIteration exception is raised automatically when the function
print('This is printed at last') terminates.
yield n

# Using for loop


for item in my_gen():
print(item) Example: Advantage of Generator compare to Iterator
o/p:
This is printed first Generators can be implemented in a clear and concise way as compared to their
1 iterator class.
This is printed second
2
This is printed at last Following is an example to implement a sequence of power of 2's using iterator class.
3 class powtwoiter:
def __init__(self, max = 0):
self.max = max

def __iter__(self):
Python Generators with a Loop self.n = 0
return self
Normally, generator functions are implemented with a loop having a suitable terminating
condition. def __next__(self):
an example of a generator that reverses a string. if self.n > self.max:
def rev_str(my_str): raise StopIteration
length = len(my_str)
for i in range(length-1,-1,-1): result = 2 ** self.n
yield my_str[i] self.n += 1
return result
# For loop to reverse the string x=powtwoiter(3)
myit=iter(x)
for c in rev_str("hello"): print(next(myit))
print(c) print(next(myit))

o/p: o/p:
o 1
l 2
l
e
h Now lets do the same using a generator function.

def powtwogen(max = 0):


n=0
Difference between Generator function and Normal while n < max:
function yield 2 ** n
n += 1
x=powtwogen(3)
 Normal function contains only one return statement whereas generator myit=iter(x)
function can contain one or more yield statement. print(next(myit))
 When the generator functions are called, the normal function is paused print(next(myit))
immediately and control transferred to the caller. o/p:
1
 Local variable and their states are remembered between successive 2
calls.
# square each term using list comprehension
Python Generator Expression # Output: [1, 9, 36, 100]
print([x**2 for x in my_list])
Simple generators can be easily created on the fly using generator expressions.
It makes building generators easy.
# same thing can be done using generator expression
Same as lambda function creates an anonymous function, generator expression # Output: <generator object <genexpr> at 0x0000000002EBDAF8>
creates an anonymous generator function. # Initialize the list

a = (x**2 for x in my_list)


The syntax for generator expression is similar to that of a list comprehension
# Output: 1
in Python. But the square brackets are replaced with round parentheses.
print(next(a))

# Output: 9
Example of list comprehension:
print(next(a))
List comprehension consists of an expression followed by for statement inside # Output: 36
square brackets. print(next(a))

Here is an example to make a list with each item being increasing power of 2. # Output: 100
print(next(a))
pow2 = [2 ** x for x in range(10)]
# Output: StopIteration
# Output: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
print(pow2)
next(a)

This code is equivalent to

pow2 = []
for x in range(10):
Python Decorator
pow2.append(2 ** x)
"In Decorators, functions are passed as an argument into another function and
A list comprehension can optionally contain more for or if statements. An optional then called inside the wrapper function."
if statement can filter out items for the new list. Here are some examples.
It is also called meta programming where a part of the program attempts to
>>> pow2 = [2 ** x for x in range(10) if x > 5] change another part of program at compile time.
>>> pow2
[64, 128, 256, 512]
>>> odd = [x for x in range(20) if x % 2 == 1] Before we go for decorator, ffirst you have to know or remember that function names
>>> odd are references to functions and that we can assign multiple names to the same function:
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
Ex1:
def func1(msg):
The major difference between a list comprehension and a generator print(msg)
expression is that while list comprehension produces the entire list, func1("Hii")
generator expression produces one item at a time. func2 = func1
func2("Hii")
Example1: del func1
# Initialize the list func1(“hello”) #error
my_list = [1, 3, 6, 10] func2(“hello”)
o/p:
Hii return x-1
Hii def operator(func, x):
temp = func(x)+x
Ex2: return temp
>>> def succ(x): print(operator(sub,10))
... return x + 1 print(operator(add,20))
...
Output:
>>> successor = succ
19
>>> successor(10)
41
11
>>> succ(10)
11 Python decorators allows us to decorate a function.
It allows you to take on extra functionality to an existing function.

In the above program, we need to understand the following concept of the Ex:
function: def simple_function():
#do something
 The function can be referenced and passed to a variable and returned
To add more functionality to this function if we require, then there is a problem.
from other functions as well.
Here we have two options:
 The functions can be declared inside another function and passed as an
1) Add extra code to the old function
argument to another function.
2) Create a new function by copying the old code and then adding
new code to that.
Inner Function But again if we want to remove the extra functionality then, we need to delete
them manually or check for the old function if it is exist.
Python provides the facility to define the function inside another function. These
types of functions are called inner functions. Consider the following example: If we have some ON/OFF switch for adding functionality to the existing function
then it is called decorator.
def func():
print("We are in first function") For it we use the @ operator at the top of the original function.
def func1(): Example:
print("This is first child function") @some_decorator
def func2(): def simple_function():
print(" This is second child function") #dop something
func1()
func2()
Now let us go through the steps of manually building a decorator to know what
func()
@ operator is doing behind the scene.
Output: Ex1:
def func():
We are in first function return 1;
This is first child function
This is second child function
func()

o/p:
1
function that accepts other function as an argument is also called higher order
function. Consider the following example:
If we type:
func
def add(x): then the error displayed as:
return x+1
< function__main__.func>
def sub(x):
result = "It's " + str(celsius2fahrenheit(t)) + " degrees!"
So, it is showing error message that we have a function func return result

Ex2: print(temperature(20))
def hello(): The output:
return “hello” It's 68.0 degrees!
hello()
o/p:
hello
passing a function into another
if we type: we can pass functions - or better "references to functions" - as parameters to a
greet=hello function. We will demonstrate this in the next simple example:
greet() def g():
print("Hi, it's me 'g'")
o/p: print("Thanks for calling me")
hello
def f(func):
 Here actually greet is pointing to the function object hello(). print("Hi, it's me 'f'")
print("I will call 'func' now")
 Here even we delete hello(), then also the greet() will be exist and will func()
work.
Ex: f(g)
del hello
hello() # it will error The output looks like this:
greet() Hi, it's me 'f'
I will call 'func' now
Hi, it's me 'g'
o/p: Thanks for calling me
hello
def g():
define a function inside another. print("Hi, it's me 'g'")
print("Thanks for calling me")
def f(): def f(func):
print("Hi, it's me 'f'")
def g(): print("I will call 'func' now")
print("Hi, it's me 'g'") func()
print("Thanks for calling me") print("func's real name is " + func.__name__)
print("This is the function 'f'") f(g)
print("I am calling 'g' now:")
g()
The output explains once more what's going on:
Hi, it's me 'f'
I will call 'func' now
Hi, it's me 'g'
f()
Thanks for calling me
func's real name is g
We will get the following output, if we start the previous program:
This is the function 'f'
I am calling 'g' now: EXAMPLE USING PYTHON DECORATOR:
Hi, it's me 'g'
Thanks for calling me
Ex1:consider a function and observe the output
def newfun(original):
Another example using "proper" return statements in the functions:
def temperature(t):
def func():
def celsius2fahrenheit(x): print("extra code before");
return 9 * x / 5 + 32 original();
print("extra code after"); extra code after
return func
Note: When we call the original() function actually this function is supplied as
def original(): argument to the newfun(), as because we have written @followed by decorator
print("I m original") function newfun.

original() So, now we can go for switch ON or OFF to the statement written with @
Eg:
o/p: @newfun
I m original Or
#@newfun
Ex2: observe the 2nd output
def newfun(original): Decorators are mainly used in web frame work applications and other software
def func(): development fields.
print("extra code before");
original();
print("extra code after");
return func

def original():
print("I m original")

d=newfun(original)
d()

o/p:
extra code before
I m original
extra code after

Now the function which needed to be decorated i.e: original() can be modified by
prefix one statement as: @newfun
Ex3:
def newfun(original):
def func():
print("extra code before");
original();
print("extra code after");
return func

@newfun
def original():
print("I m original")

original() # d=newfun(original)

o/p:
extra code before
I m original

You might also like