Inheritance refers to defining a new class with little or no modification to an existing class
Inheritance allows to define a class that takes all the methods and properties from parent class and allows to add more functions
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
class BaseClass:
Body of base class
class DerivedClass(BaseClass):
Body of derived class
Derived class is declared with the BaseClass inside parentheses
Consider a class called File
defined as follows
import os
class File:
def __init__(self, file_type, file_name):
self.file_type = file_type
self.file_name = file_name
def fileSize(self):
return os.path.getsize(self.file_name)
This class has data attributes to store the name of a file as file_name and its type file_type and method fileSize()
returns the size of the file
A class called Image
can be created which inherits fromFile
This makes all the attributes of class File
to be available in Image
, and need not be defined again (code re-usability)
from PIL import Image as PilImage
class Image(File):
def __init__(self, file_name):
img = PilImage.open(file_name)
File.__init__(self, img.format, file_name)
def getHeight(self):
im = PilImage.open(self.file_name)
return im.size[1]
def getWidth(self):
im = PilImage.open(self.file_name)
return im.size[0]
Class Image
has new methods getHeight()
and getWidth()
to find the height and width of an Image
Here is a sample run, assuming a file test.jpg exists in the same directory where it is run :
>>> t = Image("test.jpg")
>>> t.fileSize()
13123
>>> t.getHeight()
500
>>> t.getWidth()
800
It shows that class Image
could use method fileSize()
of class File
If an attribute is not found in a class, search continues to its base class
This repeats further, if the base class is itself derived from other classes
A subclass can override methods of its parent class
This is done in case the subclass requires a different or additional functionality for the same method than its Parent
In the above example, __init__()
method was defined in both classes, File
and Image
This denotes that __init__()
in Image
gets preference over the same in File
, when called by an object of Image
Here, the __init__()
method of File
is also called from __init__()
in Image
(denoted by the line File.__init__(self, img.format, file_name)
)
The same can be done by using built-in function super()
, which refers to the parent of a derived class
So, File.__init__(self, img.format, file_name)
can be replaced with super().__init__(self, img.format, file_name)
#!/usr/bin/python
# define parent class
class Parent:
def myMethod(self):
print'Calling parent method'
# define child class
class Child(Parent):
def myMethod(self):
print'Calling child method'
# instance of child
c =Child()
c.myMethod() #child calls overridden method
When the above code is executed, it produces the following output :
Calling child method
isinstance()
and issubclass()
methods Two built-in functions isinstance()
and issubclass()
can be used to check inheritance
The isinstance(obj, Class)
boolean function returns true if obj
is an instance of class Class
or is an instance of a subclass of Class
Every class in Python inherits from the base class object
>>> isinstance(t, Image)
True
>>> isinstance(t, File)
True
>>> isinstance(t,int)
False
>>> isinstance(t,object)
True
The issubclass(sub, sup)
boolean function returns true if the given class sub
is a subclass of the class sup
>>> issubclass(File, Image)
False
>>> issubclass(Image, File)
True
>>> issubclass(bool, int)
True
A class can be inherited from multiple parent classes as follows :
# define your class A
class A:
.....
# define your class B
class B:
.....
# subclass of A and B
class C(A, B):
....
For example, consider a class Shared
as
class Shared:
def __init__(self, userList):
self.users = userList
def canOpen(self, username):
if username in self.users:
return True
else:
return False
Then a class SharedImage
can be defined as
class SharedImage(Image, Shared):
def __init__(self, file_name, userList):
Image.__init__(self, file_name)
Shared.__init__(self, userList)
Objects of class SharedImage
can access methods of Image
and Shared
Following table lists some generic functionality that you can override in your own classes -
Consider a class SomeClass
Sr.No | Method | Description | Example |
---|---|---|---|
1 | __init__ ( self [,args...] ) | Constructor (with any optional arguments) | obj = SomeClass(args) |
2 | __del__( self ) | Destructor, deletes an object | del obj |
3 | __repr__( self ) | Evaluable string representation | repr(obj) |
4 | __str__( self ) | Printable string representation | str(obj) |
5 | __cmp__ ( self, x ) | Object comparison | cmp(obj, x) |
Classes can have methods to overload functionality of operators like +
-
This way, behaviour of using operators for objects of these classes can be manipulated
To define the behaviour of +
(plus) operator, __add__
method has to be added to a class
#!/usr/bin/python
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' %(self.a,self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print(v1 + v2)
When the above code is executed, it produces the following output :
Vector(7,8)
An object's attributes may or may not be visible outside the class definition
Attributes and methods can be named with a double underscore prefix, so that these attributes are then not directly visible from its caller or derived class
#!/usr/bin/python
class JustCounter:
__secretCount =0
def count(self):
self.__secretCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print counter.__secretCount
When the above code is executed, it produces the following output :
1
2
Traceback (most recent call last):
File "test.py", line 12, in <module>
print counter.__secretCount
AttributeError: JustCounter instance has no attribute '__secretCount'
Python protects those members by internally changing the name to include the class name
Such attributes can be accessed as object._className__attrName
Replace last line of above example as following, to make it work :
print counter._JustCounter__secretCount
It then produces the following output :
1
2
2