0% found this document useful (0 votes)
2 views18 pages

Python Programming Course PLC 6 Unit 4 Module 4

The document provides an overview of Object-Oriented Programming (OOP) concepts in Python, including classes, objects, encapsulation, inheritance, and polymorphism. It explains how to create classes and objects, use constructors, and the differences between class attributes and instance attributes. Additionally, it covers the advantages of OOP, such as code reusability and maintainability, along with examples demonstrating these concepts.

Uploaded by

manstar9067
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)
2 views18 pages

Python Programming Course PLC 6 Unit 4 Module 4

The document provides an overview of Object-Oriented Programming (OOP) concepts in Python, including classes, objects, encapsulation, inheritance, and polymorphism. It explains how to create classes and objects, use constructors, and the differences between class attributes and instance attributes. Additionally, it covers the advantages of OOP, such as code reusability and maintainability, along with examples demonstrating these concepts.

Uploaded by

manstar9067
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

Object-Oriented Programming: Classes and Objects, Creating Classes in Python, Creating

Objects in Python, The Constructor Method, Classes with Multiple Objects, Using Objects
as Arguments, Objects as Return Values, Class Attributes versus Data Attributes,
Encapsulation, Using Private Instance Variables and Methods. Inheritance: Accessing the
Inherited Variables and Methods, Using super() Function and Overriding Base Class
Methods, Using super() Function and Overriding Base Class Methods, Multiple
Inheritances, Method Resolution Order (MRO), The Polymorphism, Operator
Overloading and Magic Methods. Example Programs.

Introduction: Object Oriented Programming empowers developers to build modular,


maintainable and scalable applications. OOP is a way of organizing code that uses objects and
classes to represent real-world entities and their behavior. In OOP, an object has attributes that
have specific data and can perform certain actions using methods.
1. Organizes code into classes and objects.
2. Supports encapsulation to group data and methods together.
3. Enables inheritance for reusability and hierarchy.
4. Allows polymorphism for flexible method implementation.
5. Improves modularity, scalability and maintainability.

What are POP and OOP?


1. POP (Procedure-Oriented Programming) → Focus on functions
2. OOP (Object-Oriented Programming) → Focus on objects (data + functions together)

Advantages of OOP
1. Encapsulation (Data Safety)
2. Multiple Objects Easily
3. Code Reusability
4. Real-World Modeling
5. Easy Maintenance

Example program for POP approach:

name="Rahul"
marks=85
def display():
print('name:', name)
print('marks:', marks)
display()
Output:

name: Rahul
marks: 85

Example program for OOP approach:


class student:
def __init__(self,name,marks):
[Link]=name
[Link]=marks
def display(self):
print('name:',[Link])
print('marks:',[Link])
s1=student('Rahul',85)
s2=student('Rohit',90)
[Link]()
[Link]()

Output:
name: Rahul
marks: 85
name: Rohit
marks: 90

Class: A class is a collection of objects. Classes are blueprints for creating objects. A class
defines a set of attributes and methods that the created objects (instances) can have.
1. Classes are created by keyword class.
2. Attributes are the variables that belong to a class.
3. Attributes are always public and can be accessed using the dot (.) operator.
Example;
class Car:
type="vehicle"
def __init__(self,name,model):
[Link]=name
[Link]=model

1. class Car creates a class named Car which acts as a blueprint for car objects.
2. Type is a class attribute meaning it is shared by all instances of the class.
3. __init__(). is a constructor method that runs automatically when a new object is created.
It is used to initialize object data.
4. self refers to a current object allowing each object to store and access its own data.
5. [Link] and [Link] are instance of the attribute, unique to each car object created
from the class

Objects: An Object is an instance of a Class. It represents a specific implementation of the


class and holds its own data. An object consists of:
1. State: It is represented by the attributes and reflects the properties of an object.
2. Behavior: It is represented by the methods of an object and reflects the response of an
object to other objects.
3. Identity: It gives a unique name to an object and enables one object to interact with
other objects.
4. Creating Object
5. Creating an object involves instantiating a class to create a new instance of that class.
This process is also referred to as object instantiation.

