0% found this document useful (0 votes)
0 views33 pages

Python Book Chapter 3

This document provides a comprehensive overview of Python Object-Oriented Programming, focusing on the concepts of classes, objects, methods, constructors, and destructors. It explains how to define classes, create instances, and utilize various types of variables and methods, including instance, static, and local variables. Additionally, it highlights the differences between methods and constructors, as well as the role of destructors in resource management.

Uploaded by

yashvar1211
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
0 views33 pages

Python Book Chapter 3

This document provides a comprehensive overview of Python Object-Oriented Programming, focusing on the concepts of classes, objects, methods, constructors, and destructors. It explains how to define classes, create instances, and utilize various types of variables and methods, including instance, static, and local variables. Additionally, it highlights the differences between methods and constructors, as well as the role of destructors in resource management.

Uploaded by

yashvar1211
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Unit-3

Python Object Oriented Programming

3.1. Concept of class, object and instances, method call


3.1.1. Class Introduction:

In Python, everything is treated as an object. To create objects, we need a model, plan, or blueprint,
which is known as a class. A class is used to define the properties (attributes) and actions (behaviors)
of objects. Properties are represented by variables, while actions are represented by methods.
Hence class contains both variables and methods.

How to define Class?


Define a class by using class keyword.
Syntax:
class className:
''' documenttation string '''

variables:instance variables,static and local variables methods:


instance methods,static methods,class methods

Documentation string represents description of the class. Within the class doc string is always optional.
2 ways to get doc string-
1. print(classname. doc )
2. help(classname)

Example:
1) class Student:
2) ''''' This is student class with required data'''
3) print(Student. doc )
4) help(Student)

Within the Python class we can represent data by using variables. 3 types of variables are follows-
1. Instance Variables (Object Level Variables)
2. Static Variables (Class Level Variables)
3. Local variables (Method Level Variables)

Within the Python class, we can represent operations by using methods. Various types of allowed
method
1. Instance Methods
2. Class Methods
3. Static Methods
Example for class:
1) class Student:
2) '''''Developed by CodePlanet for python demo'''
3) def init (self):
4) [Link]='CodePlanet'
5) [Link]=40
6) [Link]=80
7)
8) def talk(self):
9) print("Hello I am :",[Link])
10) print("My Age is:",[Link])
11) print("My Marks are:",[Link])
3.1.2 Object:

Physical existence of a class is nothing but object. We can create any number of objects for a class.
Syntax :
referencevariable = classname()
Example: s = Student()

Reference Variable:
A reference variable is a variable used to refer to an object. Through the reference variable, we can
access the properties and methods of the object.
Program: Python program to create a Student class and Creates an object to it. Call the method talk() to
display student details

1) class Student:
2)
3) def init (self,name,rollno,marks):
4) [Link]=name
5) [Link]=rollno
6) [Link]=marks
7)
8) def talk(self):
9) print("Hello My Name is:",[Link])
10) print("My Rollno is:",[Link])
11) print("My Marks are:",[Link])
13) s1=Student("CodePlanet",101,80)
14) [Link]()

Output: py [Link]
Hello My Name is:
CodePlanet My Rollno
is: 101
My Marks are: 80

Self variable:

self is the default variable which is always pointing to current object (like this keyword in Java)
By using self we can access instance variables and instance methods of object.
Note:
1. self should be first parameter inside
constructor def init (self):
2. self should be first parameter inside instance
methods def talk(self):

3.2. Constructor, class attributes and destructors


3.2.1 Constructor
Define constructor as follows-
 The name of the constructor should be __init__(self)
 The constructor is executed automatically during object creation.
 The major purpose of constructor is to declare and initialize instance variables.
 Per object constructor will be exeucted only once.
 Constructor can take atleast one argument(atleast self)
 Constructor is optional and if we are not providing any constructor then python will
provide default constructor.
Example:
1) def init (self,name,rollno,marks):
2) [Link]=name
3) [Link]=rollno
4) [Link]=marks

Program to demonistrate constructor will execute only once per object:

1) class Test:
2)
3) def init (self):
4) print("Constructor exeuction...")
5)
6) def m1(self):
7) print("Method execution...")
9) t1=Test()
10) t2=Test()
11) t3=Test()
12) t1.m1()
Output
Constructor
exeuction...
Constructor
exeuction...
Constructor
exeuction... Method
execution...

Program:
1) class Student:
2)
3) ''''' This is student class with required data'''
4) def init (self,x,y,z):
5) [Link]=x
6) [Link]=y
7) [Link]=z
8)
9) def display(self):
10) print("Student Name:{}\nRollno:{} \nMarks:{}".format([Link],[Link],[Link])
)
11)
12) s1=Student("Ram",101,80)
13) [Link]()
14) s2=Student("Sham",102,100)
15) [Link]()

Output
Student Name:Ram
Rollno:101
Marks:80
Student
Name:Sham
Rollno:102
Marks:100
Differences between Methods and Constructors:

Method Constructor
1. Name of method can be any name 1. Constructor name should be always init

2. Method will be executed if we call 2. Constructor will be executed automatically


that at the time of object creation.
Method
3. Per object, method can be called any 3. Per object, Constructor will be executed
number only
of times. once
4. Inside method we can write business logic 4. Inside Constructor we have to declare
and instance variables

Destructors:

Destructor is method and the name should be __del__(self)


