Unit 4
Unit 4
In Python, object-oriented
oriented Programming (OOPs) is a programming paradigm that uses objects
and classes in programming. It aims to implement real-worldreal world entities like inheritance,
polymorphisms, encapsulation, etc. in the programming. The main concept of OOPs is to bind
the data and the functions that work on that together as a single unit so that no other part of the
code can access this data.
Python Class
A class is a collection of objects. A class contains the blueprints or the prototype from which
the objects are being created. It is a logical entity that contains some attributes and methods.
Classes are created by keyword class.
Attributes are the variables that belong to a class.
Attributes are always public and can be accessed using the dot (.) operator. Eg.:
Myclass.Myattribute
Class Definition Syntax:
class ClassName:
# Statement-1
# Statement-N
class Dog:
pass
Python Objects
The object is an entity that has a state and behavior associated with it. It may be any real-world
object like a mouse, keyboard, chair, table, pen, etc. Integers, strings, floating-point numbers,
even arrays, and dictionaries, are all objects.
This will create an object named obj of the class Dog defined above.
Example:
obj = Dog()
1. Class methods must have an extra first parameter in the method definition. We do not give
a value for this parameter when we call the method, Python provides it
2. If we have a method that takes no arguments, then we still have to have one argument.
Self represents the instance of the class. By using the “self” we can access the attributes and
methods of the
he class in python. It binds the attributes with the given arguments.
Program
#it is clearly seen that self and obj is referring to the same object
class check:
def __init__(self):
print("Address of self = ",id(self))
obj = check()
print("Address of class object = ",id(obj))
Output:
Address of self = 140124194801032
Address of class object = 140124194801032
class car():
def show(self):
print("Model is", self.model )
print("color is", self.color )
Output:
Model is audi a4
color is blue
Model is ferrari 488
color is green
The __init__ method is similar to constructors in C++ and Java. It is run as soon as an object of
a class is instantiated. The method is useful to do any initialization you want to do with your
object. Now let us define a class and create some objects using the self and __init__ method.
class Dog:
# class attribute
attr1 = "mammal"
# Instance attribute
self.name = name
# Driver code
# Object instantiation
Rodger = Dog("Rodger")
Tommy = Dog("Tommy")
print("Rodger is a {}".format(Rodger.__class__.attr1))
Output:
Rodger is a mammal
Tommy is also a mammal
My name is Rodger
My name is Tommy
__init__ is a special
cial method (constructor) that initializes an instance of the Dog class. It
takes two parameters: self (referring to the instance being created) and name (representing
the name of the dog). The name parameter is used to assign a name attribute to each
instance
ance of Dog.
Creating Classes and objects with methods
The speak method is defined within the Dog class. This method prints a string that includes
the name of the dog instance.
class Dog:
# class attribute
attr1 = "mammal"
# Instance attribute
self.name = name
def speak(self):
# Driver code
# Object instantiation
Rodger = Dog("Rodger")
Tommy = Dog("Tommy")
Rodger.speak()
Tommy.speak()
Output:
My name is Rodger
My name is Tommy
CONSTRUCTOR IN PYTHON
Constructors are generally used for instantiating an object. The task of constructors is to
initialize(assign values) to the data members of the class when an object of the class is created.
In Python the __init__() method is called the constructor and is always called when an object is
created.
Syntax of constructor declaration :
def __init__(self):
# body of the constructor
Types of constructors :
default constructor: The default constructor is a simple constructor which doesn’t accept
any arguments. Its definition has only one argument which is a reference to the instance
being constructed.
class fruit:
# default constructor
def __init__(self):
self.fruit = "apple"
Output:
Apple
PARAMETERIZED CONSTRUCTOR
class Concat_Str:
first = 0
second = 0
answer = 0
# parameterized constructor
def __init__(self, f, s):
self.first = f
self.second = s
def display(self):
print("First string = " + (self.first))
print("Second string = " + (self.second))
print("Concatination of two strings = " + (self.answer))
def calculate(self):
self.answer = self.first + self.second
Output:
First string = 1000
Second string = 2000
Concatenation of two string = 3000
First string = 10
Second string = 20
Concatenation of two string = 30
DESTRUCTOR IN PYTHON
Destructors are called when an object gets destroyed. Python has a garbage collector that
handles memory management automatically.
The __del__() method is a known as a destructor method in Python. It is called when all
references to the object have been deleted i.e when an object is garbage collected.
Syntax of destructor declaration :
def __del__(self):
# body of destructor
Program
# Python program to illustrate destructor
class Employee:
# Initializing
def __init__(self):
print('Employee created.')
# Deleting (Calling destructor)
def __del__(self):
print('Destructor called, Employee deleted.')
obj = Employee()
del obj
Output
Employee created.
Destructor called, Employee deleted.
GETTER AND SETTER METHOD
In Python, getters and setters are not the same as those in other object-oriented programming
languages. Basically, the main purpose of using getters and setters in object-oriented programs
is to ensure data encapsulation.
In python Getters and Setters are often used
# setter method
def set_age(self, x):
self._age = x
raj = person_age ()
Output:
21
21
In above code functions get_age() and set_age() acts as normal functions and doesn’t play any
impact as getters and setters, to achieve such functionality Python has a special
function property().
In Python property()is a built-in function that creates and returns a property object. A property
object has three methods, getter(), setter(), and delete(). property() function in Python has four
arguments property(fget, fset, fdel, doc), fget is a function for retrieving an attribute
value. fset is a function for setting an attribute value. fdel is a function for deleting an attribute
value. doc creates a docstring for attribute. A property object has three
methods, getter(), setter(), and delete() to specify fget, fset and fdel individually. For Example
class person_age:
def __init__(self):
self._age = 0
mark = person_age()
mark.age = 10
print(mark.age)
ENCAPSULATION
A class is an example of encapsulation as it encapsulates all the data that is member functions,
variables, etc. The goal of information hiding is to ensure that an object’s state is always valid
by controlling access to attributes that are hidden from the outside world.
PROTECTED MEMBERS
Protected members (in C++ and JAVA) are those members of the class that cannot be accessed
outside the class but can be accessed from within the class and its subclasses. To accomplish
this in Python, just follow the convention by prefixing the name of the member by a single
underscore “_”.
# Python program to
class Base:
def __init__(self):
# Protected member
self._a = 2
class Derived(Base):
def __init__(self):
# Calling constructor of
# Base class
Base.__init__(self)
self._a)
self._a = 3
print("Calling modified protected member outside class: ",
self._a)
obj1 = Derived()
obj2 = Base()
Output:
PRIVATE MEMBERS
Private members are similar to protected members, the difference is that the class
members declared private should neither be accessed outside the class nor by any base
class. In Python, there is no existence of Private instance variables that cannot be accessed
except inside a class.
# Python program to
# demonstrate private members
class Base:
def __init__(self):
self.a = "GeeksforGeeks"
self.__c = "GeeksforGeeks"
class Derived(Base):
def __init__(self):
# Calling constructor of
# Base class
Base.__init__(self)
print(self.__c)
# Driver code
obj1 = Base()
print(obj1.a)
# raise an AttributeError
Output:
GeeksforGeeks
Traceback (most recent call last):
File "/home/f4905b43bfcf29567e360c709d3c52bd.py", line 25, in <module>
print(obj1.c)
AttributeError: 'Base' object has no attribute 'c'
INHERITANCE
Syntax
Class BaseClass:
{Body}
Class DerivedClass(BaseClass):
{Body}
A parent class is a class whose properties are inherited by the child class. Let’s create a parent
class called Person which has a Display method to display the person’s information.
class Person(object):
# Constructor
self.name = name
self.id = id
def Display(self):
print(self.name, self.id)
# Driver code
emp = Person("Satyam", 102) # An Object of Person
emp.Display()
A child class is a class that drives the properties from its parent class. Here Emp is another
class that is going to inherit the properties of the Person class (base class).
class Emp(Person):
def Print(self):
Emp_details.Display()
Emp_details.Print()
Output:
Mayank 103
Emp class called
The super() function is a built-in function that returns the objects that represent the parent
class. It allows to access the parent class’s methods and attributes in the child class.
Example:
# parent class
class Person():
def __init__(self, name, age):
self.name = name
self.age = age
def display(self):
print(self.name, self.age)
# child class
class Student(Person):
self.sName = name
self.sAge = age
super().__init__("Rahul", age)
def displayInfo(self):
print(self.sName, self.sAge)
obj.display()
obj.displayInfo()
Output:
Rahul 23
Mayank 23
Adding Properties
One of the features that inheritance provides is inheriting the properties of the parent class as
well as adding new properties of our own to the child class. Let us see this with an example:
# parent class
class Person():
self.name = name
self.age = age
def display(self):
print(self.name, self.age)
# child class
class Student(Person):
self.sName = name
self.sAge = age
self.dob = dob
super().__init__("Rahul", age)
def displayInfo(self):
obj.display()
obj.displayInfo()
Output:
Rahul 23
Mayank 23 16-03-2000
Single inheritance:
Single inheritance enables a derived class to inherit properties from a single parent class,
thus enabling code reusability and the addition of new features to existing code.
Multiple Inheritance:
When a class can be derived from more than one base class this type of inheritance is called
multiple inheritances. In multiple inheritances, all the features of the base classes are inherited
into the derived class.
# Python example to show the working of multiple inheritance
class Base1(object):
def __init__(self):
self.str1 = "Geek1"
print("Base1")
class Base2(object):
def __init__(self):
self.str2 = "Geek2"
print("Base2")
def printStrs(self):
print(self.str1, self.str2)
ob = Derived()
ob.printStrs()
Multilevel Inheritance:
In multilevel inheritance, features of the base class and the derived class are further
inherited into the new derived class. This is similar to a relationship representing a child
and a grandfather.
class Base(object):
# Constructor
def __init__(self, name):
self.name = name
# To get name
def getName(self):
return self.name
# Constructor
def __init__(self, name, age):
Base.__init__(self, name)
self.age = age
# To get name
def getAge(self):
return self.age
class GrandChild(Child):
# Constructor
def __init__(self, name, age, address):
Child.__init__(self, name, age)
self.address = address
# To get address
def getAddress(self):
return self.address
# Driver code
g = GrandChild("Geek1", 23, "Noida")
print(g.getName(), g.getAge(), g.getAddress())
Output:
Geek1 23 Noida
Hierarchical Inheritance:
When more than one derived class are created from a single base this type of inheritance is
called hierarchical inheritance. In this program, we have a parent (base) class and two child
(derived) classes.
# Hierarchical inheritance
# Base class
class Parent:
def func1(self):
# Derived class1
class Child1(Parent):
def func2(self):
# Derivied class2
class Child2(Parent):
def func3(self):
# Driver's code
object1 = Child1()
object2 = Child2()
object1.func1()
object1.func2()
object2.func1()
object2.func3()
Output:
This function is in parent class.
This function is in child 1.
This function is in parent class.
This function is in child 2.
Hybrid Inheritance:
Inheritance consisting of multiple types of inheritance is called hybrid inheritance
# hybrid inheritance
class School:
def func1(self):
class Student1(School):
def func2(self):
class Student2(School):
def func3(self):
def func4(self):
# Driver's code
object = Student3()
object.func1()
object.func2()
Output:
This function is in school.
This function is in student 1.
POLYMORPHISM
The word polymorphism means having many forms. In programming, polymorphism means
the same function name (but different signatures) being used for different types. The key
difference is the data types and number of arguments used in function.
print(len("geeks"))
In Python, Polymorphism lets us define methods in the child class that have the same name as
the methods in the parent class. In inheritance, the child class inherits the methods from the
parent class. However, it is possible to modify a method in a child class that it has inherited
from the parent class. This is particularly useful in cases where the method inherited from the
parent class doesn’t quite fit the child class. In such cases, we re-implement the method in the
child class. This process of re-implementing a method in the child class is known as Method
Overriding.
class Bird:
def intro(self):
def flight(self):
class sparrow(Bird):
def flight(self):
def flight(self):
obj_bird = Bird()
obj_spr = sparrow()
obj_ost = ostrich()
obj_bird.intro()
obj_bird.flight()
obj_spr.intro()
obj_spr.flight()
obj_ost.intro()
obj_ost.flight()
Output
By defining an abstract base class, you can define a common Application Program
Interface(API) for a set of subclasses. This capability is especially useful in situations where a
third-party is going to provide implementations, such as with plugins, but can also help you
when working in a large team or with a large code-base where keeping all classes in your mind
is difficult or not possible.
By default, Python does not provide abstract classes. Python comes with a module that
provides the base for defining Abstract Base classes(ABC) and that module name is
ABC. ABC works by decorating methods of the base class as abstract and then registering
concrete classes as implementations of the abstract base. A method becomes abstract when
decorated with the keyword @abstractmethod.
class Polygon(ABC):
@abstractmethod
def noofsides(self):
pass
class Triangle(Polygon):
def noofsides(self):
class Pentagon(Polygon):
def noofsides(self):
class Hexagon(Polygon):
def noofsides(self):
class Quadrilateral(Polygon):
def noofsides(self):
R = Triangle()
R.noofsides()
K = Quadrilateral()
K.noofsides()
R = Pentagon()
R.noofsides()
K = Hexagon()
K.noofsides()
Output:
I have 3 sides
I have 4 sides
I have 5 sides
I have 6 sides
INTERFACE
INFORMAL INTERFACE
Python informal interface is also a class that defines methods that can be overridden but without
force enforcement. An informal interface also called Protocols or Duck Typing. The duck typing
is actually we execute a method on the object as we expected an object to have, instead of
checking the type of an object.
Program
classFruits:
def__init__( self, ele):
self.__ele = ele
def__contains__( self, ele):
return ele in self.__ele
def__len__( self ):
returnlen( self.__ele)
Fruits_list = Fruits(["Apple","Banana","Orange"])
print(len(Fruits_list))
print("Apple"in Fruits_list)
print("Mango"in Fruits_list)
print("Orange"notin Fruits_list)
Output
3
True
False
False
As in the above example code, class Fruits implement the __len__, and __contains__ methods,
so on the instance of the Fruits class, we can directly use the len function to get the size and can
check the membership by using the in operator. As in the above code, the __iter__ method
(iterable protocol) is not implemented, so we would not iterate over the instance of the Fruits.
Therefore an informal interface cannot be enforced formally.
FORMAL INTERFACE
A formal Interface is an interface which enforced formally. To create a formal interface, we need
to use ABCs (Abstract Base Classes).
An ABC is simple as an interface or base classes define as an abstract class in nature and the
abstract class contains some methods as abstract. Next, if any classes or objects implement or
drive from these base classes, then these bases classes forced to implements all those methods.
Note that the interface cannot be instantiated, which means that we cannot create the object of
the interface. So we use a base class to create an object, and we can say that the object
implements an interface. And we will use the type function to confirm that the object implements
a particular interface or not.
Program
import abc
classMyinterface( abc.ABC ):
@abc.abstractclassmethod
defdisp():
pass
classMyclass( Myinterface ):
pass
o1 = Myclass()
Output:
In the above code, the Myclass class inherits abstract class Myinterface but not provided
the disp() abstract method’s implementation. The class Myclass also becomes an abstract class
and hence cannot be instantiated.
Program:
import abc
classMyinterface( abc.ABC ):
@abc.abstractclassmethod
defdisp():
pass
#print(" Hello from Myclass ")
classMyclass(Myinterface):
defdisp(s):
print(" Hello from Myclass ")
o1=Myclass()
o1.disp()
Output