OOP With Python
OOP With Python
Python is an object-oriented programming language. Due to that creation and usage of class
and object is very much easy. You can implement any of the OOP concepts using python.
1. Terminologies:
• Class: A user-defined prototype for an object that defines a set of attributes that
characterise any object of the class. The attributes are data members (class variables
and instance variables) and methods, accessed via dot notation.
• Data member: A class variable or instance variable that holds data associated with a
class and its objects.
• Class variable: A variable that is shared by all instances of a class.
• Instance: An individual object of a certain class. An object obj that belongs to a class
Circle, for example, is an instance of the class Circle.
• Instance variable: A variable that is defined inside a method and belongs only to the
current instance of a class.
• Instantiation: The creation of an instance of a class.
• Method: − A special kind of function that is defined in a class definition.
• Inheritance: − The transfer of the characteristics of a class to other classes that are
derived from it.
• Function overloading: The assignment of more than one behaviour to a particular
function. The operation performed varies by the types of objects or arguments
involved.
• Operator overloading: The assignment of more than one function to a particular
operator.
• The class has a documentation string, which can be accessed via ClassName.__doc__.
• The class_suite consists of all the component statements defining class members, data
attributes and functions.
1
• Classes support multiple copies. This is because classes have two different objects:
class objects and instance objects.
• Instance objects are normally marked by the keyword self, so a class method could be
Employee.Display() while a specific instance of the Display() method would be marked
as self.Display().
• Each instance object has its own namespace but also inherits from the base class
object.
• Classes can define objects that respond to the same operations as built-in types.
Example 1:
class MyClass:
variable = "Hello"
def function(self):
print('Inside Class')
print(MyClass)
Output:
<class '__main__.MyClass'>
❖ Delete Object
We can delete objects by using the del keyword
del e1
Example 2:
class Employee:
'Common base class for all employees'
empCount = 0
age=10
def displayCount(self):
2
print("Total Employee %d" %Employee.empCount)
def displayEmployee(self):
print("Name : ", self.name, ", Salary: ", self.salary
)
e1=Employee("Hetal",50000)
e1.displayCount()
e1.displayEmployee()
e2=Employee("Ved",45000)
e2.displayCount()
e2.displayEmployee()
Output:
Total Employee 1
Name :Hetal , Salary: 50000
Total Employee 2
Name :Ved , Salary: 45000
Age of e1 : 8
• The first method __init__() is a special method, which is called class constructor or
initialization method that Python calls when you create a new instance of this class.
• Python adds the self argument to the list for you; you do not need to include it when
you call the methods.
• 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:
In example 2,
• The variable empCount is a class variable whose value is shared among all instances of
a this class. This can be accessed using an object of a class from inside the class or
outside the class.
• The first method __init__() is a special method, which is called class constructor or
initialisation method that Python calls when you create a new instance of this class.
Note: The __init__() function is called automatically every time the class is being used to
create a new object.
3
❖ The self Parameter
• The self parameter is a reference to the current instance of the class, and is used to
access variables that belongs 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:
Example 3:
class Person:
def __init__(myobj, name, age):
myobj.name = name
myobj.age = age
def func(x):
print("My name is " + x.name)
p1 = Person("Heta", 30)
p1.func()
Output:
My name is Heta
Note: The self parameter is a reference to the current instance of the class, and is used to
access variables that belong to the class.
Example 4:
class Employee:
'Common base class for all employees'
empCount = 0
4
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
)
print("Employee.__doc__:", Employee.__doc__)
print("Employee.__name__:", Employee.__name__)
print("Employee.__module__:", Employee.__module__)
print("Employee.__bases__:", Employee.__bases__)
print("Employee.__dict__:", Employee.__dict__)
Output:
Employee.__doc__: Common base class for all employees
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: (<class 'object'>,)
Employee.__dict__: {'__module__': '__main__', '__doc__':
'Common base class for all employees', 'empCount': 0,
'__init__': <function Employee.__init__ at 0x7f63c2522200>,
'displayCount': <function Employee.displayCount at
0x7f63c2522dd0>, 'displayEmployee': <function
Employee.displayEmployee at 0x7f63c2522440>, '__dict__':
<attribute '__dict__' of 'Employee' objects>, '__weakref__':
<attribute '__weakref__' of 'Employee' objects>}
5
3. Inheritance
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.
class BaseClass:
Body of base class
class DerivedClass(BaseClass):
Body of derived class
Example 5:
class Parent: # define parent class
parentAttr = 100
def __init__(self):
print("Calling parent constructor")
def parentMethod(self):
print('Calling parent method')
def display(self):
print("Parent attribute :", Parent.parentAttr)
def childMethod(self):
print('Calling child method')
A=Parent()
B=Child()
A.parentMethod()
B.childMethod()
B.parentMethod()
B.setAttr(10)
B.display()
Output:
Calling parent constructor
Calling child constructor
Calling parent method
6
Calling child method
Calling parent method
Parent attribute : 10
Example 6:
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname
def printname(self):
print(self.firstname, self.lastname)
class Student(Person):
pass
Output:
Hetal Patel
Example 7:
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname
print("Initialization in Parent Class")
7
def printname(self):
print(self.firstname, self.lastname)
class Student(Person):
def __init__(self, fname, lname):
Person.__init__(self, fname, lname)
x = Student("Hetal", "Patel")
x.printname()
Output:
Initialization in Parent Class
Hetal Patel
❖ super() Function
Python also has a 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 8:
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname
def printname(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)
Output:
8
❖ Overriding Methods
When the method is defined in both classes (Base class and derived class) then the method
in the derived class overrides that in the base class.
• Generally when overriding a base method, we tend to extend the definition rather
than simply replace it. The same is being done by calling the method in base class
from the one in derived class (calling Person.__init__() from __init__() in Student).
• A better option would be to use the built-in function super().
Two built-in functions isinstance() and issubclass() are used to check inheritances.
• The function isinstance() returns True if the object is an instance of the class or other
classes derived from it.
• Each and every class in Python inherits from the base class object.
Example 9:
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname
def printname(self):
print(self.firstname, self.lastname)
class Student(Person):
def __init__(self, fname, lname):
super().__init__(fname, lname)
x = Student("Ved", "Shah")
x.printname()
y = Person("Saloni","Patel")
y.printname()
print("\nUse of isinstance()")
print(isinstance(x,Student))
print(isinstance(x,Person))
print(isinstance(x,object))
print(isinstance(y,Student))
9
Output:
Ved Shah
Saloni Patel
Use of isinstance()
True
True
True
False
Use of issubclass()
True
False
4. Operator Overloading
• The assignment of more than one function to a particular operator.
• You can change the meaning of an operator in Python depending upon the operands
used.
• Python operators work for built-in classes. But the same operator behaves differently
with different types.
• This feature in Python that allows the same operator to have different meaning
according to the context is called operator overloading.
Example 10:
class Addition:
10
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return "({0},{1})".format(self.x, self.y)
p1 = Addition(10, 20)
p2 = Addition(10, 50)
Output:
Addition of Two Points on 2D = (20,70)
Here in above Example, when you use p1 + p2, Python calls p1.__add__(p2) which in turn is
Addition.__add__(p1,p2).
Addition p1 + p2 p1.__add__(p2)
Subtraction p1 - p2 p1.__sub__(p2)
Multiplication p1 * p2 p1.__mul__(p2)
Power p1 ** p2 p1.__pow__(p2)
Division p1 / p2 p1.__truediv__(p2)
11
Bitwise Right Shift p1 >> p2 p1.__rshift__(p2)
Bitwise OR p1 | p2 p1.__or__(p2)
def __str__(self):
return "({0},{1})".format(self.x, self.y)
p1 = Point(1,1)
p2 = Point(-2,-3)
p3 = Point(1,-1)
Output:
True
False
False
12
To overload other comparison operators are tabulated below.
Equal to p1 == p2 p1.__eq__(p2)
5. Data Hiding
• An object's attributes may or may not be visible outside the class definition.
• You need to name attributes with a double underscore prefix, and those attributes
then are not be directly visible to outsiders.
Example 12:
class JustCounter:
__secretCount = 0
def count(self):
self.__secretCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print(counter.__secretCount) # Error in the line
Output:
1
2
AttributeError: 'JustCounter' object has no attribute
'__secretCount'
13
• Python protects those members by internally changing the name to include the class
name.
• You can access such attributes as object._className__attrName.
• So modified code is for Example 12 is given in example 13
Example 13:
class JustCounter:
__secretCount = 0
def count(self):
self.__secretCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print(counter._JustCounter__secretCount)
Output:
1
2
2
6. Multithreading
• Multiple threads within a process share the same data space with the main thread and
can therefore share information or communicate with each other more easily than if
they were separate processes.
• Threads sometimes called light-weight processes and they do not require much
memory overhead; they are cheaper than processes.
• It can be pre-empted (interrupted)
• It can temporarily be put on hold (also known as sleeping) while other threads are
running - this is called yielding.
❖ Benefits of Threading
• For a single process, multiple threads can be used to process and share the same data-
space and can communicate with each other by sharing information.
• They use lesser memory overhead, and hence they are called lightweight processes.
• A program can remain responsive to input when threads are used.
• Threads can share and process the global variable's memory.
In a thread, there are three different parts. It has the beginning, an execution part, and a
conclusion. It also has an instruction pointer that points to where the thread or process is
14
currently running, and hence the thread can run several different program blocks
concurrently.
Here, the first part is a method & this method is a faster and more efficient way to create
new threads. As the child thread starts, the function passes a list of args. The thread gets
terminated when the function returns a value.
The 'args' in the above syntax is a tuple of arguments.
15