Before an object is destroyed, the Garbage Collector always calls the destructor to carry out
cleanup activities, such as deallocating resources like closing a database connection.
Once the destructor's execution is complete, the Garbage Collector automatically destroys the
object.
It's important to note that the destructor's role is not to destroy the object itself, but rather to
perform cleanup activities.
Example:
1) import time
2) class Test:
3) def init (self):
4) print("Obj Initialization...")
5) def del (self):7)
6) print("performing clean up activities...")
9) t1=None
8) t1=Test()
11) print("End of application")
10) [Link](5)

Output
Obj Initialization...
performing clean up activities...
End of application

Example:

1) import time
2) class Test:
3) def init (self):
4) print("Constructor...")
5) def del (self):
6) print("Destructor...")
7)
8) t1=Test()
9) t2=t1
10) t3=t2
11) del t1
12) [Link](5)
13) print("object not destroyed after deleting t1 object")
14) del t2
15) [Link](5)
16) print("object not destroyed even after deleting t2 object")
17) print("trying to delete last reference variable...")
18) del t3
Example:
1) import time
2) class Test:
3) def init (self):
4) print("Constructor...")
5) def del (self):
6) print("Destructor...")
7)
8) list=[Test(),Test(),Test()]
9) del list
10) [Link](5)
11) print("End of appl")
Output
Constructor...
Constructor...
Constructor...
Destructor...
Destructor...
Destructor...
End of appl

Find the number of references of an object: getrefcount()


Which contains in sys module.
[Link](objectreference)
Example:

1) import sys
2) class Test:
3) pass
4) t1=Test()
5) t2=t1
6) t3=t1
7) t4=t1
8) print([Link](t1))

Output 5

3.2.2 Types of Variables:


Inside Python class 3 types of variables are allowed.
1. Instance Variables (Object Level Variables)
2. Static Variables (Class Level Variables)
3. Local variables (Method Level Variables)

1. Instance Variables:
Instance variables are those whose values vary from object to object. For each object, a distinct
copy of instance variables is created.
Where we can declare Instance variables:
1. Inside Constructor- using self variable
2. Inside Instance Method - using self variable
3. Outside of the class by using object reference variable
 Inside Constructor - using self variable:
We can declare instance variables into constructor by using self keyword. Once we
creates object, automatically these variables will added to the object.
Example:

1) class Employee:
2)
3) def init (self):
4) [Link]=100
5) [Link]='CodePlanet'
6) [Link]=10000
8) e=Employee()
9) print([Link])

Output: {'eno': 100, 'ename': 'CodePlanet', 'esal': 10000}

 Inside Instance Method by using self variable:

We can also declare instance variables inside instance method by using self variable. If any
instance variable declared inside instance method, that instance variable will be added
once we call taht method.
Example:
1) class Test:
2)
3) def init (self):
4) self.a=10
5) self.b=20
6)
7) def m1(self):
8) self.c=30
9)
10) t=Test()
11) t.m1()
12) print(t. dict )
Output
{'a': 10, 'b': 20, 'c': 30}

 Outside of the class by using object reference variable:


We can also add instance variables outside of a class to a particular object.

1) class Test:
2)
3) def init (self):
4) self.a=10
5) self.b=20
6)
7) def m1(self):
8) self.c=30
9)
10) t=Test()
11) t.m1()
12) t.d=40
13) print(t. dict )

Output {'a': 10, 'b': 20, 'c': 30, 'd': 40}


Access Instance variables:
Within the class, instance variables can be accessed using the self variable, while outside of the
class, they can be accessed using the object reference.

1) class Test:
2)
3) def init (self):
4) self.a=10
5) self.b=20
6)
7) def display(self):
8) print(self.a)
9) print(self.b)
10)
11) t=Test()
12) [Link]()
13) print(t.a,t.b)

Output
10
20
10 20

How to delete instance variable from the object:


1. Within a class delete instance variable as follows

del [Link]

2. Outside of class we can delete instance variables as follows

del [Link]
Example:

1) class Test:
2) def init (self):
3) self.a=10
4) self.b=20
5) self.c=30
6) self.d=40
7) def m1(self):
8) del self.d
10) t=Test()
11) print(t. dict )
12) t.m1()
13) print(t. dict )
14) del t.c
15) print(t. dict )

Output
{'a': 10, 'b': 20, 'c': 30, 'd': 40}
{'a': 10, 'b': 20, 'c': 30}
{'a': 10, 'b': 20}

Note: The instance variables which are deleted from one object,will not be deleted from other
objects.
Example
1) class Test:
2) def init (self):
3) self.a=10
4) self.b=20
5)
7 self.c=30
6) self.d=40
9) t1=Test()
10) t2=Test()
11) del t1.a

13) print(t2. dict )


12) print(t1. dict )

Output
{'b': 20, 'c': 30, 'd': 40}
{'a': 10, 'b': 20, 'c': 30, 'd': 40}

If we changed the values of instance variables of one object then those changes won't be
reflected to the remaining objects, because for every object we are separate copy of instance
variables are available.
Example:
1) class Test:
2) def init (self):
3) self.a=10
4) self.b=20
5)
6) t1=Test()
7) t1.a=888
8) t1.b=999
9) t2=Test()
10) print('t1:',t1.a,t1.b)
11) print('t2:',t2.a,t2.b)
Output
t1: 888 999
t2: 10 20

2 Static variables:

Static variables are those whose value remains constant across all objects of the class. They are
declared within the class directly but outside of methods. Only one copy of a static variable is
created for the entire class, shared by all objects. Static variables can be accessed either by the
class name or by object reference, although it's recommended to use the class name.

Instance Variable vs Static Variable:


Note: In case of instance variables for every object a seperate copy will be created,but in
the case of static variables for total class only one copy will be created and shared by every
object of that class.
1) class Test:
2) x=100
3) def init (self):
4) self.y=20
5) 0
6) t1=Test()
7) t2=Test()
8) print('t1:',t1.x,t1.y)
9) print('t2:',t2.x,t2.y)
10) Test.x=888
11) t1.y=999
12) print('t1:',t1.x,t1.y)
13) print('t2:',t2.x,t2.y)

Output
t1: 100 200
t2: 100 200
t1: 888 999
t2: 888 20

Where we declare static variables:


1. Static variables can be declared within a class directly, but outside of any method.
2. Inside constructor by using class name
3. by using class name Inside instance method
4. Inside class method by using either class name or cls variable
5. Inside static method by using class name

1) class Test:
2) a=10
3) def init (self):
4) Test.b=20
5) def m1(self):
6) Test.c=30
7) @classmethod
8) def m2(cls):
9) cls.d1=40
10) Test.d2=400
11) @staticmethod
12) def m3():
13) Test.e=50
14) print(Test. dict )
15) t=Test()
16) print(Test. dict )
17) t.m1()
18) print(Test. dict )
19) Test.m2()
20) print(Test. dict )
21) Test.m3()
22) print(Test. dict )
23) Test.f=60
24) print(Test. dict )

To access static variables:


1. inside constructor: Use either self or the class name
2. inside instance method: Use either self or the class name.
3. inside class method: Use either cls variable or classname
4. inside static method: Using classname
5. From outside of class: by using either object reference or classnmae

1) class Test:
2) a=10
3) def init (self):
4) print(self.a)
5) print(Test.a)
6) def m1(self):
7) print(self.a)
8) print(Test.a)
9) @classmethod
10) def m2(cls):
11) print(cls.a)
12) print(Test.a)
13) @staticmethod
14) def m3():
15) print(Test.a)
16) t=Test()
17) print(Test.a)
18) print(t.a)
19) t.m1()
20) t.m2()
21) t.m3()

Where we can modify the value of static variable:


Anywhere either with inside the class or outside of class we can modify by using
classname. But inside class method, by using cls variable.

Example:
1) class Test:
2) a=777
3) @classmethod
4) def m1(cls):
5) cls.a=888
6) @staticmethod
7) def m2():
8) Test.a=999
9) print(Test.a)
10) Test.m1()
11) print(Test.a)
12) Test.m2()
13) print(Test.a)
Output
777
888
999

Example:

1) class Test:
2) a=10
3) def init (self):
4) self.b=20
5) t1=Test()
6) t2=Test()
7) Test.a=888
8) t1.b=999
9) print(t1.a,t1.b)
10) print(t2.a,t2.b)

Output
888 999
888 20

1) class Test:
2) a=10
3) def init (self):
4) self.b=20
5) def m1(self):
6) self.a=888
7) self.b=999
8)
9) t1=Test()
10) t2=Test()
11) t1.m1()
12) print(t1.a,t1.b)
13) print(t2.a,t2.b)

Output
888 999
10 20

Example:
1) class Test:
2) a=10
3) def init (self):
4) self.b=20
5) @classmethod
6) def m1(cls):
7) cls.a=888
8) cls.b=999
9)
10) t1=Test()
11) t2=Test()
12) t1.m1()
13) print(t1.a,t1.b)
14) print(t2.a,t2.b)
15) print(Test.a,Test.b)
Output
888 20
888 20
888 999

How to delete static variables of a class:


We can delete variables from anywhere
del [Link]

But inside classmethod we can also use cls variable


del [Link]
1) class Test:
2) a=10
3) @classmethod
4) def m1(cls):
5) del cls.a
6) Test.m1()
7) print(Test.__dict__)
Example:

1) class Test:
2) a=10
3) def init (self):
4) Test.b=20
5) del Test.a
6) def m1(self):
7) Test.c=30
8) del Test.b
9) @classmethod
10) def m2(cls):
11) cls.d=40
12) del Test.c
13) @staticmethod
14) def m3():
15) Test.e=50
16) del Test.d
17) print(Test. __dict__)
18) t=Test()
19) print(Test.__dict__)
20) t.m1()
21) print(Test.__dict__)
22) Test.m2()
23) print(Test. __dict__)
24) Test.m3()
25) print(Test.__dict__)
26) Test.f=60
27) print(Test. __dict__)
28) del Test.e
29) print(Test. __dict__)

****
Note: By using object reference variable self we can read static variables, but we cannot
modify or delete.
If we are trying to modify, then a new instance variable will be added to that particular
object. t1.a = 70
If we are trying to delete then we will get error.

Example:
1) class Test:
2) a=10
3)
4) t1=Test()
5) del t1.a ===>AttributeError: a