class Car:
type="vehicle" # class attribute
def __init__(self,name,model):
[Link]=name # instance attribute
[Link]=model
def display(self):
print('name:',[Link])
print('model:',[Link])
print('type:',[Link])
c1=Car('BMW',2019) # creating objects
c2=Car('AUDI',2020)
[Link]()
[Link]()

Output:
name: BMW
model: 2019
type: vehicle
name: AUDI
model: 2020
type: vehicle

The Constructor Method


In Python, a constructor is a special method that is called automatically when an object is created
from a class. Its main role is to initialize the object by setting up its attributes or state. The
__init__ is the initializer that sets up the instance's attributes after creation. These methods work
together to manage object creation and initialization.
__init__ Method
This method initializes the newly created instance and is commonly used as a constructor in
Python.

Syntax:
class ClassName:
def __init__(self, parameters):
[Link] = value
Example program:

class Car:
def __init__(self, make, model, year):

#Initialize the Car with specific attributes.


[Link] = make
[Link] = model
[Link] = year

# Creating an instance using the parameterized constructor


car = Car("Honda", "Civic", 2022)
print([Link])
print([Link])
print([Link])

Output:
Honda
Civic
2022

Classes with Multiple Objects


“A class can create multiple objects, where each object has its own set of data but shares the
same methods defined in the class.” An object is a specific instance of a class. It holds its own
set of data (instance variables) and can invoke methods defined by its class. Multiple objects can
be created from the same class, each with its own unique attributes.
class Student:
def __init__(self, name, marks):
[Link] = name
[Link] = marks
def display(self):
print("Name:", [Link], "Marks:", [Link])
# Creating multiple objects
s1 = Student("Rahul", 85)
s2 = Student("Anita", 90)
s3 = Student("John", 78)
# Calling method for each object
[Link]()
[Link]()
[Link]()

Output:
Name: Rahul Marks: 85
Name: Anita Marks: 90
Name: John Marks: 78
Explination:
class Student: → one class (blueprint)
s1, s2, s3 → three different objects
Each object stores its own values
Same method (display) works for all objects
Using Objects as Arguments in Python
“Objects can be passed as arguments to functions, allowing access to their data members and
methods inside the function.”
1. An object can be passed to a function like any other variable
2. The function receives the object reference
3. It can access attributes (data) and methods of that object.
4. It will be used
5. To work with complete object data inside a function
6. Improves code reusability
7. Makes programs more organized and modular
class Student:
def __init__(self, name, marks):
[Link] = name
[Link] = marks

def display(student): # parameter name


print([Link], [Link])

s1 = Student("Rahul", 85)
display(s1) # passing object

Output:
Rahul 85

Explanation:
● s1 is an object of class Student
● display(s1) passes the object to the function
● student parameter refers to the same object (s1)
● Inside function:
● [Link] → accesses name
● [Link] → accesses marks
● s1=Student("Rahul")
→ Object created and stored in s1
● display(s1)
→ s1 is passed to function
● Inside function:
● student = s1 (both point to same object)
● So:
● [Link] = [Link] = "Rahul"
Objects as Return Values in Python
A function can return an object, just like it returns numbers or strings
The returned object can be stored in a variable and used later

def square(n):
return n * n

res = square(4)
print(res)
Output:
16

class Student:
def __init__(self, name, marks):
[Link] = name
[Link] = marks

# Function returning an object


def create_student():
s = Student("Rahul", 85)
return s
# Receive returned object
s1 = create_student()

# Use the object


print([Link], [Link])

Output:
Rahul 85

Explaination:
 create_student() creates an object s
 return s → sends the object back
 s1 = create_student() → stores returned object
 [Link], [Link] → access object data
Class Attributes versus Data Attributes
 Class Attributes → Shared by all objects of a class
 Data (Instance) Attributes → Unique to each object
 Class attributes are shared data
 Instance attributes are object-specific data
 Changing class attribute affects all objects (unless overridden)
 Key Differences

Feature Class attribute Instance attribute

Defined Inside class, outside methods Inside constructor(__init__)

Sharing Common to all objects Separate for each object

Access [Link] or object Only through objects

Memory One copy Multiple copies


class Student:
college = "ABC College" # Class attribute (common)

def __init__(self, name):


[Link] = name # Instance attribute
(individual)

