View
85
Download
0
Category
Preview:
Citation preview
Introduction to Object Oriented Programming:
Object-oriented vs Procedure-oriented Programming languages:
1. Object-oriented programming is the problem-solving approach and used where computation
is done by using objects.
Procedural programming uses a list of instructions to do computation step by step.
2. It makes the development and maintenance easier.
In procedural programming, It is not easy to maintain the codes when the project becomes
lengthy.
3. It simulates the real world entity. So real-world problems can be easily solved through oops.It
doesn't simulate the real world.
It works on step by step instructions divided into small parts called functions.
4. It provides data hiding. So it is more secure than procedural languages. You cannot access
private data from anywhere.
Procedural language doesn't provide any proper way for data binding, so it is less secure.
5. Example of object-oriented programming languages is C++, Java, .Net, Python, C#, etc.
Examples of procedural languages are: C, Fortran, Pascal, VB etc.
Class:
The class can be defined as a collection of objects. It is a logical entity that has some
specific attributes and methods. It specifies the set of instance variables and methods that are
bundle together for defining a type of object. For example: if you have an employee class then it
should contain an attribute and method, i.e. an email id, name, age, salary, etc.
Syntax
class ClassName: <statement-1> . . <statement-N>
The class keyword is used to define classes, much as def is used for defining functions. class ClassName:
Data members
methods()
For example, strings in Python are object instances of the built-in String class, depicted in
Figure 1.
Figure 1: Object Instances of String Class
One method of the String class is isdigit(). Thus, every string object has this
method. The specific object whose isdigit() method is called determines the specific
string that it is applied to,
name.isdigit() ➝ False city_state.isdigit() ➝ False
address.isdigit() ➝ False zip_code.isdigit() ➝ True
Object creation:
An object is simply a collection of data (variables) and methods (functions) that
act on those data. Similarly, a class is a blueprint for that object. An object is also
called an instance of a class and the process of creating this object is called
instantiation. The class object could be used to access different attributes. It can also
be used to create new object instances (instantiation) of that class. The procedure to
create an object is similar to a function call.
Syntax:
objectname=ClassName(<arguments>)
Accessing members of the class:
We can access the members of class using object and period or dot operator as
follows.
objectname.datamember
objectname.method()
__init__() method:
All classes have a function called __init__(), which is always executed when the
class is being initiated. Use the __init__() function to assign values to object properties,
or other operations that are necessary to do when the object is being created.
This special function gets called whenever a new object of that class is
instantiated. This type of function is also called constructors in Object Oriented
Programming (OOP). We normally use it to initialize all the variables.
Syntax:
def __init__(self,arg1,arg2….):
#statements
Note: The __init__() function is called automatically every time the class is being used to
create a new object.
Class method and self argument:
Class methods are exactly same as ordinary functions that we have been defined
so far. Class methods must have the first argument named as self. We do not pass any
value to this argument. Python provides its value automatically. Class methods also
called as instance methods or object methods. Methods in objects are functions that
belong to the object.
The self argument is a reference to the current instance of the class, and is used
to access variables that belong to the class. It does not have to be named self , you can
call it whatever you like, but it has to be the first parameter of any function in the
class.
Class variable: A variable that is shared by all instances of a class. Class variables are
defined within a class but outside any of the class's methods. Class variables are not
used as frequently as instance variables are. Class or static variables are shared by all
objects.
Instance variable: A variable that is defined inside a method and belongs only to the
current instance of a class. Instance or non-static variables are different for different
objects (every object has a copy of it).
Examples1:
class Student: name='ece' #class Variables roll=401 #class Variables
def display(self): #class or instance method print(self.name,self.roll)
s1=Student() s2=Student()
s1.display() s2.display() '''
OUTPUT: ece 401
ece 401 ''' Example2:
class Student: def __init__(self): #constructor in python (special member function) print('non parametrized constructor')
self.sname='ece' #instance Variables self.sroll=401 #instance Variables
def display(self): #class or instance method print(self.sname,self.sroll)
s1=Student() s2=Student()
s3=Student() s1.display() s2.display()
''' OUTPUT: non parametrized constructor
non parametrized constructor non parametrized constructor
ece 401 ece 401 '''
Example3:
Stduent.py: class Student:
stdcount=0 #class variable def __init__(self,name,roll): print('Parametrized Constructor')
self.sname=name #sname is instance varaible self.sroll=roll #sroll is instance varaible Student.stdcount+=1
def display(self): #class or instance method
print(self.stdcount,self.sname,self.sroll) s1=Student('ece',401)
s1.display() s2=Student('cse',501) s2.display()
s3=Student('EEE',201) s3.display()
''' s4=Student('MECH',301) s4.display()'''
print('total students:',s1.stdcount) '''
OUTPUT: Parametrized Constructor 1 ece 401
Parametrized Constructor 2 cse 501 Parametrized Constructor
3 EEE 201 total students: 3
''' __del__() method:
The __del__ method is a special method of a class. It is also called the destructor
method and it is called (invoked) when the instance (object) of the class is about to get
destroyed. We use the __del__ method to clean up resources like closing a file. This
method is automatically called when an object is going out of scope. This is the time
when object will no longer used and its occupied resources are return back to the
system so that they can be reused when required. We can also explicitly do the same
using del keyword.
Syntax:
def __del__(self):
#statements
Example:
class Person: count=0
def __init__(self,name,age): self.name=name
self.age=age Person.count+=1
def display(self): print(Person.count,' Name:',self.name,'Age:',self.age)
def __del__(self): Person.count-=1
print('Object with name %s goes out of scope'%self.name) p1=Person('john',28) p1.display()
p2=Person('Raju',30) p2.display()
p3=Person('Rani',29) p3.display() print(p1)
del p1 del p2
del p3 print(p2) """
OUTPUT: 1 Name: john Age: 28 2 Name: Raju Age: 30
3 Name: Rani Age: 29 <__main__.Person object at 0x01C9B5C8>
Object with name john goes out of scope Object with name Raju goes out of scope Object with name Rani goes out of scope
Traceback (most recent call last): File "G:\2020-21-Online Classes\DSP\19-08-2020\Persondel.py", line 26, in
<module> print(p2) NameError: name 'p2' is not defined
""" Three Fundamental Features of Object oriented Programming:
Inheritance:
Inheritance is the most important aspect of object-oriented programming which simulates
the real world concept of inheritance. It specifies that the child object acquires all the properties
and behaviours of the parent object.
By using inheritance, we can create a class which uses all the properties and behaviour of
another class. The new class is known as a derived class or child class, and the one whose
properties are acquired is known as a base class or parent class.
It provides re-usability of the code.
Polymorphism:
Polymorphism contains two words "poly" and "morphs". Poly means many and Morphs
means form, shape. By polymorphism, we understand that one task can be performed in
different ways. For example You have a class animal, and all animals speak. But they speak
differently. Here, the "speak" behaviour is polymorphic in the sense and depends on the animal.
So, the abstract "animal" concept does not actually "speak", but specific animals (like dogs and
cats) have a concrete implementation of the action "speak".
Encapsulation:
Encapsulation is also an important aspect of object-oriented programming. It is used to
restrict access to methods and variables. In encapsulation, code and data are wrapped together
within a single unit from being modified by accident.
Data Abstraction:
Data abstraction and encapsulation both are often used as synonyms. Both are nearly
synonym because data abstraction is achieved through encapsulation.
Abstraction is used to hide internal details and show only functionalities. Abstracting
something means to give names to things so that the name captures the core of what a function
or a whole program does.
Data Abstraction and Hiding through Classes:
Data Abstraction:
Data abstraction and encapsulation both are often used as synonyms. Both are nearly
synonym because data abstraction is achieved through encapsulation.
Abstraction in Python is the process of hiding the real implementation of an application
from the user and emphasizing only on usage of it.
For example, consider you have bought a new electronic gadget. Along with the gadget,
you get a user guide, instructing how to use the application, but this user guide has no info
regarding the internal working of the gadget.
Another example is, when you use TV remote, you do not know how pressing a key in the
remote changes the channel internally on the TV. You just know that pressing + volume key will
increase the volume.
A programmer can hide all the irrelevant data/process of an application in order to reduce
complexity and increase efficiency. In Python, abstraction can be achieved by using abstract
classes and methods in our programs.
A class containing at least one or more abstract methods is called an abstract class. An
abstract class just serves as a template for other classes by defining a list of methods that the
classes must implement.
Abstract methods do not contain any implementation. Instead, all the implementations
can be defined in the methods of sub-classes that inherit the abstract class. An abstract class
is created by importing a class named 'ABC' from the 'abc' module and inheriting the 'ABC'
class. Below is the syntax for creating the abstract class.
An abstract class can have both a normal method and an abstract method
An abstract class cannot be instantiated, ie., we cannot create objects for the abstract
class.
Syntax:
from abc import ABC,abstractmethod
Class ClassName(ABC):
Where ABC is an abstract base class.
Example:
from abc import ABC, abstractmethod class Shape(ABC): def display(self):#concrete Method or normal Method
print("I am a normal method defined inside the abstract class 'Shape'") @abstractmethod def calculate_area(self):#abstract Method pass class Rectangle(Shape): length = 5 breadth = 3 def calculate_area(self): return self.length * self.breadth class Circle(Shape): radius = 4 def calculate_area(self):
return 3.14 * self.radius * self.radius #s=Shape() #s.display() rec = Rectangle() #object created for the class 'Rectangle' rec.display() print("Area of a rectangle:", rec.calculate_area()) #call to 'calculate_area' method defined inside the class 'Rectangle' cir = Circle() #object created for the class 'Circle' print("Area of a circle:", cir.calculate_area()) """ OUTPUT: I am a normal method defined inside the abstract class 'Shape' Area of a rectangle: 15 Area of a circle: 50.24 """
Public and Private data members:
Classical object-oriented languages, such as C++ and Java, control the access to
class resources by public, private and protected keywords.
Private members of a class are denied access from the environment outside the
class. They can be handled only from within the class.
Public members (generally methods declared in a class) are accessible from
outside the class. The object of the same class is required to invoke a public method.
This arrangement of private instance variables and public methods ensures the
principle of data encapsulation.
Protected members of a class are accessible from within the class and are also
available to its sub-classes. No other environment is permitted access to it. This
enables specific resources of the parent class to be inherited by the child class.
Python doesn't have any mechanism that effectively restricts access to any
instance variable or method. Python prescribes a convention of prefixing the name of
the variable/method with single or double underscore to emulate the behaviour of
protected and private access specifiers.
All members in a Python class are public by default. Any member can be
accessed from outside the class environment.
Python's convention to make an instance variable protected is to add a prefix _
(single underscore) to it. This effectively prevents it to be accessed, unless it is from
within a sub-class.
Similarly, a double underscore __ prefixed to a variable makes it private. It gives a
strong suggestion not to touch it from outside the class. Any attempt to do so will result
in an AttributeError:
We can access private variables from outside of the class using following syntax.
Objectname._classname__privatevariable #name mangling
Example1:
class Encap: def __init__(self,num1,num2): self.num1=num1 self.__num2=num2 def display(self): print("Number1 value is:",self.num1) print("Number1 value is:",self.__num2) e=Encap(10,20) e.display() print("From the main module,Number1 is:",e.num1) #print("From the main module,Number2 is:",e.__num2) print("From the main module,Number2 is:",e._Encap__num2) """ OUTPUT: Number1 value is: 10 Number2 value is: 20 From the main module,Number1 is: 10 From the main module,Number2 is: 20 """
ENCAPSULATION (Data Hiding):
Encapsulation is a means of bundling together instance variables and methods to
form a given type (class). Selected members of a class can be made inaccessible
(“hidden”) from its clients, referred to as information hiding. Information hiding is a
form of abstraction. This is an important capability that object-oriented programming
languages provide. As an example, we give a depiction of a Fraction object in Figure 2.
Figure 2: Fraction Object Access
The Fraction object shows private instance variables __numerator and __denominator, and
four public methods.Private members of a class begin with two underscore characters, and
cannot be directly accessed. For example, trying to access the instance variables of Fraction
object frac1 is invalid,
frac1.__numerator =4 NOT ALLOWED
frac1.__denominator= 6 NOT ALLOWED
Public members of a class, on the other hand, are directly accessible. For example, the
following are valid method calls,
frac1.getNumerator() ALLOWED
frac1.getDenominator() ALLOWED
frac1.setNumerator(4) ALLOWED
frac1.setDenominator(6) ALLOWED
These methods are referred to as getters and setters since their purpose is to get (return)
and set (assign) private instance variables of a class. Restricting access to instance variables via
getter and setter methods allows the methods to control what values are assigned (such as not
allowing an assignment of 0 to the denominator), and how they are represented when retrieved.
Thus, the instance variables of a class are generally made private, and the methods of the class
generally made public.
Example1:
class Student: __stdcount=0
def __init__(self,name,roll): print('Parametrized Constructor') self.sname=name
self.sroll=roll Student.__stdcount+=1
def display(self): #self.__stdcount=8
print(self.__stdcount,self.sname,self.sroll)
s1=Student('ece',401) s1.display() s2=Student('cse',501)
s2.display() s3=Student('EEE',201) s3.display()
s4=Student('MECH',301) s4.display()
print('Total No.of Students :',s4.__stdcount) ''' OUTPUT:
Parametrized Constructor 1 ece 401
Parametrized Constructor 2 cse 501 Parametrized Constructor
3 EEE 201
Parametrized Constructor 4 MECH 301 Total No.of Students : 4
''' Special Methods in Python:
Method names that begin and end with two underscore characters are called
special methods in Python. Special methods are automatically called. For example, the
__init__ method of the Fraction class developed is automatically called whenever a new
Fraction object is created,
class Fraction: def __init__(self,n,d): self.__numerator=n #private member
self.__denominator=d #private member frac1 = Fraction(1,2) – creates new fraction with value 1/2
frac2 = Fraction(6,8) – creates new fraction with value 6/8 The values in parentheses are arguments to the __init__ method to initialize a new
Fraction object to a specific value. Note that although there are three parameters
defined (self, numerator,denominator), the first is always implied. Therefore, only the
remaining arguments (numerator and denominator) are explicitly provided when
creating a Fraction object.
Two other special methods of Python are __str__ and __repr__. These methods are
used for representing the value of an object as a string. The __str__ method is called
when an object is displayed using print (and when the str conversion function is used.)
The __repr__function is called when the value of an object is displayed in the Python
shell (when interactively using Python).
The following Special methods used to provide arithmetic operators and
Relational Operators for class types are shown in Figure 3 & 4.
Figure 3: Arithmetic Operator Special Methods
Figure 4: Relational Operator Special Methods
Example:
class XYCoord: def __init__(self,x,y):
self.x=x self.y=y
def __repr__(self): return '('+str(self.x)+','+str(self.y)+')'
def __str__(self): return'XY-Coordinators:'+'('+str(self.x)+','+str(self.y)+')'
def __add__(self1,self2): newx=self1.x+self2.x
newy=self1.y+self2.y return XYCoord(newx,newy)
def __sub__(self1,self2):
newx=self1.x-self2.x newy=self1.y-self2.y
return XYCoord(newx,newy)
def __mul__(self1,self2): newx=self1.x*self2.x newy=self1.y*self2.y
return XYCoord(newx,newy)
def __truediv__(self1,self2): newx=self1.x/self2.x
newy=self1.y/self2.y return XYCoord(newx,newy)
def __pow__(self1,item):
newx=self1.x**item newy=self1.y**item
return XYCoord(newx,newy) def __neg__(self1):
newx=-self1.x newy=-self1.y
return XYCoord(newx,newy)
def __lt__(self1,self2): newx=self1.x<self2.x newy=self1.y<self2.y
return XYCoord(newx,newy)
def __gt__(self1,self2): newx=self1.x>self2.x newy=self1.y>self2.y
return XYCoord(newx,newy)
def __ge__(self1,self2): newx=self1.x>=self2.x
newy=self1.y>=self2.y return XYCoord(newx,newy)
def __le__(self1,self2):
newx=self1.x<=self2.x newy=self1.y<=self2.y
return XYCoord(newx,newy)
def __eq__(self1,self2): newx=self1.x==self2.x newy=self1.y==self2.y
return XYCoord(newx,newy)
def __ne__(self1,self2): newx=self1.x!=self2.x
newy=self1.y!=self2.y return XYCoord(newx,newy)
"""
OUTPUT: >>> c1=XYCoord(4,5) >>> c2=XYCoord(6,8)
>>> c1 (4,5) >>> print(c2)
XY-Coordinators:(6,8) >>> c1+c2
(10,13) >>> c1-c2 (-2,-3)
>>> c3=c1*c2 >>> print(c3)
XY-Coordinators:(24,40) >>> c2/c2 (1.0,1.0)
>>> c1**2 (16,25) >>> -c2
(-6,-8) >>> c1<c2
(True,True) >>> c1<=c2 (True,True)
>>> c1>c2
(False,False) >>> c1>=c2 (False,False)
>>> c1==c2 (False,False)
>>> c1!=c2 (True,True) >>>
"""
__len__():
Python len() function returns the length of the object. This function internally
calls __len__() function of the object. So we can use len() function with any object that
defines __len__() function.
__contains__():
Python String class has __contains__() function which we can use to check if it
contains another string or not.__contains__() is an instance method and returns
boolean value True or False depending on whether the string object contains the
specified string object or not.This method will be called whenever we use in operator on
instance.
Example:
class College: def __init__(self,name,area): self.name=name
self.area=area
def __repr__(self): return self.name+','+self.area
def __str__(self): return 'College details:'+self.name+','+self.area
def __len__(self): return len(self.name)
def __contains__(self,item): return item in self.name
""" OUTPUT:
>>> c=College("AITS","RAJAMPET") >>> c AITS,RAJAMPET
>>> print(c) College details:AITS,RAJAMPET >>> len(c)
4 >>> "IT" in c
True >>> """
__iter__() and __next__():
The __iter__() function returns an iterator for the given object (array, set, tuple
etc. or custom objects). It creates an object that can be accessed one element at a time
using __next__() function, which generally comes in handy when dealing with loops.
Example1:
class PrintNumbers: def __init__(self, max):
self.max = max
def __iter__(self): self.num = 0 return self
def __next__(self):
if(self.num >= self.max): raise StopIteration self.num += 1
return self.num p=PrintNumbers(5) for i in p:
print(i) """
OUTPUT: 1 2
3 4
5 """ Example2:
class PrintNumbers:
def __init__(self, max): self.max = max
def __iter__(self): self.num = 0
return self def __next__(self):
if(self.num >= self.max): raise StopIteration
self.num += 1 return self.num """
OUTPUT: >>> p=PrintNumbers(5) >>> pt=iter(p)
>>> next(pt) 1
>>> next(pt) 2
>>> next(pt) 3 >>> next(pt)
4 >>> next(pt)
5 >>> next(pt) Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module> next(pt) File "G:\2020-21-Online Classes\DSP\21-08-2020\PrintNumbers.py", line 11, in
__next__ raise StopIteration
StopIteration >>> """
__getitem__() and __setitem__():
The __getitem__() method is used for indexing.it has the following syntax.
def __getitem__(self,key):
statements
The __setitem__() method is used to assign an item to the indexed value.It has the
following syntax.
def __setitem__(self,key,value):
statements
Example:
class Numbers: def __init__(self,mylist):
self.mylist=mylist def __getitem__(self,index): return self.mylist[index]
def __setitem__(self,index,value): self.mylist[index]=value n=Numbers([10,20,30,40,50]);
print(n[3]) n[2]=60
print(n.mylist) """
OUTPUT: 40
[10, 20, 60, 40, 50] """ Private Methods:
In the context of class, private means the attributes are only available for the
members of the class not for the outside of the class. Like Private attributes we can also
define private methods in a class. Private class methods, which can't be called from
outside their class.
Private methods are those methods that should neither be accessed outside the
class nor by any base class.
In Python, there is no existence of Private methods that cannot be accessed
except inside a class. However, to define a private method prefix the member name with
double underscore “__”.
Example:
class Person: def __init__(self,name):
self.__name=name def __display(self): print("The Person Name is:",self.__name)
p=Person("Nag")
p.__display() """ OUTPUT:
Traceback (most recent call last): File "G:/2020-21-Online Classes/DSP/24-08-2020/Private_method.py", line 8, in
<module> p.__display() AttributeError: 'Person' object has no attribute '__display'
""" Name mangling:
Python provides a magic wand which can be used to call private methods outside
the class also, it is known as name mangling. It means that any identifier of the form
__display() (at least two leading underscores or at most one trailing underscore) is
replaced with _classname__display(), where classname is the current class name with
leading underscore(s) stripped.
Example:
class Person: def __init__(self,name): self.__name=name
def __display(self): print("The Person Name is:",self.__name)
p=Person("Nag") p._Person__display()
""" OUTPUT: The Person Name is: Nag
""" Calling a Class Method from another class method:
We can call a class method from another class method using self-argument. This
is shown in the following program.
Example:
class Person:
def __init__(self,Firstname,Lastname): self.__Firstname=Firstname
self.__Lastname=Lastname
def Fullname(self): self.name=self.__Firstname+' '+self.__Lastname
def __display(self):
self.Fullname() #calling a class method from another class method print("The Person Name is:",self.name)
p=Person("Pidugu","Nagendra") p._Person__display() """
OUTPUT: The Person Name is: Pidugu Nagendra
""" A class method can reference global names in same way as ordinary methods.
This is shown in the following program.
Example:
#Global Name space
def myage_5(a): return a+5
class Person:
def __init__(self,Firstname,Lastname,age): self.__Firstname=Firstname self.__Lastname=Lastname
self.age=age def Fullname(self):
self.name=self.__Firstname+' '+self.__Lastname
def __display(self): self.Fullname() #calling a class method from another class method
self.age=myage_5(self.age) print("The Person Name is:",self.name,"and his age after 5 years is",self.age)
p=Person("Pidugu","Nagendra",30) p._Person__display()
""" OUTPUT: The Person Name is: Pidugu Nagendra and his age after 5 years is 35
""" Note:
Unlike C++ and java, Python allows programmers to add, remove or modify attributes of
class and object at any time.
Example:
class RuntimeAttr:
def __init__(self,name): self.name=name
def display(self): print("My Name is:",self.name)
obj=RuntimeAttr("Naga") obj.display()
obj.new_name="Endra" print("My New Name is:",obj.new_name) obj.new_name="Nagendra"
print("After Modification,My New Name is:",obj.new_name) del new_name print("After deletion,My New Name is:",obj.new_name)
"""
OUTPUT: My Name is: Naga My New Name is: Endra
After Modification,My New Name is: Nagendra Traceback (most recent call last):
File "G:/2020-21-Online Classes/DSP/26-08-2020/RuntimeAttr.py", line 14, in <module> del new_name
NameError: name 'new_name' is not defined """
Built-in functions to check, get, set and delete class attributes:
Python has some built-in function that can also be used to work with attribute of
class or object. We can use these function to check whether a class has attribute or
not, get the attribute value if it exists, set a new value, or even delete that attribute.
These built-in functions are a follows.
1. hasattr(object, name)
2. getattr(object, name[,default])
3. setattr(object, name, value)
4. delattr(object, name)
1. hasattr (object, name):
The hasattr() method returns true if an object has the given named attribute and
false if it does not. This method takes two parameters:
object - object whose named attribute is to be checked.
name - name of the attribute to be searched.
This method returns Boolean values.
Example:
class Person: age = 30 name = 'Naga'
p = Person() print('Person has age?:', hasattr(p, 'age')) print('Person has salary?:', hasattr(p, 'salary'))
""" OUTPUT:
Person has age?: True Person has salary?: False """
2. getattr (object, name[,default]):
The getattr() method returns the value of the named attribute of an object. If not
found, it returns the default value provided to the function. It is Similar to
object.attribute. This method takes multiple parameters:
object - object whose named attribute's value is to be returned.
name - string that contains the attribute's name.
default (Optional) - value that is returned when the named attribute is not found.
This method returns:
value of the named attribute of the given object.
default, if no named attribute is found.
AttributeError exception, if named attribute is not found and default is not
defined.
Example1:
class Person: age = 30
name = "Naga" p = Person() print('The age is:', getattr(p, "age"))
print('The age is:', p.age) Output: The age is: 30
The age is: 30 Example2:
class Person:
age = 30 name = "Naga" p = Person()
# when default value is provided print('The Gender is:', getattr(p, 'Gender', 'Male'))
# when no default value is provided print('The Gender is:', getattr(p, 'Gender')) """
OUTPUT: The Gender is: Male
Traceback (most recent call last): File "G:\2020-21-Online Classes\DSP\26-08-2020\getattr.py", line 8, in <module> print('The Gender is:', getattr(p, 'Gender'))
AttributeError: 'Person' object has no attribute 'Gender' """ 3. setattr(object, name, value):
The setattr() function sets the value of the attribute of an object. This function takes
three parameters:
object - object whose attribute has to be set.
name - attribute name.
value - value given to the attribute.
The setattr() method doesn't return anything; returns None.
Example:
class Person:
name = 'Naga' p = Person()
print('Before modification:', p.name) # setting name to 'Endra' setattr(p, 'name', 'Endra')
print('After modification:', p.name) """
OUTPUT: Before modification: Naga After modification: Endra
""" If the attribute is not found, setattr() creates a new attribute an assigns value to it.
Example2:
class Person:
name = 'Naga' p = Person() # setting attribute name to John
setattr(p, 'name', 'Endra') print('Name is:', p.name)
# setting an attribute not present in Person setattr(p, 'age', 30) print('Age is:', p.age)
""" OUTPUT: Name is: Endra
Age is: 30 """
4. delattr(object, name):
The delattr() deletes an attribute from the object (if the object allows it). It takes two
parameters:
object - the object from which name attribute is to be removed.
name - a string which must be the name of the attribute to be removed from the
object.
delattr() doesn't return any value (returns None). It only removes an attribute (if the
object allows it).
Example:
class Person: def __init__(self,name,age,salary): self.age = age
self.name = name self.salary=salary
p = Person("NAGA",30,15000)
print('Person has age?:', hasattr(p, 'age')) print('Person has salary?:', hasattr(p, 'salary')) delattr(p,'salary')
print("After using delattr()") print('Person has salary?:', hasattr(p, 'salary'))
print('Person age is:', getattr(p,'age')) print('Person name is:', getattr(p,'name')) print('Person salary is:',getattr(p,'salary'))
""" OUTPUT: Person has age?: True
Person has salary?: True After using delattr()
Person has salary?: False Person age is: 30 Person name is: NAGA
Traceback (most recent call last): File "G:\2020-21-Online Classes\DSP\26-08-2020\delattr.py", line 15, in <module>
print('Person salary is:',getattr(p,'salary')) AttributeError: 'Person' object has no attribute 'salary' """
Built-in Class Attributes:
Every Python class keeps following built-in attributes and they can be accessed
using dot operator like any other attribute.
__dict__ − Dictionary containing the class's namespace.
__doc__ − Class documentation string or none, if undefined.
__name__ − Class name.
__module__ − Module name in which the class is defined. This attribute is
"__main__" in interactive mode.
__bases__ − A possibly empty tuple containing the base classes, in the order of
their occurrence in the base class list.
Example:
class Employee:
'Common base class for all employees' empCount = 0
def __init__(self, name, salary): self.name = name self.salary = salary
Employee.empCount += 1 def displayCount(self):
print("Total Employee %d" % Employee.empCount)
def displayEmployee(self): print("Name : ", self.name, ", Salary: ", self.salary)
e1=Employee("CSE",15000) e2=Employee("ECE",20000) e1.displayCount()
e1.displayEmployee()
e2.displayEmployee() print("Employee.__doc__:", Employee.__doc__)
print("Employee.__name__:", Employee.__name__) print("Employee.__module__:", Employee.__module__)
print("Employee.__bases__:", Employee.__bases__) print("Employee1.__dict__:", e1.__dict__) print("Employee2.__dict__:", e2.__dict__)
""" OUTPUT: Total Employee 2
Name : CSE , Salary: 15000 Name : ECE , Salary: 20000
Employee.__doc__: Common base class for all employees Employee.__name__: Employee Employee.__module__: __main__
Employee.__bases__: (<class 'object'>,) Employee1.__dict__: {'name': 'CSE', 'salary': 15000}
Employee2.__dict__: {'name': 'ECE', 'salary': 20000} """ Garbage Collection:
Python deletes unneeded objects (built-in types or class instances) automatically
to free memory space. The process by which Python periodically reclaims blocks of
memory that no longer are in use is termed garbage collection.
Python's garbage collector runs during program execution and is triggered when
an object's reference count reaches zero. An object's reference count changes as the
number of aliases that point to it changes.
An object's reference count increases when it's assigned a new name or placed in
a container (list, tuple or dictionary).The object's reference count decreases when it's
deleted with del, its reference is reassigned, or its reference goes out of scope. When an
object's reference count reaches zero, Python collects it automatically.
Example1:
var1=10 #Create object var1.
var2=var1 #increase reference count of var1-object assignment.
var3=[var2] #increase reference count of var1-object used in a list.
var2=50 #decrease reference count of var1-object reassignment.
var3[0]=-1 #decrease reference count of var1-removal from the list.
del var1 #decrease reference count of var1-object deleted.
Example2:
class Point: def __init__( self, x, y): self.x = x
self.y = y
def __del__(self): class_name = self.__class__.__name__
print(class_name, "destroyed") pt1 = Point(5,8)
pt2 = pt1 pt3 = pt1
print(id(pt1), id(pt2), id(pt3)) # prints the ids of the objects del pt1 del pt2
del pt3 """ OUTPUT:
29992344 29992344 29992344 Point destroyed
""" Class Method:
A class method is a method which is bound to the class and not the object of the
class. They have the access to the state of the class as it takes a class parameter that
points to the class and not the object instance. It can modify a class state that would
apply across all the instances of the class. For example it can modify a class variable
that will be applicable to all the instances.
Class methods are little different from the ordinary methods. First, these are
called by class not by the instance of class. Second, the first argument of class method
is cls not the self.
We generally use class method to create factory methods. Factory methods return
class object (similar to a constructor) for different use cases. To define a class method in
python, we use @classmethod decorator.
A decorator is syntactic convenience that takes in function, adds some
functionality to it and then returns it. It uses @ character as prefix to the function.
Syntax:
@classmethod
def class_method_name(cls,args,…):
Statements
Example:
class Rectangle:
def __init__(self,length,breadth): self.length=length
self.breadth=breadth def calculate_area(self):
return self.length*self.breadth @classmethod
def square(cls,side): return cls(side,side)
rec=Rectangle.square(10)
print("Area=",rec.calculate_area()) """ OUTPUT:
Area= 100 """
Static Method:
A static method is a special case of method which is bound to the class and not
the object of the class. A static method can’t access or modify class state. It is present
in a class because it makes sense for the method to be present in class.
We generally use static methods to create utility functions. It is similar to class
method. The only difference is that a static method does not receive any additional
arguments like cls and self. To define a static method we use @staticmethod decorator.
Syntax:
@staticmethod
def static_method_name(args,…):
Statements
Example:
from datetime import date
class Person: def __init__(self, name, age): self.name = name
self.age = age def __str__(self):
return 'Person Name: {} and Age: {}'.format(self.name, self.age)
# a class method to create a Person object by birth year. @classmethod def fromBirthYear(cls, name, year):
return cls(name, date.today().year - year)
# a static method to check if a Person is adult or not. @staticmethod def isAdult(age):
return age > 18 p1 = Person('Naga', 30) print(p1)
p2 = Person.fromBirthYear('sana', 1989) print(p2)
# print the result print(Person.isAdult(22)) print(Person.isAdult(16))
""" OUTPUT: Person Name: Naga and Age: 30
Person Name: sana and Age: 31 True
False """
Differences between class method and static method:
Class Method Static Method
The class method takes cls (class) as first argument.
The static method does not take any specific parameter.
Class method can access and modify the
class state.
Static Method cannot access or modify the
class state.
The class method takes the class as parameter to know about the state of that
class.
Static methods do not know about class state. These methods are used to do some
utility tasks by taking some parameters.
@classmethod decorator is used here. @staticmethod decorator is used here.
Inheritance:
The method of inheriting the properties of parent class into a child class is known as
inheritance. It is an OOP concept. Following are the benefits of inheritance.
Code reusability- we do not have to write the same code again and again, we can
just inherit the properties we need in a child class.
It represents a real world relationship between parent class and child class.
It is transitive in nature. If a child class inherits properties from a parent class, then
all other sub-classes of the child class will also inherit the properties of the parent
class.
Inheritance allows us to define a class that inherits all the methods and properties
from another class. Parent class is the class being inherited from, also called base
class. Child class is the class that inherits from another class, also called derived class.
Subclassing (Calling constructor of parent class):
A child class needs to identify which class is its parent class. This can be done by
mentioning the parent class name in the definition of the child class.
Eg: class subclass_name (superclass_name):
__init__( ) Function:
The __init__() function is called every time a class is being used to make an object.
When we add the __init__() function, the child class will no longer be able to inherit the
parent class’s __init__() function. The child’s class __init__() function overrides the
parent class’s __init__() function.
TYPE OF INHERITANCE:
Single Inheritance: When a child class inherits only a single parent class.
Syntax:
class A:
statments1
class B(A):
statments2
Example: class Base:
def display1(self): print('I am in Parent Class')
class Derived(Base): def display2(self): print('I am in Child Class')
d=Derived() d.display1() d.display2()
''' OUTPUT:
I am in Parent Class I am in Child Class '''
Multilevel Inheritance: When a child class becomes a parent class for another child
class.
Syntax:
class A: statments1 class B(A):
statments2 class C(B): statments3
Example:
class Base: def display1(self): print('I am in GrandParent Class')
class Derived1(Base): def display2(self):
print('I am in Parent Class') class Derived2(Derived1): def display3(self):
print('I am in Child Class') d=Derived2() d.display1()
d.display2() d.display3()
'''
OUTPUT: I am in GrandParent Class I am in Parent Class
I am in Child Class '''
Hierarchical Inheritance: Hierarchical inheritance involves multiple inheritances from
the same base or parent class.
Syntax:
class A: statments1
class B(A): statments2 class C(A):
statments3 Example: class Base:
def display1(self): print('I am in Parent Class')
class Derived1(Base): def display2(self): print('I am in Child1 Class')
class Derived2(Base): def display3(self):
print('I am in Child2 Class') d1=Derived1() d1.display1()
d1.display2() d2=Derived2() d2.display1()
d2.display3()'''
OUTPUT: I am in Parent Class I am in Child1 Class
I am in Parent Class I am in Child2 Class
'''
Multiple Inheritance: When a child class inherits from more than one parent class.
Syntax:
class A: statments1 class B:
statments2 class C(A,B):
statments3 Example: class Base1:
def display1(self): print('I am in Parent1 Class') class Base2:
def display2(self): print('I am in Parent2 Class')
class Derived(Base1,Base2): def display3(self): print('I am in Child Class')
d=Derived() d.display1()
d.display2() d.display3() '''
OUTPUT: I am in Parent1 Class I am in Parent2 Class
I am in Child Class '''
Hybrid Inheritance: Inheritance consisting of multiple types of inheritance is called
hybrid inheritance. It is also called as multipath inheritance.
Example:
class School: def func1(self):
print("This function is in school.")
class Student1(School):
def func2(self):
print("This function is in student 1. ") class Student2(School):
def func3(self): print("This function is in student 2.")
class Student3(Student1, School): def func4(self):
print("This function is in student 3.") # Driver's code
object = Student3() object.func1()
object.func2() """ OUTPUT:
This function is in school. This function is in student 1.
""" Python Super() Function: Super function allows us to call a method from the parent
class.The super() function that will make the child class inherit all the methods and
properties from its parent .By using the super() function, you do not have to use the name
of the parent element, it will automatically inherit the methods and properties from its
parent.
Example:
class Person: def __init__(self, fname, lname): self.firstname = fname
self.lastname = lname
def display(self): print(self.firstname, self.lastname)
class Student(Person): def __init__(self, fname, lname, year):
super().__init__(fname, lname) self.graduationyear = year
def welcome(self): print("Welcome", self.firstname, self.lastname, "to the class of", self.graduationyear)
s = Student("PIDUGU", "NAGENDRA", 2020) s.display()
s.welcome() ''' OUTPUT:
PIDUGU NAGENDRA Welcome PIDUGU NAGENDRA to the class of 2020 '''
The super() built-in returns a proxy object, a substitute object that can call methods
of the base class. This is called indirection (ability to reference base object with super())
Since the indirection is computed at the runtime, we can use different base classes at
different times (if we need to).
Example 2: super() with Multiple Inheritance
class Animal: def __init__(self, Animal): print(Animal, 'is an animal.');
class Mammal(Animal): def __init__(self, mammalName):
print(mammalName, 'is a warm-blooded animal.') super().__init__(mammalName)
class NonWingedMammal(Mammal): def __init__(self, NonWingedMammal):
print(NonWingedMammal, "can't fly.") super().__init__(NonWingedMammal)
class NonMarineMammal(Mammal): def __init__(self, NonMarineMammal):
print(NonMarineMammal, "can't swim.") super().__init__(NonMarineMammal)
class Dog(NonMarineMammal, NonWingedMammal): def __init__(self):
print('Dog has 4 legs.'); super().__init__('Dog')
d = Dog() print('') bat = NonMarineMammal('Bat')
""" OUTPUT:
Dog has 4 legs. Dog can't swim. Dog can't fly.
Dog is a warm-blooded animal. Dog is an animal.
Bat can't swim. Bat is a warm-blooded animal.
Bat is an animal. """ Method Resolution Order (MRO):
Method Resolution Order (MRO) is the order in which methods should be inherited in
the presence of multiple inheritance. We can view the MRO by using the __mro__ attribute
or by using mro() method.
>>> Dog.__mro__ (<class 'Dog'>,
<class 'NonMarineMammal'>, <class 'NonWingedMammal'>,
<class 'Mammal'>,
<class 'Animal'>, <class 'object'>)
A method in the derived calls is always called before the method of the base class.
In our example, Dog class is called before NonMarineMammal or NoneWingedMammal.
These two classes are called before Mammal, which is called before Animal, and
Animal class is called before the object.
If there are multiple parents like Dog(NonMarineMammal, NonWingedMammal),
methods of NonMarineMammal is invoked first because it appears first.
Polymorphism:
Polymorphism is taken from the Greek words Poly (many) and morphism (forms). It
means that the same function name can be used for different types. This makes
programming more intuitive and easier.
In Python, we have different ways to define polymorphism. So let’s move ahead and
see how polymorphism works in Python.
Polymorphism in Python:
A child class inherits all the methods from the parent class. However, in some
situations, the method inherited from the parent class doesn’t quite fit into the child
class. In such cases, you will have to re-implement method in the child class.
Polymorphism with Inheritance:
Polymorphism in python defines methods in the child class that have the same name
as the methods in the parent class. In inheritance, the child class inherits the methods
from the parent class. Also, it is possible to modify a method in a child class that it has
inherited from the parent class.
This is mostly used in cases where the method inherited from the parent class
doesn’t fit the child class. This process of re-implementing a method in the child class is
known as Method Overriding. Here is an example that shows polymorphism with
inheritance.
Example:
class Animal: def __init__(self,n,a):
self.name=n self.age=a
def display(self): pass def sound(self):
pass
class Cat(Animal): def __init__(self,n,a): super().__init__(n,a)
def display(self): print('I am cat.My name is',self.name,'and i am',self.age,'years old')
def sound(self):
print('MEOW MEOW') class Dog(Animal):
def __init__(self,n,a): super().__init__(n,a)
def display(self): print('I am Dog.My name is',self.name,'and i am',self.age,'years old') def sound(self):
print('BOW BOW') c=Cat('Lucy',5)
c.display() c.sound()
d=Dog('puppy',6) d.display() d.sound()
'''
OUTPUT: I am cat.My name is Lucy and i am 5 years old MEOW MEOW
I am Dog.My name is puppy and i am 6 years old BOW BOW ''' Abstract Class and Interface:
Data abstraction and encapsulation both are often used as synonyms. Both are nearly
synonym because data abstraction is achieved through encapsulation.
Abstraction in Python is the process of hiding the real implementation of an application from
the user and emphasizing only on usage of it.
For example, consider you have bought a new electronic gadget. Along with the gadget, you
get a user guide, instructing how to use the application, but this user guide has no info regarding
the internal working of the gadget.
Another example is, when you use TV remote, you do not know how pressing a key in the
remote changes the channel internally on the TV. You just know that pressing + volume key will
increase the volume.
A programmer can hide all the irrelevant data/process of an application in order to reduce
complexity and increase efficiency. In Python, abstraction can be achieved by using abstract
classes and methods in our programs.
A class containing at least one or more abstract methods is called an abstract class. An
abstract class just serves as a template for other classes by defining a list of methods that the
classes must implement.
Abstract methods do not contain any implementation. Instead, all the implementations can
be defined in the methods of sub-classes that inherit the abstract class. An abstract class is
created by importing a class named 'ABC' from the 'abc' module and inheriting the 'ABC' class. We
can use NotImplementedError to restrict the instantiation of a class. Any class that has
NotImplementedError inside the method definition cannot be instantiated.
An abstract class can have both a normal method and an abstract method
An abstract class cannot be instantiated, ie., we cannot create objects for the abstract class.
An interface acts as a blueprint for designing classes. Like classes, interfaces define
methods. Unlike classes, these methods are abstract. An abstract method is one that the interface
simply defines. It doesn’t implement the methods. This is done by classes, which then implement
the interface and give concrete meaning to the interface’s abstract methods .An interface has only
abstract methods.
Example1:
from abc import ABC, abstractmethod class Shape(ABC): def display(self):#concrete Method or normal Method print("I am a normal method defined inside the abstract class 'Shape'") @abstractmethod def calculate_area(self):#abstract Method pass class Rectangle(Shape): length = 5 breadth = 3 def calculate_area(self): return self.length * self.breadth class Circle(Shape): radius = 4 def calculate_area(self): return 3.14 * self.radius * self.radius #s=Shape() #s.display() rec = Rectangle() #object created for the class 'Rectangle' rec.display() print("Area of a rectangle:", rec.calculate_area()) #call to 'calculate_area' method defined inside the class 'Rectangle' cir = Circle() #object created for the class 'Circle' print("Area of a circle:", cir.calculate_area()) """ OUTPUT: I am a normal method defined inside the abstract class 'Shape' Area of a rectangle: 15 Area of a circle: 50.24 """ Example2:
class Fruit: def taste(self): raise NotImplementedError() def contains(self): raise NotImplementedError() def color(self): raise NotImplementedError() class Mango(Fruit): def taste(self): return "Sweet" def contains(self): return "Vitamin A"
def color(self): return "Yellow" class Orange(Fruit): def taste(self): return "Sour" def contains(self): return "Vitamin C" def color(self): return "Orange" m=Mango() print(m.taste(),m.contains(),m.color()) o=Orange() print(o.taste(),o.contains(),o.color()) """ OUTPUT: Sweet Vitamin A Yellow Sour Vitamin C Orange """
Recommended