We can modify or delete static variables only by using classname or cls variable.
1) import sys
2) class Customer:
3) ''''' Customer class with bank operations.. '''
4) bankname='CODEPLANETBANK'
5) def init (self,name,balance=0.0):
6) [Link]=name
7) [Link]=balance
8) def deposit(self,amt):
9) [Link]=[Link]+amt
10) print('Balance after deposit:',[Link])
11) def withdraw(self,amt):
12) if amt>[Link]:
13) print('Insufficient Funds..cannot perform this operation')
14) [Link]()
15) [Link]=[Link]-amt
16) print('Balance after withdraw:',[Link])
17)
18) print('Welcome to',[Link])
19) name=input('Enter Your Name:')
20) c=Customer(name)
21) while True:
22) print('d-Deposit \nw-Withdraw \ne-exit')
23) option=input('Choose your option:')
24) if option=='d' or option=='D':
25) amt=float(input('Enter amount:'))
26) [Link](amt)
27) elif option=='w' or option=='W':
28) amt=float(input('Enter amount:'))
29) [Link](amt)
30) elif option=='e' or option=='E':
31) print('Thanks for Banking')
32) [Link]()
33) else:
34) print('Invalid option..Plz choose valid option')

Local variables:

Sometimes to fulfill the temporary needs of a programmer, variables can be declared


directly within a method. These variables are referred to as local variables or temporary
variables.
Local variables are created at the time of method execution and are destroyed once the
method completes.
Local variables of a method cannot be accessed from outside of method.
Example:
1) class Test:
2) def m1(self):
3) a=1000
4) print(a)
5) def m2(self):
6) b=2000
7) print(b)
8) t=Test()
9) t.m1()
10) t.m2()
Output
1000
2000
Example 2:
1) class Test:
2) def m1(self):
3) a=1000
4) print(a)
5) def m2(self):
6) b=2000
7) print(a) #NameError: name 'a' is not defined
8) print(b)
9) t=Test()
10) t.m1()
11) t.m2()

Types of Methods:

Inside Python class 3 types of methods are allowed


1. Instance Methods
2. Class Methods
3. Static Methods

1. Instance Methods:
Methods that utilize instance variables within their implementation are termed instance
methods. Within the declaration of an instance method, the self variable must be passed.

def m1(self):

By using self variable inside method we can able to get instance variables.
Inside the class we can call instance method by using self variable and from outside of the
class we can call by using object reference.
1) class Student:
2) def init (self,name,marks):
3) [Link]=name
4) [Link]=marks
5) def display(self):
6) print('Hi',[Link])
7) print('Your Marks are:',[Link])
8) def grade(self):
9) if [Link]>=60:
10) print('You got First Grade')
11) elif [Link]>=50:
12) print('Yout got Second Grade')
13) elif [Link]>=35:
14) print('You got Third Grade')
15) else:
16) print('You are Failed')
17) n=int(input('Enter number of students:'))
18) for i in range(n):
19) name=input('Enter Name:')
20) marks=int(input('Enter Marks:'))
21) s= Student(name,marks)
22) [Link]()
23) [Link]()
24) print()
ouput:
D:\CodePlanet_classes>py
[Link] Enter number of
students:2
Enter Name:CodePlanet
Enter
Marks:90
Hi CodePlanet
Your Marks are: 90
You got First Grade
Enter
Name:Ravi
Enter Marks:12
Hi Ravi
Your Marks are:
12
You are Failed

Setter and Getter Methods:


We can set and get the values of instance variables by using getter and setter methods.

Setter Method:
Setter methods used to set values to the instance variables. setter methods also known as
mutator methods.
syntax:
def setVariable(self,variable):
[Link]=variable

Example:
def setName(self,name):
[Link]=name

Getter Method:
Getter methods used to get values of the instance variables. Getter methods also known as
accessor methods.
syntax:

def
getVariable(self):
return
[Link]

Example:
def getName(self):
return
[Link]

Demo Program:
1) class Student:
2) def setName(self,name):
3) [Link]=name
4)
5) def getName(self):
6) return [Link]
7)
8) def setMarks(self,marks):
9) [Link]=marks
10)
11) def getMarks(self):
12) return [Link]
13)
14) n=int(input('Enter number of students:'))
15) for i in range(n):
16) s=Student()
17) name=input('Enter Name:')
18) [Link](name)
19) marks=int(input('Enter Marks:'))
20) [Link](marks)
21)
22) print('Hi',[Link]())
23) print('Your Marks are:',[Link]())
24) print()

output:
D:\python_classes>py
[Link] Enter number of
students:2 Enter
Name:CodePlanet
Enter
Marks:100
Hi CodePlanet
Your Marks are: 100
Enter
Name:Ravi
Enter Marks:80
Hi Ravi
Your Marks are: 80

2. Class Methods:

If a method's implementation solely involves class variables (static variables), then such
methods should be declared as class methods.
We can declare class method explicitly by using @classmethod decorator. For class method we
should provide cls variable at a time of declaration .We can call classmethod by using class
name or object reference variable.
Demo Program:

1) class Animal:
2) legs=4
3) @classmethod
4) def walk(cls,name):
5) print('{} walks with {} legs...'.format(name,[Link]))
6) [Link]('Dog')
7) [Link]('Cat')

Output
D:\python_classes>py
[Link] Dog walks with 4
legs...
Cat walks with 4 legs...

Program to track the number of objects created for a class:

Static Methods:
1) class Test:
2) count=0
3) def init (self):
4) [Link] =[Link]+1
5) @classmethod
6) def noOfObjects(cls):
7) print('The number of objects created for test class:',[Link])
8)
9) t1=Test()
10) t2=Test()
11) [Link]()
12) t3=Test()
13) t4=Test()
14) t5=Test()
15) [Link]()

In general these methods are general utility methods.