# Create objects
s1 = Student("Rahul")
s2 = Student("Anita")

print([Link], [Link])
print([Link], [Link])

Output:
Rahul ABC College
Anita ABC College
Explanation:
college → same for all students → class attribute
name → different for each student → instance attribute
s1 and s2 share college but have different name

Encapsulation, Using Private Instance Variables and Methods


Encapsulation in Python
What is Encapsulation?
 Encapsulation is an Object-Oriented Programming (OOP) concept used to:
 Combine data and methods into a single unit called a class
 Protect data from direct access
 Allow access to data only through controlled methods
 In simple words:
 Encapsulation means “hiding the internal details of an object and providing controlled access.”

Why Do We Need Encapsulation?


 Without encapsulation:
 Any part of the program can directly change object data
 Data may become invalid or corrupted
 With encapsulation:
 Data is safer
 Better security
 Easy maintenance
 Controlled access using methods
 Private Instance Variables in Python
 In Python, private variables are created using double underscore (__) before the variable name.

Syntax
self.__variable_name
These variables cannot be accessed directly outside the class.
class Student:
def __init__(self, name, marks):
[Link] = name # Public variable
self.__marks = marks # Private variable
def display(self):
print("Name:", [Link])
print("Marks:", self.__marks)
s1 = Student("Ravi", 85)
[Link]()
# Trying to access private variable directly
# print(s1.__marks) # Error
Output:
Name: Ravi
Marks: 85
Class Definition
class Student:

● This statement creates a class named Student, which acts as a blueprint for creating
student objects containing data and methods.

Constructor Method

def __init__(self, name, marks):

● The __init__() method is a constructor that automatically initializes the object data when
an object is created.

Public Variable
[Link] = name

● This statement creates a public variable name that stores the student’s name and can be
accessed anywhere inside or outside the class.

Private Variable
self.__marks = marks

● This statement creates a private variable __marks that stores the student’s marks securely
and cannot be accessed directly outside the class.

Method
def display(self):

● This statement defines a method named display that is used to access and display both
public and private data of the object safely.

Access Specifiers
Access specifiers define how class members (variables and methods) can be accessed from
outside the class. They help in implementing encapsulation by controlling the visibility of data.
There are three types of access specifiers:
1. Public Members
Public members are variables or methods that can be accessed from anywhere inside the class,
outside the class or from other modules. By default, all members in Python are public. They are
defined without any underscore prefix (e.g., [Link]).
Example: This example shows how a public attribute (name) and a public method
(display_name) can be accessed from outside the class using an object.
class Employee:
def __init__(self, name):
[Link] = name # public attribute

def display_name(self): # public method


print([Link])

emp = Employee("John")
emp.display_name() # Accessible
print([Link]) # Accessible

Output
John
John

Explanation:
[Link]: Declared without underscores, so it is public.
display_name(): Public method that prints the value of the public attribute.
[Link]: Directly accessed from outside the class, showing public members are fully
accessible.
Note: __init__ method is a constructor and runs as soon as an object of a class is instantiated.
2. Protected members
Protected members are variables or methods that are intended to be accessed only within the
class and its subclasses. They are not strictly private but should be treated as internal. In Python,
protected members are defined with a single underscore prefix (e.g., self._name).Example: This
example shows how a protected attribute (_age) can be accessed within a subclass,
demonstrating that protected members are meant for use within the class and its subclasses.
class Employee:
def __init__(self, name, age):
[Link] = name # public
self._age = age # protected

class SubEmployee(Employee):
def show_age(self):
print("Age:", self._age) # Accessible in subclass

emp = SubEmployee("Ross", 30)


print([Link]) # Public accessible
emp.show_age() # Protected accessed through subclass

Output
Ross
Age: 30

Explanation:

● self._age: Defined with a single underscore, marking it as protected.


● SubEmployee: Inherits from Employee and can access _age directly.
● Protected members should not be accessed outside the class hierarchy, but Python does
not enforce this rule strictly.

3. Private members
Private members are variables or methods that cannot be accessed directly from outside the class.
They are used to restrict access and protect internal data. In Python, private members are defined
with a double underscore prefix (e.g., self.__salary).
Python uses name mangling, where the interpreter internally renames the variable (for eg,
__salary becomes _ClassName__salary). This discourages direct access from outside the class,
although it does not create strict privacy like other languages.

