Polymorphism with Function and Objects: -
§ In
Python we cannot specify the type explicitly. Based on provided value at
runtime the type will be considered automatically. Hence Python is considered
as Dynamically Typed Programming Language.
§ You
can create a function that can take any object, allowing for polymorphism.
def figure(obj):
obj.draw()
§ What
is the type of obj? We cannot decide at the beginning. At runtime we can pass
any type. Then how we can decide the type?
§ Let’s
take an example and create a function called 'figure()' which will take
an object which we will name 'obj'. Now, let’s give the function
something to do that uses the 'obj' object we passed to it.
§ In
this case, let’s call the methods draw () and color (), each of which is
defined in the three classes 'Circle' and 'Rectangle’, ‘Square'. Now, you have
to create instantiations of these classes:
class Circle:
def draw(self):
print('Circle
Shape Draw!.')
def color(self):
print('Yellow
Color Fill In Circle!.')
class Rectangle:
def draw(self):
print('Rectangle
Shape Draw!.')
def color(self):
print('Green
Color Fill In Rectangle!.')
class Square:
def draw(self):
print('Square
Shape Draw!.')
def color(self):
print('Pink
Color Fill In Square!.')
#define function for Polymorphism
def figure(obj):
obj.draw()
obj.color()
l=[Circle(),Rectangle(),Square()]
for obj in l:
figure(obj)
print('===========================')
output:
Circle Shape Draw!.
Yellow Color Fill In
Circle!.
====================
Rectangle Shape Draw!.
Green Color Fill In
Rectangle!.
====================
Square Shape Draw!.
Pink Color Fill In
Square!.
====================
§
The
problem in this approach is if obj does not contain draw() method then we will
get AttributeError
class Circle:
def draw(self):
print('Circle
Shape Draw!.')
class Rectangle:
def paint(self):
print('Rectangle
Shape Paint!.')
class Square:
def draw(self):
print('Square
Shape Draw!.')
class Triangle:
def paint(self):
print('Triangle Shape Paint!.')
#define function for Polymorphism
def figure(obj):
obj.draw()
l=[Circle(),Rectangle(),Square(),Triangle]
for obj in l:
figure(obj)
print('===========================')
output:
Circle Shape Draw!.
===========================
obj.draw()
AttributeError:
'Rectangle' object has no attribute 'draw'
Demo
Program with hasattr() function:
§ The hasattr()
method returns true if an object has the given named attribute and false if it
does not.
The syntax of
hasattr() method is:
hasattr(object, name)
The hasattr()
method takes two parameters:
object
- object whose named attribute is to be checked
name -
name of the attribute to be searched.
§ In The given
figure there are four classes Circle,Rectangle,Square,Triangle where Circle,
Square classes contain draw() method and Rectangle,Triangle classes contain
paint() method.
class Circle:
def draw(self):
print('Circle
Shape Draw!.')
class Rectangle:
def paint(self):
print('Rectangle
Shape Paint!.')
class Square:
def draw(self):
print('Square
Shape Draw!.')
class Triangle:
def paint(self):
print('Triangle
Shape Paint!.')
#define function for Polymorphism
def figure(obj):
if
hasattr(obj,'draw'):
obj.draw()
elif
hasattr(obj,'paint'):
obj.paint()
#Create a list which
contain given class object
l=[Circle(),Rectangle(),Square(),Triangle()]
for obj in l:
figure(obj)
print('===========================')
output:
Circle Shape Draw!.
===========================
Rectangle Shape Paint!.
===========================
Square Shape Draw!.
===========================
Triangle Shape Paint!.
===========================
§ Polymorphism
with Instance Methods
§ See the above,
diagram in the given diagram there are three classes. All the classes have two
methods. Now we will see how to call. Here, you have to create a for loop that
iterates through a tuple of objects. Next, you have to call the methods without
being concerned about which class type each object is. We assume that these
methods actually exist in each class.
class India():
def capital(self):
print("New
Delhi")
def language(self):
print("Hindi
and English")
class USA():
def capital(self):
print("Washington,
D.C.")
def language(self):
print("English")
class Europe():
def capital(self):
print("Brussels")
def language(self):
print("French")
obj_ind = India()
obj_usa = USA()
obj_eur=Europe()
for
country in (obj_ind, obj_usa,obj_eur):
country.capital()
country.language()
output:
New Delhi
Hindi and English
Washington, D.C.
English
Brussels
French
Method
Overriding in Python
v
If
the child class not satisfy the parent class method implementation then it is
possible to override that method in the child class based on child class
requirement.
v
Whatever
methods parent has by default available to the child through inheritance. Sometimes
child may not satisfy with parent method implementation. Then child is allowed
to redefine that method based on its requirement. This process is called
overriding.
v
It's
an approach of re-implementing a parent classes method under the child class
with the same signature.
The parent class method which is overridden is called overridden method.
The child class method which is overriding is called overriding method.
The parent class method is
called-------------overridden method
The child class method is
called---------------overriding method
§ When the child
inherits the features from his parent, the child may be happy with those features
of the parent but sometimes the child may not be happy with those features of
the parent if the child is not satisfied with those features of the parent.
then child Can override those features of the parent. this is nothing it is
overriding.
§ In the given
example, the parent has three method such as the parent has taken the decision
to purchase the hero bike but may be child not be happy with this decision of the
parent, may be the child wants to buy another bike, then the child Can override
the parent decision
class Parent:
def property(self):
print('Parent
has Money,Gold')
def purchaseBike(self):
print('parent
wants to purchase Hero Bike!')
def marry(self):
print('parent
decide marry with Black girl!')
class Child(Parent):
def purchaseBike(self):
print('Child
wants to purchase R1-5 Bike!')
def marry(self):
print('Child
decide marry with White girl!')
#Creating Parent class
object
print('With
respect to parent object!.')
p=Parent()
p.property()
p.purchaseBike()
p.marry()
#Creating Child class
object
print('With
respect to child object!.')
c=Child()
c.property()
c.purchaseBike()
c.marry()
output:
With respect to parent object!.
Parent has Money,Gold
parent wants to purchase Hero Bike!
parent decide marry with Black
girl!
With respect to child object!.
Parent has Money,Gold
Child wants to purchase R1-5 Bike!
Child decide marry with White girl!
Real example of Java Method Overriding
class Bank:
def getRateOfInterest(self):
return 0
class SBI(Bank):
def getRateOfInterest(self):
return 7
class ICICI(Bank):
def getRateOfInterest(self):
return 8
class AXIS(Bank):
def getRateOfInterest(self):
return 9
#creating an object
s= SBI();
print('SBI
Rate of Interest: ',s.getRateOfInterest())
i= ICICI();
print('ICICI
Rate of Interest: ',i.getRateOfInterest())
a= AXIS();
print('AXIS
Rate of Interest: ',a.getRateOfInterest())
output:
SBI Rate of
Interest: 7
ICICI Rate of
Interest: 8
AXIS Rate of
Interest: 9
Another Example:
class Animal:
def eating(self):
print('Animal
Eating!.')
class Lion(Animal):
def eating(self):
print('Lion
is eating meat!.')
class Cow(Animal):
def eating(self):
print('Cow
is eating grass!.')
#creating an object
a=Animal()
a.eating()
l=Lion()
l.eating()
c=Cow()
c.eating()
output:
Animal Eating!.
Lion is eating meat!.
Cow is eating grass!.
Overloading In Python
§ When we are using
operator or method for different purpose then it is known as operator or method
overloading.
§ Overloading refers
to the ability of a function or an operator to behave in different
ways
depending on the parameters that are passed to the function, or the operands
that the operator acts on.
There
are 3 types of overloading
1.
Operator
Overloading
2.
Method
Overloading
3.
Constructor
Overloading
Operator
Overloading
§ Python allows us
to change the default behavior of an operator depending on the operands that we
use. This practice is referred to as "operator overloading".
§ Python supports
operator overloading.
operand1 + operand2
§ when we are
applying + operator between both operand if both operand numeric types then it
will perform default behavior addition.
print(10+20)#the
output:30
§ when we are
applying + operator between both operand if both operand str types then you
must have noticed its different behavior and then it will perform String concatenation.
print('hello'+'world')#the
output:helloworld
§ when we are
applying + operator between both operand if both operand list types then you
must have noticed its different behavior and then it will perform list merge operation.
[10,20,30] + [40,50]
= [10,20,30,40,50]
§ It is possible
because + operator is overloaded by both int class and str class
* operator can be used for multiplication and
string repetition purposes.
§ If you want to
represent any object as a string, then __str__method comes into picture.
§ The __str__()method returns the
string representation of the object.
§ If you print any
object, python compiler internally invokes the __str__ method on the
object.
§ So, overriding the
__str__method, returns
the desired output.
class Point:
def __init__(self,
x = 0, y = 0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x,self.y)
#creating an object
p1=Point(10,20)
print(p1)
output:
(10,20)
Overloading the + Operator in Python
class Point:
def __init__(self,
x = 0, y = 0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x,self.y)
#creating first point
object
p1=Point(10,20)
#creating second point
object
p2=Point(30,40)
p3=p1+p2
print(p3)
p3=p1+p2
TypeError: unsupported
operand type(s) for +: 'Point' and 'Point'
TypeError
was raised since Python didn't know how to add two Point objects
together.actually + operator doesn't know
what to do when we are apply between two point object.
§
To
achieve operator overloading, we define a special method in a class definition.
The name of the method should begin and end with a double underscore (__). The
+ operator is overloaded using a special method named __add__
class Point:
def __init__(self,
x = 0, y = 0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x,self.y)
def __add__self,other):
x = self.x + other.x
y = self.y + other.y
return
Point(x,y)
#creating first point
object
p1=Point(10,20)
#creating second point
object
p2=Point(30,40)
p3=p1+p2
print('Point1
=',p1)
print('Point2=
',p2)
print('Sum
of Points= ',p3)
output:
Point1 = (10,20)
Point2= (30,40)
Sum of Points= (40,60)
What
actually happens is that, when you do p1 + p2, Python will call p1.__add__(p2)
which in turn is Point.__add__(p1,p2)
The following is
the list of operators and corresponding magic methods.
OPERATOR
|
MAGIC METHOD
|
+
|
__add__(self,
other)
|
–
|
__sub__(self,
other)
|
*
|
__mul__(self,
other)
|
/
|
__truediv__(self,
other)
|
//
|
__floordiv__(self,
other)
|
%
|
__mod__(self,
other)
|
**
|
__pow__(self,
other)
|
Comparison
Operators :
OPERATOR
|
MAGIC METHOD
|
<
|
__lt__ (self,
other)
|
>
|
__gt__ (self,
other)
|
<=
|
__le__ (self,
other)
|
>=
|
__ge__ (self,
other)
|
==
|
__eq__ (self,
other)
|
!=
|
__ne__ (self,
other)
|
§ Overloading
> and <= operators for Person class objects:
p1>p2
i.e. p1 person is older than p2 person
p1<p2
i.e. p1 person is younger than p2 person
p1==p2
i.e. p1 person and p2 person both is equal in age.
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
def __gt__(self,other):
return
self.age>other.age
def __lt__(self,other):
return
self.age<other.age
def __eq__(self,other):
return
self.age==other.age
#Creating first person object
p1=Person('Scott',50)
#Creating second person object
p2=Person('John',90)
if p1>p2:
print(p1.name,'is
older than',p2.name)
elif p1<p2:
print(p2.name,'is
older than',p1.name)
elif p1==p2:
print(p1.name,'and',p2.name,'is
equal in age')
output:
John is older than
Scott
=======================
p1>p2= False
p1<p2= True
p1==p2 False