Inside these methods we won't use any instance or class variables. Here we won't provide self or
cls arguments at the time of declaration.
We can declare static method explicitly by using @static_method decorator We can access static
methods by using classname or object reference

1) class CodePlanetMath:
2)
3) @staticmethod
4) def add(x,y):

5) print('The Sum:',x+y)
6)
7) @staticmethod
8) def product(x,y):
9) print('The Product:',x*y)
10)
11) @staticmethod
12) def average(x,y):
13) print('The average:',(x+y)/2)
14)
15)
[Link](10,20)
16) [Link](10,20)

17)
Output
The Sum: 30
The Product: 200
The average: 15.0

Note: In general we can use only instance and static methods. Inside static method we can
access class level variables by using class name.
class methods are most rarely used methods in python.
3.3. Inheritance
3.3.1 Inheritance:

Inheritance is a fundamental concept in object-oriented programming (OOP) where a class (subclass)


can inherit attributes and methods from another class (superclass). This allows for code reuse and
facilitates the creation of a hierarchy structure of classes with increasing specialization.
Here's a basic example of inheritance in Python:
# Define a superclass
class Animal:
def __init__(self, name):
[Link] = name

def speak(self):
raise NotImplementedError("Subclass must implement abstract method")

# Define a subclass that inherits from Animal


class Dog(Animal):
def speak(self):
return "Woof!"

# Define another subclass that inherits from Animal


class Cat(Animal):
def speak(self):
return "Meow!"
# Usage
dog = Dog("Buddy")
print([Link]) # Output: Buddy
print([Link]()) # Output: Woof!

cat = Cat("Whiskers")
print([Link]) # Output: Whiskers
print([Link]()) # Output: Meow!

In the above example:


The Animal class is a superclass with a constructor that initializes the name attribute and
defines an abstract method speak().
The Dog and Cat classes are subclasses of Animal. They inherit the name attribute and
override the speak() method with their own implementation.
Instances of Dog and Cat can access both attributes and methods defined in the superclass
(Animal).
Inheritance promotes code reuse, as subclasses can leverage the functionality of their
superclass while specializing in certain behaviors. It also allows for polymorphism, where
different subclasses can be treated interchangeably through a common interface (in this case,
the speak() method).
Types Of Inheritance:
In Python, like in many object-oriented programming languages, there are several types of
inheritance, including:

1. Single Inheritance:
A subclass inherits from only one superclass.
It's the simplest form of inheritance.
class Animal:
def speak(self):
return "Animal speaks"

class Dog(Animal):
def bark(self):
return "Dog barks"

dog = Dog()
print([Link]()) # Output: Animal speaks

2. Multiple Inheritance:
A subclass inherits from multiple superclasses.
Allows a class to inherit attributes and methods from more than one parent class.
class Bird:
def fly(self):
return "Bird flies"

class Dog:
def bark(self):
return "Dog barks"

class DogBird(Dog, Bird):


pass

dog_bird = DogBird()
print(dog_bird.bark()) # Output: Dog barks
print(dog_bird.fly()) # Output: Bird flies

[Link] Inheritance:
A subclass inherits from a superclass, and another subclass inherits from this subclass.
class Animal:
def speak(self):
return "Animal speaks"

class Dog(Animal):
def bark(self):
return "Dog barks"

class Puppy(Dog):
def wag_tail(self):
return "Puppy wags tail"

puppy = Puppy()
print([Link]()) # Output: Animal speaks
print([Link]()) # Output: Dog barks
print(puppy.wag_tail()) # Output: Puppy wags tail

4. Hierarchical Inheritance:
Multiple subclasses inherit from a single superclass.
class Animal:
def speak(self):
return "Animal speaks"

class Dog(Animal):
def bark(self):
return "Dog barks"

class Cat(Animal):
def meow(self):
return "Cat meows"

dog = Dog()
cat = Cat()
print([Link]())
print([Link]())

5. Hybrid Inheritance:
It is a combination of multiple and hierarchical inheritance.
Not directly supported in Python, but can be get through combinations of other types of
inheritance.

3.3.2 Passing parameters from one class to another class:

We can access members of one class inside another class.

1) class Employee:
2) def init (self,eno,ename,esal):
3) [Link]=eno
4) [Link]=ename
5) [Link]=esal
6) def display(self):
7) print('Employee Number:',[Link])
8) print('Employee Name:',[Link])
9) print('Employee Salary:',[Link])
10) class Test:
11) def modify(emp):
12) [Link]=[Link]+10000
13) [Link]()
14) e=Employee(100,'CodePlanet',10000)
15) [Link](e)

Output
D:\python_classes>py
[Link] Employee Number:
100 Employee Name:
CodePlanet
Employee Salary: 20000

In the above application, Employee class members are available to Test class.

3.3.3 Inner classes:


Occasionally, we can define a class within another class. These types of classes are referred
to as inner classes.
Without existing one type of object if there is no chance of existing another type of
object,then we should go for inner classes.
Example: Without existence of Car object there is no chance of existing Engine object. Hence
Engine class should be part of Car class.

class
Car:
.....
class Engine:
......
Example: The existence of a Department object class University relies on the presence of a
University object.
.....
class Department:
......

Note: The existence of an inner class object is always contingent upon the presence of an
outer class object. Therefore, an inner class object is inherently associated with an outer class
object.