Example: This example shows how a private attribute (__salary) is accessed within the class
using a public method, demonstrating that private members cannot be accessed directly from
outside the class.
class Employee:
def __init__(self, name, salary):
[Link] = name # public
self.__salary = salary # private

def show_salary(self):
print("Salary:", self.__salary)

emp = Employee("Robert", 60000)


print([Link]) # Public accessible
emp.show_salary() # Accessing private correctly
# print(emp.__salary) # Error: Not accessible directly

Output
Robert
Salary: 60000

Explanation:
self.__salary: Defined with double underscores, so it is private.
show_salary(): A public method that provides safe access to the private attribute.
Attempting emp.__salary causes an AttributeError, proving private members cannot be accessed
directly.

Inheritance in Python
Inheritance is an OOP concept in which one class acquires the properties and methods of another
class.
● The existing class is called the Base Class or Parent Class
● The new class is called the Derived Class or Child Class
Inheritance helps in:
● Code reusability
● Reducing duplicate code
● Easy program maintenance
Accessing the Inherited Variables and Methods
Here, a parent class Animal is created that has a method info(). Then a child classes Dog is
created that inherit from Animal and add their own behavior.
class Animal:
def __init__(self, name):
[Link] = name

def info(self):
print("Animal name:", [Link])

class Dog(Animal):
def sound(self):
print([Link], "barks")

d = Dog("Buddy")
# Inherited method
[Link]()
[Link]()
Output
Animal name: Buddy

Buddy barks

Explanation:
● class Animal defines the parent class.
● info() prints the name of the animal.
● class Dog(Animal) defines Dog as a child of Animal class.
● [Link]() calls parent method info() and [Link]() calls child method.

super() Function
super() function is used to call methods from a superclass following Python’s Method Resolution
Order (MRO). In particular, it is commonly used in the child class's __init__() method to
initialize inherited attributes. This way, the child class can leverage the functionality of the
parent class.

Example: Here, Dog uses super() to call Animal's constructor.


# Parent Class: Animal
class Animal:
def __init__(self, name):
[Link] = name
def info(self):
print("Animal name:", [Link])
# Child Class: Dog
class Dog(Animal):
def __init__(self, name, breed):
# Calls constructor based on MRO
super().__init__(name)
[Link] = breed
def details(self):
print([Link], "is a", [Link])
d = Dog("Buddy", "Golden Retriever")
[Link]() # Parent method
[Link]() # Child method

Output
Animal name: Buddy
Buddy is a Golden Retriever
Explanation:
● super() function is used inside __init__() method of Dog to call the constructor of
Animal and initialize inherited attribute (name).
● This ensures that parent class functionality is reused without needing to rewrite the
code in the child class.
Using super() Function and Overriding Base Class Methods
Method overriding is an ability of any object-oriented programming language that allows a
subclass or child class to provide a specific implementation of a method that is already provided
by one of its super-classes or parent classes. When a method in a subclass has the same name, the
same parameters or signature, and same return type(or sub-type) as a method in its super-class,
then the method in the subclass is said to override the method in the super-class.
Example1:
class Animal:
def sound(self):
print("Animals make sound")
class Dog(Animal):
def sound(self):
print("Dog barks")
d = Dog()
[Link]()
Output:
Dog barks
Example 2:

class Animal:
def __init__(self, name):
[Link] = name

def sound(self):
print([Link], "makes a sound")

class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # Calling parent constructor
[Link] = breed

# Overriding parent method


def sound(self):
print([Link], "barks")

def display(self):
print("Name:", [Link])
print("Breed:", [Link])

d = Dog("Buddy", "Labrador")

[Link]()
[Link]()
Output:
Name: Buddy
Breed: Labrador
Buddy barks

Multiple Inheritance
Multiple inheritance means a child class inherits properties and methods from more than one
parent class.

● A single child class can access members of multiple parent classes


● It helps in code reusability
● The child class combines features of different classes

Multiple Inheritances
Multiple inheritance means a child class inherits properties and methods from more than one
parent class.
● A single child class can access members of multiple parent classes
● It helps in code reusability
● The child class combines features of different classes

