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

  1. single inheritance:

  2. multiple inheritance,

  3. multi-level inheritance,

  4. hierarchical inheritance

  5. 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:

  1. Object-Oriented-Programming-Practice-Sheet-1 : https://colab.research.google.com/drive/1aMfP2glGKZSikQcjzaxPhR1Ja36mLqxI