Demo Program-1:
1) class Outer:
2) def init (self):
3) print("outer class object creation")
4) class Inner:
5) def init (self):
6) print("inner class object creation")
7) def m1(self):
8) print("inner class method")
9) o=Outer()
10) i=[Link]()
11) i.m1()

Output
outer class object
creation inner class
object creation inner
class method
Note: The following are various syntaxes for calling inner class method
1.
o=Outer()
i=[Link]
() i.m1()

2.
i=Outer().Inner
() i.m1()

3. Outer().Inner().m1()
Demo Program-2:
1) class Person:
2) def init (self):
3) [Link]='CodeP
4) lanet'
[Link]=[Link]()
5) def display(self):
6) print('Name:',[Link])
7) class Dob:
8) def init (self):
9) [Link]=10
10) [Link]=5
11) [Link]=1947
12) def display(self):
13) print('Dob={}/{}/{}'.format([Link],[Link],[Link]))
14) p=Person()
15) [Link]()
16) x=[Link]
17) [Link]()
Output
Name:
CodePlanet
Dob=10 5
1947

Demo Program-3:
We can declare any number of inner classes in the class.

1) class Human:
2)
3) def init (self):
4) [Link] = 'Sunny'
5) [Link] = [Link]()
6) [Link] = [Link]()
7) def display(self):
8) print("Hello..",[Link])
9)
10) class Head:
11) def talk(self):
12) print('Talking...')
13)
14) class Brain:
15) def think(self):
16) print('Thinking...')
17)
18) h=Human()
19) [Link]()
20) [Link]()
21) [Link]()

Output
Hello..
Sunny
Talking...
Thinking...
3.4. Polymorphism - overloading and Overriding
3.4.1. Polymorphism
Poly means many. Morphs means forms. Polymorphism means 'Many Forms'.
Eg1: Yourself is best example of [Link] front of Your parents You will have one
type of behaviour and with friends another type of [Link] person but different
behaviours at different places,which is nothing but polymorphism.

Eg2: The + operator serves as both concatenation and arithmetic addition.


Eg3 : The * operator functions as both a multiplication and repetition operator.
Eg4: The method with varying implementations present in both the parent class and
its child classes. (overriding)
Related to polymorphism the following 4 topics are important
1. Overloading
1. Operator Overloading
2. Method Overloading
3. Constructor Overloading
2. Overriding
1. Method overriding
2. constructor overriding

Overloading:
We can use same operator or methods for different purposes.
Eg1: + operator used for Arithmetic addition and String concatenation
print(10+20)#30
print('CodePlanet'+'soft')#CodePlanetsoft

Eg2: * operator used for multiplication and string repetition purposes.


print(10*20)#200
print('CodePlanet'*3)#CodePlanetCodePlanetCodePlanet

Eg3: We can use deposit() method to deposit cash or cheque or dd


deposit(cash)
deposit(cheque
) deposit(dd)
There are 3 types of overloading
1. Operator Overloading
2. Method Overloading
3. Constructor Overloading

1. Operator Overloading:

We can use the same operator for multiple purposes, which is nothing but operator
overloading. Python supports operator overloading.
Eg1: + operator can be used for Arithmetic addition and String concatenation
print(10+20)#30
print('CodePlanet'+'soft')#CodePlanetsoft

Eg2: * operator can be used for multiplication and string repetition purposes.
print(10*20)#200
print('CodePlanet'*3)#CodePlanetCodePlanetCodePlanet

Demo program to use + operator for our class objects:


1) class Book:
2) def init (self,pages):
3) [Link]=pages
4)
5) b1=Book(100)
6) b2=Book(200)
7) print(b1+b2)

D:\CodePlanet_classes>py
[Link] Traceback :
File "[Link]", line 7, in
<module> print(b1+b2)
TypeError: unsupported operand type(s) for +: 'Book' and 'Book'

We can overload + operator to work with Book objects also. i.e Python supports
Operator Overloading.
For every operator Magic Methods are available. To overload any operator we have to
override that Method in our class.
Internally + operator is implemented by using add () [Link] method is called
magic method for + operator. We have to override this method in our class.

Demo program to overload + operator for our Book class objects:

1) class Book:
2) def init (self,pages):
3) [Link]=pages
4)
5) def add (self,other):
6) return [Link]+[Link]
7)
8) b1=Book(100)
9) b2=Book(200)
10) print('The Total Number of Pages:',b1+b2)

Output: The Total Number of Pages: 300

The following are list of operators and corresponding magic methods.


+ ---> object. add (self,other)
- ---> object. sub (self,other)
* ---> object. mul (self,other)
---> object. div (self,other)
---> object. floordiv (self,other)
% ---> object. mod (self,other)
** ---> object. pow (self,other)
+= ---> object. iadd (self,other)
-= ---> object. isub (self,other)
*= ---> object. imul (self,other)
= ---> object. idiv (self,other)
= ---> object. ifloordiv (self,other)
%= ---> object. imod (self,other)
**= ---> object. ipow (self,other)
< ---> object. lt (self,other)
<= ---> object. le (self,other)
> ---> object. gt (self,other)
>= ---> object. ge (self,other)
== ---> object. eq (self,other)
!= ---> object. ne (self,other)

Overloading > and <= operators for Student class objects:

1) class Student:
2) def init (self,name,marks):
3) [Link]=name
4) [Link]=marks
5) def gt (self,other):
6) return [Link]>[Link]
7) def le (self,other):
8) return [Link]<=[Link]
9)
10)
11) print("10>20 =",10>20)
12) s1=Student("CodePlanet",100)
13) s2=Student("Ravi",200)
14) print("s1>s2=",s1>s2)
15) print("s1<s2=",s1<s2)
16) print("s1<=s2=",s1<=s2)
17) print("s1>=s2=",s1>=s2)
Output:
10>20 =
False s1>s2=
False
s1<s2= True
s1<=s2=
True
s1>=s2=
False

Program to overload multiplication operator to work on Employee objects:


1) class Employee:
2) def init (self,name,salary):
3) [Link]=name
4) [Link]=salary
5) def mul (self,other):
6) return [Link]*[Link]
7)
8) class TimeSheet:
9) def init (self,name,days):
10) [Link]=name
11) [Link]=days
12)
13)
e=Employee('CodePlanet',500)
14) t=TimeSheet('CodePlanet',25)

15) print('This
Output: This Month Month Salary:',e*t)
Salary: 12500

2. Method Overloading:

If 2 methods having same name but different type of arguments then those methods are
said to be overloaded methods.
Eg: m1(int a)
m1(double
d)

But in Python Method overloading is not possible.


If we are trying to declare multiple methods with same name and different number of
arguments then Python will always consider only last method.
Demo Program:

1) class Test:
2) def m1(self):
3) print('no-arg method')
4) def m1(self,a):
5) print('one-arg method')
6) def m1(self,a,b):
7) print('two-arg method')
8)
9) t=Test()
10) #t.m1()
11) #t.m1(10)
12) t.m1(10,20)
Output: two-arg method
In the above program python will consider only last method.

How we can handle overloaded method requirements in Python:

In many cases, when a method necessitates a variable number of arguments, it can be managed
using either default arguments or methods that accept a variable number of arguments.
Demo Program with Default Arguments:
1) class Test:
2) def sum(self,a=None,b=None,c=None):
3) if a!=None and b!= None and c!= None:
4) print('The Sum of 3 Numbers:',a+b+c)
5) elif a!=None and b!= None:
6) print('The Sum of 2 Numbers:',a+b)
7) else:
8) print('Please provide 2 or 3 arguments')
9)
10) t=Test()
11) [Link](10,20)
12) [Link](10,20,30)
13) [Link](10)
O/p:
The Sum of 2 Numbers: 30
The Sum of 3 Numbers: 60
Please provide 2 or 3 arguments
Demo Program with Variable Number of Arguments:
1) class Test:
2) def sum(self,*a):
3) total=0
4) for x in a:
5) total=total+x
6) print('The Sum:',total)
7)
8)
9) t=Test()
10) [Link](10,20)
11) [Link](10,20,30)
12) [Link](10)
13) [Link]()
3. Constructor Overloading:

Constructor overloading is not possible in Python.


If we define multiple constructors then the last constructor will be considered.
1) class Test:
2) def init (self):
3) print('No-Arg Constructor')
4)
5) def init (self,a):
6) print('One-Arg constructor')
7)
8) def init (self,a,b):
9) print('Two-Arg constructor')
10) #t1=Test()
11) #t1=Test(10)
12) t1=Test(10,20)
Output: Two-Arg constructor

In the above program, only a Two-Arg Constructor is provided. However, depending on our
needs, we can declare constructors with default arguments or variable numbers of arguments.

Constructor with Default Arguments:


1) class Test:
2) def init (self,a=None,b=None,c=None):
3) print('Constructor with 0|1|2|3 number of arguments')
4)
5) t1=Test()
6) t2=Test(10)
7) t3=Test(10,20)
8) t4=Test(10,20,30)
Output:
Constructor with 0|1|2|3 number of
arguments Constructor with 0|1|2|3 number of
arguments Constructor with 0|1|2|3 number of
arguments Constructor with 0|1|2|3 number of
arguments
Constructor with Variable Number of Arguments:
1) class Test:
2) def init (self,*a):
3) print('Constructor with variable number of arguments')
4)
5) t1=Test()
6) t2=Test(10)
7) t3=Test(10,20)
8) t4=Test(10,20,30)
9) t5=Test(10,20,30,40,50,60)

Whatever members available in the parent class are bydefault available to the child class
through inheritance. If the child class not satisfied with parent class implementation then
child class is allowed to redefine that method in the child class based on its requirement. This
concept is called overriding.
Overriding concept applicable for both methods and constructors.

Demo Program for Method overriding:

1) class P:
2) def property(self):
3) print('Gold+Land+Cash+Power')
4) def marry(self):
5) print('Appalamma')
6) class C(P):
7) def marry(self):
8) print('Katrina Kaif')
9)
10) c=C()
11) [Link]()
12) [Link]()
Output:
Gold+Land+Cash+Power
Katrina Kaif
From Overriding method of child class,we can call parent class method also by using super()
1) class P:
2) def property(self):
3) print('Gold+Land+Cash+Power')
4) def marry(self):
5) print('Lakshmi')
6) class C(P):
7) def marry(self):
8) super().marry()
9) print('Katrina Kaif')
10)
11) c=C()
12) [Link]()
13) [Link]()

Output:
Gold+Land+Cash+Power
Lakshmi
Katrina Kaif
Demo Program for Constructor overriding:
1) class P:
2) def init (self):
3) print('Parent Constructor')
4)
5) class C(P):
6) def init (self):
7) print('Child Constructor')
8)
9) c=C()

Output: Child Constructor


