Object-Oriented Programming in Python3
We can think as though we're working with real-life items or objects when we use an object-oriented programming approach.
Python having many kind of datatype such as int, float, string etc. In python everything is an object.
Every objects having type and methods.
Object: object is an run time entity. It is an instance of a particular type.
Example :
f=2.3,4.5,2.1 so every values of float is going to store as an instance.
Class Keyword : class provides a blueprint or a template using which objects are created.
Defining class:
class Class_Name:
statement 1
.
.
Statement N
A class creates a new local namespace where all its attributes( data and functions) are defined.
class Student :
def __init__(self):
self.rollNumber = 987654
self.name='Ram Krishn Mishra'
In above class structure colon (:) define the class block
Atributes : rollnumber and name
init() : constructor of class
self parameter : refers to the newly created instance of the class.66060 60 0 60
attributes rollnumber and name are associated with self-keyword to identify them as instance variables.
Creating Object :
Once the class is created , next job is to create an object or an instance of the class. Object can be created by class name of the class followed by parenthesis.
object_name=Class_name()
Example creating an object of student:
s1 = Student()
print("Roll Number=", s1.rollNumber, "\nName=", s1.name)
Parameterized constructor:
parametrized constructor - dynamically assign the attribute values during object creation
class Rectangle :
def __init__(self, length, breadth):
self.length = length
self.breadth = breadth
rect = Rectangle(10, 5)
print("Length = ",rect.length, "\nBreadth = " ,rect.breadth)
Class Variable and Instance variables
class Circle :
pi = 3.14
def __init__(self, radius):
self.radius = radius
circle_1 = Circle(5)
print("Radius = {} \t pi = {}".format(circle_1.radius,circle_1.pi))
circle_2 = Circle(2)
print("Radius = {} \t pi = {}".format(circle_2.radius,circle_2.pi))
circle_1 = Circle(5)
print("Radius = {} \t pi = {}".format(circle_1.radius,circle_1.pi))
circle_2 = Circle(2)
print("Radius = {} \t pi = {}".format(circle_2.radius,circle_2.pi))
Circle.pi = 3.1436
circle_1 = Circle(5)
print("Radius = {} \t pi = {}".format(circle_1.radius,circle_1.pi))
circle_2 = Circle(2)
print("Radius = {} \t pi = {}".format(circle_2.radius,circle_2.pi))
Adding a method to class
calculate_area() - retutns the product of attributes length and breadth
self - identifies its association with the instance
In [9]:
class Rectangle :
def __init__(self, length, breadth):
self.length = length
self.breadth = breadth
def calculate_area(self):
return self.length * self.breadth
rect = Rectangle(10,5)
print("Length = ",rect.length, "\nBreadth = " ,rect.breadth, "\nArea = ", rect.calculate_area())
Length = 10
Breadth = 5
Area = 50
Significance of self:
The attributes length and breadth are associated with an instance.
Self makes sure that each instance refers to its own copy of attributes
new_rect = Rectangle(15, 8)
print("Length = ",new_rect.length, "\nBreadth = " ,new_rect.breadth, "\nArea = ", new_rect.calculate_area())
Length = 15
Breadth = 8
Area = 120
print("Length = ",rect.length, "\nBreadth = " ,rect.breadth, "\nArea = ", rect.calculate_area())
Length = 10
Breadth = 5
Area = 50
Class Method and Static Method
In [34]:
class Circle :
pi = 3.14
def __init__(self, radius):
self.radius = radius
# Instance Method
def calculate_area(self):
return Circle.pi * self.radius
# Class Method - It cannot access - radius
@classmethod
def access_pi(cls):
cls.pi = 3.1436
# Static Method - It cannot access - pi and radius
@staticmethod
def circle_static_method():
print("This is circle's static method")
cir = Circle(5)
3.14
This is circle's static method
Inheritance and Overriding
class Shape :
def set_color(self, color):
self.color = color
def calculate_area(self):
pass
def color_the_shape(self):
color_price = {"red" : 10, "blue" : 15, "green" : 5}
return self.calculate_area() * color_price[self.color]
class Circle(Shape) :
pi = 3.14
def __init__(self, radius):
self.radius = radius
def calculate_area(self):
return Circle.pi * self.radius
c = Circle(5)
c.set_color("red")
print("Circle with radius =",c.radius ,"when colored", c.color,"costs $",c.color_the_shape())
Circle with radius = 5 when colored red costs $ 157.0
class Rectangle(Shape) :
def __init__(self, length, breadth):
self.length = length
self.breadth = breadth
# Overriding user defined method
def calculate_area(self):
return self.length * self.breadth
# Overriding python default method
def __str__(self):
return "area of rectangle = " + str(self.calculate_area())
r = Rectangle(5, 10)
r.set_color("blue")
print("Rectangle with length =",r.length ," and breadth = ",r.breadth ,"when colored", r.color,"costs $",r.color_the_shape())
Rectangle with length = 5 and breadth = 10 when colored blue costs $ 750
Simple Animal Class Creation:
class Animal:
def elephant_call(self):
print("Making Elephant Function Call")
def horse_call(self):
print("Calling Hourse Function Call")
Creating Object:
a1=Animal()
a1.elephant_call()
a1.horse_call()
Output:
Making Elephant Function Call
Calling Hourse Function Call
Student Class
class Student:
"This is common class for all students"
scount=0
def __init__(self, rollno, name, course):
self.rollno=rollno
self.name=name
self.course=course
Student.scount+=1
def displayCount(self):
print("Total Students=", Student.scount)
def displayStd(self):
print('Roll Number : ', self.rollno)
print('Name : ', self.name)
print('Course: ', self.course)
Object Creation
#object Creation
s1=Student(12345, "Ram Krishn", "PhD")
s2=Student(456789, "Mishra", "ME")
s1.displayStd()
s2.displayStd()
s1.displayCount()
Output
Roll Number : 12345
Name : Ram Krishn
Course: PhD
Roll Number : 456789
Name : Mishra
Course: ME
Total Students= 2
ACCESS MODIFIERS (PUBLIC, PRIVATE AND PROTECTED) in Python
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.
INHERITANCE in Python
Inheritance is a mechanism in which one class (derived class) acquires the property of another class (base class). With inheritance, we can reuse the variables and methods of the existing class. The existing class is called base class and the new class is called derived class.
Hence, inheritance facilitates reusability and is an important concept of object oriented programming.
Types of inheritance
single inheritance:
multiple inheritance,
multi-level inheritance,
hierarchical inheritance
hybrid inheritance.
Single inheritance enables a derived class to use the variables and functions defined in an existing class. In multiple inheritance, derived class inherits the characteristics and features from more than one existing classes.
In python, syntax for defining single inheritance is class z(x), where x is the name of the base class and z is the name of the derived class. Similarly, multiple inheritance is defined using the syntax class z(x, y), where x and y are the names of base classes and z is the name of the derived class.
Advantages of inheritance
Inheritance is the capability of one class to derive or inherit the properties from some another class. The benefits of inheritance are:
It represents real-world relationships well.
It provides reusability of a code. We don’t have to write the same code again and again. Also, it allows us to add more features to a class without modifying it.
It is transitive in nature, which means that if class B inherits from another class A, then all the subclasses of B would automatically inherit from class A
Inheritance Example
# person is a base class
class person:
def __init__(self, n, a):
self.name = n
self.age = a
# employee is the class derived from person using single inheritance
class employee(person):
def __init__(self,n, a, d, s):
person.__init__(self,n,a)
self.designation=d
self.salary=s
def show(self):
print("Employee Details: ")
print(" Name: ",self.name,"\n Age:",self.age, "\n Designation:",self.designation, "\n Salary:",self.salary)
# student is a base class
class student:
def __init__(self, id, rno):
self.studentId = id
self.roomno=rno
# resident is a class derived from person and student using multiple inheritance
class resident(person, student):
def __init__(self, n, a, id,rno):
person.__init__(self, n, a)
student.__init__(self, id,rno)
def show(self):
print("Resident Details:")
print(" Name:", self.name,"\n Age: ",self.age, "\n Id:" ,self.studentId,"\n Room no.:",self.roomno)
# Creating objects of employee and resident classes
e1 =employee("Arun",35,"Data analyst",50000)
r1 = resident("John", 30, 201900025,203)
e1.show()
r1.show()
Output:
Employee Details:
Name: Arun
Age: 35
Designation: Data analyst
Salary: 50000
Resident Details:
Name: John
Age: 30
Id: 201900025
Room no.: 203
[ ]:
OPERATOR OVERLOADING
Operator overloading allow us to redefine the way operator works for user-defined types such as objects. It cannot be used for built-in types such as int, float, char etc., For example, '+' operator can be overloaded to perform addition of two objects of distance class.
Python provides some special function or magic function that is automatically invoked when it is associated with that particular operator. For example, when we use + operator on objects, the magic method add () is automatically invoked in which the meaning/operation for + operator is defined for user defined objects.
METHOD OVERLOADING
In Python you can define a method in such a way that there are multiple ways to call it. Depending on the function definition, it can be called with zero, one, two or more parameters.
Method Overloading Example
class distance:
def __init__(self, f, i):
self.feet = f
self.inches = i
# overloading of binary operator > to compare two distances
def __gt__(self, d):
if (self.feet > d.feet):
return (True)
elif ((self.feet == d.feet) and (self.inches > d.inches)):
return (True)
else:
return (False)
# overloading of binary operator + to add two distances
def __add__(self, d):
i = self.inches + d.inches
f = self.feet + d.feet
if (i >= 12):
i = i - 12
f = f + 1
return distance(f, i)
# displaying the distance
def show(self):
print("Feet= ", self.feet, "Inches= ", self.inches)
a, b = (input("Enter feet and inches of distance1: ")).split()
a, b = [int(a), int(b)]
c, d = (input("Enter feet and inches of distance2: ")).split()
c, d = [int(c), int(d)]
d1 = distance(a, b)
d2 = distance(c, d)
if (d1>d2):
print("Distance1 is greater than Distance2")
else:
print("Distance2 is greater or equal to Distance1")
d3 = d1 + d2
print("Sum of the two Distance is:")
d3.show()
Ouput:
Enter feet and inches of distance1: 10 25
Enter feet and inches of distance2: 45 32
Distance2 is greater or equal to Distance1
Sum of the two Distance is:
Feet= 56 Inches= 45
METHOD OVERRIDING IN PYTHON
Overriding is the ability of a class to change the implementation of a method provided by one of its ancestors. Overriding is a very important part of OOP since it is the feature that makes inheritance exploit its full power. Through method overriding a class may "copy" another class, avoiding duplicated code, and at the same time enhance or customize part of it. Method overriding is thus a strict part of the inheritance mechanism.
As for most OOP languages, in Python inheritance works through implicit delegation: when the object cannot satisfy a request, it first tries to forward the request to its ancestors, following the specific language rules in the case of multiple inheritance.
class Parent(object):
def __init__(self):
self.value=20
def get_value(self):
return self.value
class Child(Parent):
pass
c = Child()
c.get_value()
Attachment:
Object-Oriented-Programming-Practice-Sheet-1 : https://colab.research.google.com/drive/1aMfP2glGKZSikQcjzaxPhR1Ja36mLqxI