class Father:
def skill1(self):
print("Father knows Gardening")
class Mother:
def skill2(self):
print("Mother knows Cooking")
class Child(Father, Mother):
def skill3(self):
print("Child knows Painting")
c = Child()
c.skill1()
c.skill2()
c.skill3()

Output:
Father knows Gardening
Mother knows Cooking
Child knows Painting

The two create parent classes named Father and Mother.


Skills define methods in the parent classes.
create a child class Child.
The child class inherits methods from both Father and Mother.
Create a method that belongs to the child class.
The child object accesses methods from both parent classes and its own class.

Method Resolution Order (MRO)


MRO defines the order in which Python searches for methods when multiple inheritance is used.

● Python searches classes from left to right


● It follows depth-first search
● MRO avoids confusion when the same method exists in multiple classes

class Teacher:
def show(self):
print("Teacher teaches Mathematics")
class Singer:
def show(self):
print("Singer sings songs")
class Student(Teacher, Singer):
pass
s = Student()
[Link]()
print([Link]())

Output:
Teacher teaches Mathematics
[<class '__main__.Student'>,
<class '__main__.Teacher'>,
<class '__main__.Singer'>,
<class 'object'>]

➢ Create two parent classes named Teacher and Singer.


➢ Both classes contain a method named show().
➢ The child class Student inherits from both Teacher and Singer.
➢ creates an object of class Student.
➢ Python first searches for the method show() in class Student.
➢ Since Student does not contain the method, Python searches in Teacher.
➢ The method is found in Teacher, so that method is executed.
➢ Python does not search further in Singer.
➢ Student → Teacher → Singer → object
➢ Python searches methods in this order.

Method Resolution Order (MRO) is the order followed by Python to search for methods
and variables in inheritance hierarchy, especially in multiple [Link] Python
multiple inheritance, searching left to right means Python checks the parent classes in the
same order they are written inside the child class.

Polymorphism
Polymorphism is an Object-Oriented Programming (OOP) concept in which the same method
name can perform different actions depending on the object.

● The word Polymorphism means “many forms”


● A single method behaves differently for different classes
● It is mainly achieved using method overriding

Polymorphism helps to:

● Increase flexibility in programs


● Reduce code complexity
● Improve code reusability
● Use the same interface for different objects

class Payment:
def pay(self):
print("Payment processing")
class CreditCard(Payment):
def pay(self):
print("Payment made using Credit Card")
class UPI(Payment):
def pay(self):
print("Payment made using UPI")
class Cash(Payment):
def pay(self):
print("Payment made using Cash")
c1 = CreditCard()
u1 = UPI()
ca1 = Cash()
[Link]()
[Link]()
[Link]()

Output:
Payment made using Credit Card
Payment made using UPI
Payment made using Cash
➢ Create a parent class named Payment.
➢ pay method defines a general payment action.
➢ Each child class overrides the pay() method.
➢ Different payment methods provide different implementations.
➢ Create objects of different payment classes.
➢ The same method pay() behaves differently for different objects.
➢ This demonstrates polymorphism.

Operator Overloading in Python


Operator overloading is a feature in Python that allows operators to work differently for user-
defined objects.
● Python operators like +, -, *, > already work with numbers
● Using operator overloading, we can make these operators work with objects also
● It is achieved using special methods (magic methods)
Operator overloading helps:
● Make programs more readable
● Perform operations directly on objects
● Provide special meaning to operators for user-defined classes
Common Special Methods
Operator Special Method

+ __add__()

- __sub__()

* __mul__()
> __gt__()

< __lt__()

== __eq__()

class Student:
def __init__(self, marks):
[Link] = marks
# Overloading + operator
def __add__(self, other):
return [Link] + [Link]
s1 = Student(80)
s2 = Student(90)
result = s1 + s2
print("Total Marks:", result)

Output:
Total Marks: 170

➢ creates a class named Student.


➢ Using the constructor initializes the variable marks.
➢ def __add__() method overloads the + operator.
➢ self refers to the first object (s1)
➢ other refers to the second object (s2)
➢ This statement adds marks of both objects.
➢ Create two objects of class Student.
➢ The + operator works on objects because of operator overloading.

You might also like