In the above example,if child class does not contain constructor then parent class constructor
will be executed
From child class constuctor we can call parent class constructor by using super() method.

Demo Program to call Parent class constructor by using super():


1) class Person:
2) def init (self,name,age):
3) [Link]=name
4) [Link]=age
5)
6) class Employee(Person):
7) def init (self,name,age,eno,esal):
8) super(). init (name,age)
9) [Link]=eno
10) [Link]=esal
11)
12) def display(self):
13) print('Employee Name:',[Link])
14) print('Employee Age:',[Link])
15) print('Employee Number:',[Link])
16) print('Employee Salary:',[Link])
17)
18) e1=Employee('CodePlanet',48,872425,26000)
19) [Link]()
20) e2=Employee('Sunny',39,872426,36000)
21) [Link]()

Output:
Employee Name:
CodePlanet Employee
Age: 48
Employee Number: 872425
Employee Salary:
26000 Employee
Name: Sunny
Employee Age: 39
Employee Number: 872426
Employee Salary: 36000

3.6. Garbage Collection


In older languages like C++, programmers are responsible for both creating and destroying
objects. Typically, programmers are meticulous about creating objects but may neglect to
properly handle the destruction of unnecessary objects. This negligence can lead to memory-
related issues, such as memory being filled with useless objects, ultimately causing the entire
application to crash with out-of-memory errors.

However, in Python, we have a built-in assistant called the Garbage Collector that
continuously runs in the background to take care of destroying unnecessary objects. Thanks to
this Garbage Collector, the likelihood of a Python program failing due to memory problems is
significantly reduced. The primary objective of the Garbage Collector is to identify and
destroy these useless objects. Objects that do not have any reference variables pointing to them
are considered eligible for Garbage Collection.

To enable or disable the Garbage Collector in our program:


We can use functions provided by the gc module. By default, the Garbage Collector is
enabled, but we can disable it based on our specific requirements.

 [Link](): It returns True if GC enabled


 [Link](): To disable Garbage Collector explicitly
 [Link](): To enable Garbage Collector explicitly

Example:
1) import gc
2) print([Link]())
3) [Link]()
4) print([Link]())
5) [Link]()
6) print([Link]())
Output
True
False
True

Solved Programs
Q.1 Operation of Vehicales
class Vehicle:
def __init__(self, make, model, year):
[Link] = make
[Link] = model
[Link] = year
[Link] = False

def start(self):
[Link] = True
print(f"{[Link]} {[Link]} {[Link]} started.")

def stop(self):
[Link] = False
print(f"{[Link]} {[Link]} {[Link]} stopped.")

class Car(Vehicle):
def __init__(self, make, model, year, num_doors):
super().__init__(make, model, year)
self.num_doors = num_doors

def honk(self):
print("Honk!")
class Motorcycle(Vehicle):
def __init__(self, make, model, year):
super().__init__(make, model, year)
self.num_wheels = 2

def wheelie(self):
print("Performing a wheelie!")

class Bicycle(Vehicle):
def __init__(self, make, model, year, num_gears):
super().__init__(make, model, year)
self.num_gears = num_gears

def ring_bell(self):
print("Ding! Ding!")

# Usage
car = Car("Toyota", "Camry", 2020, 4)
[Link]() # Output: Toyota Camry 2020 started.
[Link]() # Output: Honk!
[Link]() # Output: Toyota Camry 2020 stopped.

motorcycle = Motorcycle("Harley-Davidson", "Sportster", 2021)


[Link]() # Output: Harley-Davidson Sportster 2021 started.
[Link]() # Output: Performing a wheelie!
[Link]() # Output: Harley-Davidson Sportster 2021 stopped.

bicycle = Bicycle("Giant", "Escape", 2019, 21)


[Link]() # Output: Giant Escape 2019 started.
bicycle.ring_bell() # Output: Ding! Ding!
[Link]() # Output: Giant Escape 2019 stopped.

Q.2 A real-life using a constructor in Python could be modeling a banking system where each
customer has an account. We create a class representing a bank account, and use a constructor to
initialize the account with the customer's name, account number, and initial balance.
class BankAccount:
def __init__(self, customer_name, account_number, initial_balance=0):
self.customer_name = customer_name
self.account_number = account_number
[Link] = initial_balance

def deposit(self, amount):


[Link] += amount
print(f"Deposited {amount} into account {self.account_number}. New balance: {[Link]}")

def withdraw(self, amount):


if amount <= [Link]:
[Link] -= amount
print(f"Withdrew {amount} from account {self.account_number}. New balance:
{[Link]}")
else:
print("Insufficient funds")

def display_balance(self):
print(f"Account {self.account_number} balance: {[Link]}")

# Creating a bank account for a customer


account1 = BankAccount("Alice", "1234567890", 1000)

# Depositing and withdrawing money


account1.display_balance() # Output: Account 1234567890 balance: 1000
[Link](500) # Output: Deposited 500 into account 1234567890. New balance: 1500
[Link](200) # Output: Withdrew 200 from account 1234567890. New balance: 1300
account1.display_balance() # Output: Account 1234567890 balance: 1300

Excercises
Q.1. Write a python code for encapsulate data within a class by using private attributes and public
methods for access.
Q.2 Write a python code to show polymorphic behavior where different classes share a common
interface (method) but provide different implementations.
Q.3 Demonstrate abstraction where a class provides only essential attributes and methods, hiding the
implementation details.

You might also like