Checking your session…
Module 06: Object-Oriented & Advanced Python

Object-Oriented Programming

Level: 9 | Version: v1.0 | Author: Meptrasoft

Object-Oriented Programming (OOP) organizes a program around objects — self-contained units that bundle data (attributes) and behavior (methods). This module builds OOP from the ground up: classes and objects, the four pillars (encapsulation, inheritance, polymorphism, abstraction), and inner classes — with real-world examples, comparison tables, interview questions, and practice throughout.


Classes and Objects

Introduction to OOP

Definition & Core Concepts

Object-Oriented Programming (OOP) is a programming paradigm that organizes a program using objects. An object represents a real-world entity and contains data (attributes) and behavior (methods). OOP helps make programs more organized, reusable, and easier to maintain.

Example:

PYTHON
class Dog:
    def bark(self):
        print("Woof! Woof!")
dog1 = Dog()
dog1.bark()

Output:

TEXT
Woof! Woof!
  • Dog is a class.
  • dog1 is an object.
  • bark() is a method.
  • The object dog1 calls the bark() method.
Class = blueprint class Student attributes: name, marks methods: study(), show() creates object: arun "Arun", 92 object: meena "Meena", 88 objects = real instances of the class Inheritance: child reuses parent Animal Dog(Animal) Cat(Animal)
A class is a blueprint; objects are real instances built from it. Inheritance lets a child class reuse a parent's attributes and methods.

Why Do We Use Object-Oriented Programming?

OOP helps us organize related data and functions into a single unit called an object. This makes programs easier to read, manage, reuse, and expand.

Without OOP:

PYTHON
student1_name = "Arun"
student1_age = 21
student2_name = "Priya"
student2_age = 22
print(student1_name)
print(student2_name)

When the number of students increases, managing separate variables becomes difficult.

With OOP:

PYTHON
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
student1 = Student("Arun", 21)
student2 = Student("Priya", 22)
print(student1.name)
print(student2.name)

Each student's information is stored inside its own object, making the code clean and organized.

Procedural Programming vs Object-Oriented Programming

Procedural Programming Object-Oriented Programming
Focuses on functions Focuses on objects
Data and functions are separate Data and methods are grouped together
Suitable for small programs Suitable for small and large programs
More code duplication Better code reuse
Harder to maintain large projects Easier to maintain and extend

Procedural Programming Example:

PYTHON
def student_details(name, age):
    print(name)
    print(age)
student_details("Arun", 21)

Object-Oriented Programming Example:

PYTHON
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def display(self):
        print(self.name)
        print(self.age)
student = Student("Arun", 21)
student.display()

Basic Structure of an OOP Program

Every OOP program follows a simple structure:

PYTHON
class Student:
    def display(self):
        print("Hello")
student = Student()
student.display()

Structure Explanation:

Part Description
class Defines a blueprint for creating objects
Student Name of the class
display() A method that defines an action
student An object created from the class
student.display() Calls the object's method

Real-World Examples of OOP

Real-World Entity Class Objects
Car Car BMW, Audi, Tesla
Student Student Arun, Priya
Mobile Phone Mobile iPhone, Samsung
Employee Employee John, David
Bank Account BankAccount Account1, Account2

Advantages of OOP

Advantage Description
Code Reusability Reuse existing classes instead of writing the same code again
Better Organization Related data and methods stay together
Easy Maintenance Programs are easier to update and debug
Scalability Easy to add new features as the program grows
Real-World Modeling Objects closely represent real-world entities

Placement Quick Points

  • OOP stands for Object-Oriented Programming.
  • OOP organizes a program using objects.
  • Objects contain attributes (data) and methods (behavior).
  • A class is a blueprint used to create objects.
  • OOP improves code organization, reusability, and maintainability.
  • Python supports Object-Oriented Programming along with procedural programming.
  • The four main pillars of OOP are:
    • Inheritance
    • Encapsulation
    • Polymorphism
    • Abstraction

Interview Questions

What is Object-Oriented Programming (OOP)?
Object-Oriented Programming (OOP) is a programming paradigm that organizes programs using objects, where each object contains data and the functions that operate on that data.
Why is OOP used?
OOP is used to make programs more organized, reusable, maintainable, and easier to expand.
What is the difference between Procedural Programming and OOP?

The differences are:

Procedural Programming Object-Oriented Programming
Function-based Object-based
Data and functions are separate Data and methods are grouped together
Best for small programs Better for large applications
What are the four pillars of OOP?

The four pillars are:

  • Inheritance
  • Encapsulation
  • Polymorphism
  • Abstraction
Does Python support Object-Oriented Programming?
Yes. Python fully supports Object-Oriented Programming and also supports procedural and functional programming.
Give a real-world example of OOP.

A Car is an example of OOP.

  • Attributes: Brand, Color, Speed
  • Methods: Start, Stop, Accelerate

Practice

  1. Write a class named Car with a method start() that prints "Car Started".
  2. Create an object of the Car class and call the start() method.
  3. List three real-world objects and write two attributes and two methods for each.
  4. Write one advantage of Object-Oriented Programming over Procedural Programming.
  5. Identify the class and the object in the following code:

    PYTHON
    class Student:
        pass
    student1 = Student()
    
  6. Explain in your own words why OOP is useful for large applications.

Class Fundamentals

Definition & Purpose

A class is a blueprint or template used to create objects. It defines the attributes (data) and methods (functions) that all objects created from the class will have.

A class itself does not store individual data. Instead, it provides the structure from which objects are created.

Example:

PYTHON
class Student:
    pass
  • class is the keyword used to define a class.
  • Student is the name of the class.
  • pass is a placeholder that allows us to create an empty class.

At this stage, the class only defines a blueprint. No object has been created yet.

Key Takeaway: Class vs Object Data

A class defines the blueprint and behavior. Individual object data, such as a student's name or marks, is stored only after an object is created using class ClassName: object_name = ClassName().

Why Do We Use a Class?

A class allows us to create multiple objects with the same structure instead of writing duplicate code.

Without a Class:

PYTHON
student1_name = "Arun"
student1_age = 21
student2_name = "Priya"
student2_age = 22
print(student1_name)
print(student2_name)

Managing many students like this becomes difficult.

With a Class:

PYTHON
class Student:
    pass
student1 = Student()
student2 = Student()
print(student1)
print(student2)

Each object is created from the same class, making the program more organized.

How to Create a Class?

Use the class keyword followed by the class name.

Syntax:

PYTHON
class ClassName:
    pass

Example:

PYTHON
class Car:
    pass
class Employee:
    pass
class Mobile:
    pass

A good practice is to write class names using PascalCase.

Naming Convention for Classes

Python recommends using PascalCase for class names.

Incorrect Correct
student Student
bank_account BankAccount
employee_details EmployeeDetails
mobile_phone MobilePhone

Example:

PYTHON
class BankAccount:
    pass

Creating Multiple Objects from One Class

A single class can be used to create many objects.

PYTHON
class Student:
    pass
student1 = Student()
student2 = Student()
student3 = Student()
print(student1)
print(student2)
print(student3)

Each object is different, even though they are created from the same class.

Class vs Object

Class Object
Blueprint or template Instance created from the class
Defines the structure Holds actual data
Created using class keyword Created by calling the class
One class can create many objects Each object is independent

Example:

Output:

TEXT
class Car:
    pass
car1 = Car()
print(car2 = Car())
print(car2)
print(car2)

Output:

PYTHON
<Car object at 0x000002B6AB273F90>
<Car object at 0x000002B6AB273F90>

Empty Class

Sometimes we create a class first and implement it later.

PYTHON
class Student:
    pass

The pass keyword tells Python to do nothing for now.

Checking the Type of an Object

Every object belongs to a class.

Output:

TEXT
class Student:
    pass
student1 = Student()
print(type(student1))

Output:

PYTHON
<class 'Student'>

This shows that student1 is an object of the Student class.

Placement Quick Points

  • A class is a blueprint used to create objects.
  • Classes are created using the class keyword.
  • Python follows PascalCase naming for class names.
  • A class can create multiple objects.
  • A class defines the structure of objects.
  • pass is used to create an empty class.
  • Objects created from the same class are independent of each other.

Interview Questions

What is a class?
A class is a blueprint or template used to create objects. It defines the attributes and methods that objects will have.
Which keyword is used to create a class?
The class keyword.
What is the purpose of the pass keyword in a class?
The pass keyword creates an empty class without causing a syntax error.
Can one class create multiple objects?
Yes. A single class can be used to create any number of objects.
What naming convention is recommended for Python class names?
PascalCase.
PYTHON
class StudentDetails:
pass
What is the difference between a class and an object?
A class is a blueprint, while an object is an instance created from that blueprint.

Practice

  1. Create an empty class named Student.
  2. Create an empty class named Car.
  3. Create three objects from a class named Employee.
  4. Write the correct class names using PascalCase:
  5. bank_account
  6. student_details
  7. mobile_phone
  8. Identify the class and objects in the following code:

    Output:

    TEXT
    class Animal:
        pass
    dog = Animal()
    cat = Animal()
    
  9. Write a program to create an empty class named Book and create two objects from it.

Objects

What is an Object?

An object is an instance of a class. It is created from a class and represents a real-world entity. An object can store its own data (attributes) and perform actions (methods) defined by the class.

Example:

PYTHON
class Student:
    pass
student1 = Student()
  • Student is a class.
  • student1 is an object created from the Student class.
  • The object is an instance of the class.

Why Do We Use Objects?

Objects allow us to create multiple independent instances from the same class. Each object can represent a different real-world entity.

Example:

PYTHON
class Student:
    pass
student1 = Student()
student2 = Student()
student3 = Student()
print(student1)
print(student2)
print(student3)

Output:

TEXT
<Student object at 0x...>
<Student object at 0x...>
<Student object at 0x...>

Although all three objects are created from the same class, each object is different.

How to Create an Object?

An object is created by calling the class name followed by parentheses ().

Syntax:

PYTHON
object_name = ClassName()

Example:

PYTHON
class Car:
    pass
car1 = Car()
print(car2 = Car())

Output:

TEXT
Car → Class
car1 → Object
car2 → Object

Multiple Objects from One Class

One class can create any number of objects.

PYTHON
class Employee:
    pass
employee1 = Employee()
employee2 = Employee()
employee3 = Employee()

Every object is created using the same blueprint.

Objects are Independent

Each object is stored separately in memory.

Output:

TEXT
class Student:
    pass
student1 = Student()
student2 = Student()
print(student1 == student2)

Output:

PYTHON
False

Even though both objects belong to the same class, they are different objects.

Checking the Type of an Object

Use the type() function to check the class of an object.

Output:

TEXT
class Student:
    pass
student1 = Student()
print(type(student1))

Output:

PYTHON
<class 'Student'>

This confirms that student1 is an object of the Student class.

Checking the Identity of an Object

Use the id() function to view the unique identity value of an object during the program run.

PYTHON
class Student:
    pass
student1 = Student()
student2 = Student()
print(id(student1))
print(id(student2))

Output:

TEXT
2983578767632
2983578767952

The values may be different on every computer or every run, but each object has its own unique identity.

One Class, Many Objects

PYTHON
class Dog:
    pass
dog1 = Dog()
dog2 = Dog()
dog3 = Dog()
Class Objects
Dog dog1
Dog dog2
Dog dog3

A single class can create multiple objects.

Real-World Examples

Class Objects
Student Arun, Priya, Rahul
Car BMW, Audi, Tesla
Mobile iPhone, Samsung
Employee John, David
Book Python Book, Java Book

Placement Quick Points

  • An object is an instance of a class.
  • Objects are created by calling the class name using ().
  • A single class can create multiple objects.
  • Each object is independent and has its own identity.
  • Use type() to check an object's class.
  • Use id() to check an object's unique identity value.

Interview Questions

What is an object?
An object is an instance of a class. It represents a real-world entity and is created from a class.
How do you create an object in Python?
By calling the class name with parentheses.
PYTHON
student = Student()
Can one class create multiple objects?
Yes. A single class can create any number of objects.
Which function is used to check an object's class?
The type() function.
PYTHON
print(type(student))
Which function is used to check an object's identity?
The id() function.
PYTHON
print(id(student))
Are two objects created from the same class equal?
No. They are separate instances with different identities.

Practice

  1. Create a class named Car and create two objects from it.
  2. Create three objects from a class named Employee.
  3. Use the type() function to check the type of an object.
  4. Use the id() function to print the identity of two different objects.
  5. Identify the class and objects in the following code:

    PYTHON
    class Animal:
        pass
    dog = Animal()
    cat = Animal()
    
  6. What will be the output of the following code?

    TEXT
    class Student:
        pass
    student1 = Student()
    student2 = Student()
    print(student1 == student2)
    

Explain why the output is produced.

__init__() and self

What is __init__()?

__init__() is a special method (constructor) in Python that is automatically called whenever an object is created. It is mainly used to initialize the object's attributes with initial values.

Example:

PYTHON
class Student:
    def __init__(self):
        print("Object Created")
student1 = Student()

Output:

TEXT
Object Created
  • __init__() is called automatically when Student() is executed.
  • We do not call __init__() directly.
  • It runs once for every new object that is created.

Why Do We Use __init__()?

Without __init__(), we have to assign values to each object manually.

Without __init__():

PYTHON
class Student:
    pass
student1 = Student()
student1.name = "Arun"
student1.age = 21
print(student1.name)
print(student1.age)

With __init__():

Output:

TEXT
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
student1 = Student("Arun", 21)
print(student1.name)
print(student1.age)

Using __init__() makes object creation easier and ensures every object is initialized properly.

How to Create a Constructor?

A constructor is created using the special method __init__().

Syntax:

TEXT
class ClassName:
    def __init__(self):
        pass

Example:

PYTHON
class Car:
    def __init__(self):
        print("Car Object Created")
car1 = Car()

Constructor Without Parameters

A constructor can simply perform an action when an object is created.

Output:

TEXT
class Student:
    def __init__(self):
        print("Welcome!")
student1 = Student()
student2 = Student()

Output:

PYTHON
Welcome!
Welcome!

The constructor runs once for each object.

Constructor With Parameters

The constructor can receive values while creating an object.

PYTHON
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
student1 = Student("Arun", 21)
print(student1.name)
print(student1.age)

Output:

PYTHON
Arun
21

What is self?

self is a reference to the current object. It allows an object to access its own attributes and methods.

Example:

Output:

TEXT
class Student:
    def __init__(self, name):
        self.name = name
class Student:
class Student:
    pass
student1 = Student()
student2 = Student()
student1 = Student("Arun")
print(student1.name)

Output:

PYTHON
Arun

When student1 is created:

PYTHON
student1 ------------> Student Object
                           |
                        self.name
                           |
                         "Arun"

self.name stores the value inside the current object.

Why Do We Use self?

self helps Python identify which object's data should be used.

Example:

Output:

TEXT
class Student:
    def __init__(self, name):
        self.name = name
student1 = Student("Arun")
student2 = Student("Priya")
print(student1.name)
print(student2.name)

Output:

PYTHON
Arun
Priya

Each object stores its own value because of self.

How Does self Work?

When we create an object:

Output:

TEXT
student1 = Student("Arun")

Python internally works like this:

PYTHON
class Student:
Student.__init__(student1, "Arun")
  • self refers to student1.
  • Python passes the object automatically.
  • We do not pass self manually.

Constructor vs Normal Method

Constructor (__init__()) Normal Method
Called automatically Called manually
Runs when an object is created Runs only when invoked
Used to initialize objects Used to perform actions
Defined using __init__() Can have any valid method name

Example:

PYTHON
class Student:
    def __init__(self):
        print("Constructor")
    def display(self):
        print("Normal Method")
student = Student()
student.display()

Output:

PYTHON
Constructor
Normal Method

self vs Object Name

Output:

TEXT
class Student:
    def __init__(self, name):
        self.name = name
student = Student("Arun")
print(student.name)
Inside the Class Outside the Class
self.name student.name
Refers to the current object Refers to a specific object

Placement Quick Points

  • __init__() is a special method called automatically when an object is created.
  • __init__() is also known as the constructor.
  • self refers to the current object.
  • self is passed automatically by Python.
  • self is used to access an object's attributes and methods.
  • Every object has its own copy of data stored using self.
  • __init__() is mainly used to initialize object attributes.

Interview Questions

What is __init__()?
__init__() is a special method (constructor) that is automatically called when an object is created.
Why is __init__() used?
It is used to initialize the attributes of an object when it is created.
What is self in Python?
self is a reference to the current object. It allows an object to access its own attributes and methods.
Do we need to pass self while creating an object?
No. Python passes self automatically.
What is the difference between __init__() and a normal method?

The differences are:

__init__() Normal Method
Called automatically Called manually
Initializes the object Performs actions
Can a constructor have parameters?
Yes. A constructor can accept parameters to initialize object attributes.
PYTHON
class Student:
def __init__(self, name):
self.name = name

Practice

  1. Create a class Student with a constructor that prints "Student Created".
  2. Create a class Car with a constructor that accepts brand and stores it using self.
  3. Create two Student objects with different names and print their names.
  4. Explain the purpose of self in your own words.
  5. What will happen if you remove self from the __init__() method?
  6. Identify the constructor and the object in the following code:

    Output:

    TEXT
    class Employee:
        def __init__(self, name):
            self.name = name
    employee = Employee("Rahul")
    

Attributes

What are Attributes?

Attributes are variables that belong to an object or a class. They are used to store the data or properties of an object.

For example, a student has attributes like name, age, and marks.

Example:

PYTHON
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
student1 = Student("Arun", 21)
print(student1.name)
print(student1.age)

Output:

PYTHON
Arun
21
  • name and age are attributes.
  • self.name stores the student's name.
  • self.age stores the student's age.

Why Do We Use Attributes?

Attributes allow every object to store its own data.

Example:

Output:

TEXT
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age
student1 = Student("Arun", 21)
student2 = Student("Priya", 22)
print(student1.name)
print(student2.name)

Output:

PYTHON
Arun
Priya

Although both objects belong to the same class, each object stores different values.

How to Create Attributes?

Attributes are usually created inside the __init__() method using self.

Syntax:

Output:

TEXT
self.attribute_name = value

Example:

PYTHON
class Car:
    def __init__(self, brand, color):
        self.brand = brand
        self.color = color
car1 = Car("BMW", "Black")
print(car1.brand)
print(car1.color)

Accessing Attributes

Use the dot (.) operator to access an object's attributes.

Example:

PYTHON
class Student:
    def __init__(self, name):
        self.name = name
student1 = Student("Arun")
print(student1.name)

Output:

TEXT
Arun

Modifying Attributes

An attribute's value can be changed after the object is created.

Example:

PYTHON
class Student:
    def __init__(self, name):
        self.name = name
student1 = Student("Arun")
student1.name = "Rahul"
print(student1.name)

Output:

PYTHON
Rahul

Deleting Attributes

Use the del keyword to remove an attribute from an object.

Example:

Output:

TEXT
class Student:
    def __init__(self, name):
        self.name = name
student1 = Student("Arun")
del student1.name

After deleting the attribute, trying to access it will result in an error.

Instance Attributes

An instance attribute belongs to an individual object. Every object has its own copy.

Example:

PYTHON
class Student:
    def __init__(self, name):
        self.name = name
student1 = Student("Arun")
student2 = Student("Priya")
print(student1.name)
print(student2.name)

Output:

PYTHON
Arun
Priya

Each object stores its own value for name.

Class Attributes

A class attribute belongs to the class itself and is shared by all objects.

Example:

PYTHON
class Student:
    school = "ABC School"
student1 = Student()
student2 = Student()
print(student1.school)
print(student2.school)

Output:

TEXT
ABC School
ABC School

Both objects access the same class attribute.

Instance Attributes vs Class Attributes

Instance Attribute Class Attribute
Belongs to an object Belongs to the class
Created using self Created inside the class, outside methods
Each object has its own copy Shared by all objects
Can have different values Same value for all objects (unless modified)

Example:

PYTHON
class Student:
    school = "ABC School"
    def __init__(self, name):
        self.name = name
student1 = Student("Arun")
student2 = Student("Priya")
print(student1.name)
print(student2.name)
print(student1.school)
print(student2.school)

Placement Quick Points

  • Attributes are variables that store data for a class or an object.
  • Attributes are usually created inside the __init__() method using self.
  • Use the dot (.) operator to access attributes.
  • Attribute values can be modified after object creation.
  • Use the del keyword to delete an attribute.
  • Instance attributes belong to individual objects.
  • Class attributes are shared by all objects of a class.

Interview Questions

What are attributes in Python?
Attributes are variables that belong to a class or an object and store data.
Where are instance attributes usually created?
Inside the __init__() method using self.
How do you access an attribute?
Using the dot (.) operator.

Output:

TEXT
print(student.name)
What is the difference between an instance attribute and a class attribute?

The differences are:

Instance Attribute Class Attribute
Belongs to an object Belongs to the class
Unique for each object Shared by all objects
Can an attribute be modified after object creation?
Yes.
PYTHON
student.name = "Rahul"
Which keyword is used to delete an attribute?
The del keyword.

Output:

TEXT
del student.name

Practice

  1. Create a Student class with attributes name and age.
  2. Create two student objects with different values and print their attributes.
  3. Create a Car class with attributes brand and color.
  4. Modify the color attribute of a car object after it is created.
  5. Create a class attribute named country with the value "India" and access it using two different objects.
  6. Identify the instance attribute and the class attribute in the following code:
    PYTHON
    class Employee:
        company = "ABC Technologies"
        def __init__(self, name):
            self.name = name
    

Methods

What are Methods?

A method is a function defined inside a class. Methods define the behavior or actions that an object can perform.

For example, a car can start, stop, and accelerate. These actions are represented as methods.

Example:

Output:

TEXT
class Car:
    def start(self):
        print("Car Started")
car1 = Car()
car1.start()

Output:

PYTHON
Car Started
  • start() is a method.
  • It is defined inside the Car class.
  • car1.start() calls the method.

Why Do We Use Methods?

Methods allow objects to perform actions instead of only storing data.

Without Methods:

Output:

TEXT
class Student:
    def __init__(self, name):
        self.name = name
student1 = Student("Arun")
print(student1.name)
print("Welcome", student1.name)

With Methods:

PYTHON
class Student:
    def __init__(self, name):
        self.name = name
    def greet(self):
        print("Welcome", self.name)
student1 = Student("Arun")
student1.greet()

Output:

PYTHON
Welcome Arun

The greeting logic is now part of the class, making the code cleaner and reusable.

How to Create a Method?

Methods are created inside a class using the def keyword.

Syntax:

Output:

TEXT
class ClassName:
    def method_name(self):
        pass

Example:

PYTHON
class Dog:
    def bark(self):
        print("Woof! Woof!")
dog1 = Dog()
dog1.bark()

Calling a Method

A method is called using the dot (.) operator.

Example:

Output:

TEXT
class Employee:
    def work(self):
        print("Employee is working")
employee1 = Employee()
employee1.work()

Output:

PYTHON
Employee is working

Methods with Parameters

A method can receive additional values through parameters.

Example:

Output:

TEXT
class Calculator:
    def add(self, a, b):
        print(a + b)
calc = Calculator()
calc.add(10, 20)

Output:

PYTHON
30
  • self refers to the current object.
  • a and b are parameters passed to the method.

Methods Returning Values

A method can return a value using the return statement.

Example:

PYTHON
class Calculator:
    def add(self, a, b):
        return a + b
calc = Calculator()
result = calc.add(10, 20)
print(result)

Output:

PYTHON
30

Accessing Attributes Inside Methods

Methods can access an object's attributes using self.

Example:

PYTHON
class Student:
    def __init__(self, name):
        self.name = name
    def display(self):
        print("Student Name:", self.name)
student1 = Student("Arun")
student1.display()

Output:

PYTHON
Student Name: Arun

Calling One Method from Another Method

A method can call another method of the same object using self.

Example:

PYTHON
class Student:
    def greet(self):
        print("Welcome!")
    def display(self):
        self.greet()
        print("Learning Python")
student1 = Student()
student1.display()

Output:

TEXT
Welcome!
Learning Python

Methods vs Functions

Method Function
Defined inside a class Defined outside a class
Called using an object Called directly
Has self as the first parameter Does not require self
Represents an object's behavior Performs a general task

Example:

PYTHON
def greet():
    print("Hello")
class Student:
    def greet(self):
        print("Hello Student")
greet()
student = Student()
student.greet()

Readable Objects with __str__

By default, printing an object shows something like <__main__.Student object at 0x...>, which is not helpful. Defining a __str__() method lets you control what print() displays.

Example:

PYTHON
class Student:
    def __init__(self, name, marks):
        self.name = name
        self.marks = marks
    def __str__(self):
        return f"Student: {self.name}, Marks: {self.marks}"

student = Student("Arun", 90)
print(student)

Output:

PYTHON
Student: Arun, Marks: 90
  • __str__() must return a string.
  • print(student) now shows a meaningful message instead of the memory address.

Python also provides __repr__(), which gives the developer-facing form of an object (used in the interactive shell and when printing a list of objects). If __str__() is not defined, print() falls back to __repr__().

PYTHON
class Student:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return f"Student('{self.name}')"

student = Student("Arun")
print(student)

Output:

TEXT
Student('Arun')

Placement Quick Points

  • A method is a function defined inside a class.
  • Methods define the behavior of an object.
  • Methods are created using the def keyword.
  • The first parameter of an instance method is self.
  • Methods are called using the dot (.) operator.
  • Methods can accept parameters.
  • Methods can return values using return.
  • Methods can access object attributes using self.

Interview Questions

What is a method?
A method is a function defined inside a class that represents the behavior of an object.
How do you call a method?
Using the dot (.) operator.
TEXT
student.display()
What is the first parameter of an instance method?
self
Can methods accept parameters?
Yes.
PYTHON
class Calculator:
def add(self, a, b):
return a + b
Can methods return values?
Yes. A method can return values using the return statement.
What is the difference between a method and a function?

The differences are:

Method Function
Inside a class Outside a class
Called using an object Called directly
Uses self Does not use self

Practice

  1. Create a Car class with a method start() that prints "Car Started".
  2. Create a Student class with a method display() that prints the student's name.
  3. Create a Calculator class with a method multiply(a, b) that returns the product.
  4. Write a class Dog with two methods: bark() and sleep().
  5. Create a class Employee with a method work(). Create two objects and call the method for both.
  6. Identify the methods in the following code:

    Output:

    TEXT
    class Mobile:
        def call(self):
            print("Calling...")
        def message(self):
            print("Sending Message")
    

Inheritance

Inheritance Basics

What is Inheritance?

Inheritance is an Object-Oriented Programming (OOP) feature that allows one class (child class) to inherit the attributes and methods of another class (parent class). It helps in reusing existing code and creating a relationship between classes.

Example:

TEXT
class Animal:
    def eat(self):
        print("Animal is eating")
class Dog(Animal):
    pass
dog = Dog()
dog.eat()

Output:

PYTHON
Animal is eating
  • Animal is the parent class.
  • Dog is the child class.
  • Dog inherits the eat() method from Animal.
  • Therefore, dog.eat() works even though eat() is not defined inside the Dog class.

Why Do We Use Inheritance?

Inheritance allows us to reuse code instead of writing the same methods again in multiple classes.

Without Inheritance:

Output:

TEXT
class Dog:
    def eat(self):
        print("Animal is eating")
class Cat:
    def eat(self):
        print("Animal is eating")

The eat() method is duplicated in both classes.

With Inheritance:

TEXT
class Animal:
    def eat(self):
        print("Animal is eating")
class Dog(Animal):
    pass
class Cat(Animal):
    pass
dog = Dog()
cat = Cat()
dog.eat()
cat.eat()

Now both classes reuse the same eat() method from the parent class.

How to Create Inheritance?

A child class is created by passing the parent class name inside parentheses.

Syntax:

PYTHON
class Parent:
    pass
class Child(Parent):
    pass

Example:

Output:

TEXT
class Vehicle:
    def start(self):
        print("Vehicle Started")
class Car(Vehicle):
    pass
car = Car()
car.start()

Parent Class

A parent class (also called a base class or superclass) is the class whose attributes and methods are inherited by another class.

Example:

TEXT
class Animal:
    def sleep(self):
        print("Sleeping...")

Animal is the parent class.

Child Class

A child class (also called a derived class or subclass) inherits the attributes and methods of the parent class.

Example:

PYTHON
class Animal:
    def sleep(self):
        print("Sleeping...")
class Dog(Animal):
    pass
dog = Dog()
dog.sleep()

Output:

TEXT
Sleeping...

Dog inherits the sleep() method from Animal.

Placement Quick Points

  • Inheritance allows one class to inherit another class's attributes and methods.
  • The class being inherited is called the parent class.
  • The class that inherits is called the child class.
  • Inheritance helps in code reusability.
  • A child class can directly use the methods of its parent class.
  • Inheritance creates an "is-a" relationship between classes.

Interview Questions

What is inheritance?
Inheritance is an OOP feature where one class acquires the attributes and methods of another class.
What is a parent class?
A parent class is the class whose members are inherited by another class.
What is a child class?
A child class is the class that inherits the members of a parent class.
Why is inheritance used?
Inheritance is used to reuse existing code, reduce duplication, and establish relationships between classes.
How do you create inheritance in Python?
By passing the parent class name inside parentheses.
PYTHON
class Child(Parent):
pass

Practice

  1. Create a parent class Animal with a method eat(). Create a child class Dog and call the inherited method.
  2. Create a parent class Vehicle with a method start(). Create a child class Car and call the method.
  3. Create a parent class Person with a method walk(). Create a child class Employee and call the inherited method.
  4. Create a parent class Shape with a method draw(). Create a child class Circle and call the inherited method.
  5. Identify the parent class and the child class in the following code:

    Output:

    TEXT
    class Animal:
        def eat(self):
            print("Eating")
    class Dog(Animal):
        pass
    
  6. Explain how inheritance helps reduce code duplication using your own example.

Parent Class and Child Class

For the definitions of a parent class and a child class, see Inheritance Basics above. This section focuses on how parent and child classes work together in practice.

How to Create a Parent and Child Class?

Create a normal class as the parent and pass its name inside parentheses while creating the child class.

Syntax:

PYTHON
class Parent:
    pass
class Child(Parent):
    pass

Example:

Output:

TEXT
class Vehicle:
    def start(self):
        print("Vehicle Started")
class Car(Vehicle):
    pass
car = Car()
car.start()

Parent Class Can Have Multiple Child Classes

One parent class can be inherited by multiple child classes.

Example:

PYTHON
class Animal:
    def eat(self):
        print("Animal is eating")
class Dog(Animal):
    pass
class Cat(Animal):
    pass
class Cow(Animal):
    pass
Dog().eat()
Cat().eat()
Cow().eat()

All three child classes inherit the same method from the parent class.

Child Class Can Have Its Own Methods

A child class can use the parent's methods and also define its own methods.

Example:

Output:

TEXT
class Animal:
    def eat(self):
        print("Animal is eating")
class Dog(Animal):
    def bark(self):
        print("Dog is barking")
dog = Dog()
dog.eat()
dog.bark()

Output:

PYTHON
Animal is eating
Dog is barking
  • eat() comes from the parent class.
  • bark() belongs to the child class.

Parent Class vs Child Class

Parent Class Child Class
Provides common attributes and methods Inherits attributes and methods from the parent
Also called Base Class or Superclass Also called Derived Class or Subclass
Cannot inherit automatically from the child Can use the parent's public members
Can have multiple child classes Can add its own methods and attributes

Real-World Examples

Parent Class Child Class
Animal Dog, Cat, Cow
Vehicle Car, Bike, Bus
Person Student, Employee
Shape Circle, Rectangle
Appliance WashingMachine, Refrigerator

Placement Quick Points

  • A parent class provides common attributes and methods.
  • A child class inherits from a parent class.
  • A child class automatically gets access to the parent's public methods and attributes.
  • One parent class can have multiple child classes.
  • A child class can define its own methods in addition to inherited methods.
  • Parent-child relationships help reduce code duplication.

Interview Questions

What is a parent class?
A parent class is a class whose attributes and methods are inherited by another class.
What is a child class?
A child class is a class that inherits the attributes and methods of a parent class.
Can a parent class have multiple child classes?
Yes. A single parent class can have multiple child classes.
Can a child class have its own methods?
Yes. A child class can define new methods in addition to the inherited methods.
What are the other names for a parent class and a child class?

The other names are:

Parent Class Child Class
Base Class Derived Class
Superclass Subclass
Does a child class automatically inherit the parent's public methods?
Yes. A child class automatically inherits and can use the public methods and attributes of its parent class.

Practice

  1. Create a parent class Vehicle with a method start(). Create a child class Car and call the inherited method.
  2. Create a parent class Animal with a method eat(). Create child classes Dog and Cat, and call the inherited method from both objects.
  3. Create a parent class Person and a child class Student. Add a new method study() to the child class.
  4. Create a parent class Shape with a method draw(). Create child classes Circle and Rectangle.
  5. Identify the parent class and the child class in the following code:

    Output:

    TEXT
    class Vehicle:
        def start(self):
            print("Vehicle Started")
    class Bike(Vehicle):
        pass
    
  6. Write one advantage of using parent and child classes instead of writing the same code in multiple classes.

Types of Inheritance

What are the Types of Inheritance?

Python supports different types of inheritance based on how classes are related to each other. These inheritance types help organize code and promote code reuse.

There are four commonly used types of inheritance in Python:

  • Single Inheritance
  • Multiple Inheritance
  • Multilevel Inheritance
  • Hierarchical Inheritance

Why Do We Have Different Types of Inheritance?

Different applications require different relationships between classes. Python provides multiple inheritance types to model these relationships effectively.

Example:

A school management system may have:

  • Student inherits from Person (Single Inheritance)
  • TeachingAssistant inherits from both Student and Employee (Multiple Inheritance)
  • Manager inherits from Employee, which inherits from Person (Multilevel Inheritance)

Different situations require different inheritance structures.

Single Inheritance

In Single Inheritance, one child class inherits from one parent class.

Diagram:

PYTHON
Animal
   │
   ▼
 Dog

Example:

Output:

TEXT
class Animal:
    def eat(self):
        print("Animal is eating")
class Dog(Animal):
    pass
dog = Dog()
dog.eat()

Output:

PYTHON
Animal is eating

Multiple Inheritance

In Multiple Inheritance, one child class inherits from more than one parent class.

Diagram:

PYTHON
Father      Mother
    \        /
     \      /
      ▼    ▼
       Child

Example:

Output:

TEXT
class Father:
    def drive(self):
        print("Can Drive")
class Mother:
    def cook(self):
        print("Can Cook")
class Child(Father, Mother):
    pass
child = Child()
child.drive()
child.cook()

Output:

PYTHON
Can Drive
Can Cook

Multilevel Inheritance

In Multilevel Inheritance, a child class inherits from another child class.

Diagram:

PYTHON
GrandParent
      │
      ▼
   Parent
      │
      ▼
    Child

Example:

PYTHON
class Person:
    def walk(self):
        print("Walking")
class Employee(Person):
    pass
class Manager(Employee):
    pass
manager = Manager()
manager.walk()

Output:

TEXT
Walking

Hierarchical Inheritance

In Hierarchical Inheritance, multiple child classes inherit from the same parent class.

Diagram:

PYTHON
        Animal
       /   |   \
      ▼    ▼    ▼
    Dog   Cat  Cow

Example:

PYTHON
class Animal:
    def eat(self):
        print("Eating")
class Dog(Animal):
    pass
class Cat(Animal):
    pass
class Cow(Animal):
    pass
Dog().eat()
Cat().eat()
Cow().eat()

Output:

TEXT
Eating
Eating
Eating

Comparison of Inheritance Types

Inheritance Type Description
Single One parent → One child
Multiple Multiple parents → One child
Multilevel Grandparent → Parent → Child
Hierarchical One parent → Multiple child classes

Placement Quick Points

  • Python commonly uses four types of inheritance.
  • Single Inheritance → One parent, one child.
  • Multiple Inheritance → Multiple parents, one child.
  • Multilevel Inheritance → Inheritance across multiple levels.
  • Hierarchical Inheritance → One parent, multiple child classes.
  • Inheritance helps improve code reusability and program organization.

Interview Questions

How many commonly used types of inheritance are there in Python?

There are four commonly used types of inheritance:

  • Single Inheritance
  • Multiple Inheritance
  • Multilevel Inheritance
  • Hierarchical Inheritance
What is Single Inheritance?
One child class inherits from one parent class.
What is Multiple Inheritance?
One child class inherits from more than one parent class.
What is Multilevel Inheritance?
A child class inherits from another child class, forming multiple inheritance levels.
What is Hierarchical Inheritance?
Multiple child classes inherit from the same parent class.

Practice

  1. Create a Single Inheritance example using Animal and Dog.
  2. Create a Multiple Inheritance example using Father, Mother, and Child.
  3. Create a Multilevel Inheritance example using Person, Employee, and Manager.
  4. Create a Hierarchical Inheritance example using Vehicle, Car, and Bike.
  5. Identify the type of inheritance used in the following code:
    PYTHON
    class Person:
        pass
    class Student(Person):
        pass
    class Employee(Person):
        pass
    

Explain your answer.

Accessing Parent Members

What is Accessing Parent Members?

Accessing Parent Members means using the attributes and methods of a parent class inside a child class. Since the child class inherits from the parent class, it can directly access the parent's public members without rewriting them.

Example:

Output:

TEXT
class Animal:
    def eat(self):
        print("Animal is eating")
class Dog(Animal):
    pass
dog = Dog()
dog.eat()

Output:

PYTHON
Animal is eating
  • Animal is the parent class.
  • Dog is the child class.
  • The eat() method belongs to the parent class.
  • The child object dog can directly call eat().

Why Do We Access Parent Members?

Accessing parent members allows us to reuse existing code instead of writing the same methods again in every child class. This is the same "without vs with inheritance" comparison shown in Inheritance Basics above: rather than each child class defining its own eat() method, the child classes share a single eat() method inherited from the parent.

Accessing Parent Methods

A child class can directly call any public method of its parent class.

Example:

Output:

TEXT
class Vehicle:
    def start(self):
        print("Vehicle Started")
class Car(Vehicle):
    pass
car = Car()
car.start()

Output:

PYTHON
Vehicle Started

Accessing Parent Attributes

A child class also inherits the parent's attributes.

Example:

PYTHON
class Person:
    def __init__(self):
        self.country = "India"
class Student(Person):
    pass
student = Student()
print(student.country)

Output:

TEXT
India

The country attribute is created in the parent class but accessed through the child object.

Accessing Parent Attributes and Methods Together

A child object can use both the parent's attributes and methods.

Example:

PYTHON
class Employee:
    def __init__(self):
        self.company = "ABC Technologies"
    def work(self):
        print("Employee is working")
class Manager(Employee):
    pass
manager = Manager()
print(manager.company)
manager.work()

Output:

PYTHON
ABC Technologies
Employee is working

Child Class Can Add Its Own Members

A child class can use the parent's members and also define its own methods.

Example:

PYTHON
class Animal:
    def eat(self):
        print("Animal is eating")
class Dog(Animal):
    def bark(self):
        print("Dog is barking")
dog = Dog()
dog.eat()
dog.bark()

Output:

PYTHON
Animal is eating
Dog is barking

Parent Members vs Child Members

Parent Members Child Members
Defined in the parent class Defined in the child class
Inherited by the child class Belong only to the child class
Can be accessed using the child object Can also be accessed using the child object

Example:

PYTHON
class Animal:
    def eat(self):
        print("Eating")
class Dog(Animal):
    def bark(self):
        print("Barking")
dog = Dog()
dog.eat()     # Parent method
dog.bark()    # Child method

Placement Quick Points

  • A child class automatically inherits the public attributes and public methods of its parent class.
  • Parent members can be accessed directly using the child object.
  • Inheritance eliminates code duplication.
  • A child class can use inherited members and define its own members.
  • Parent members are available to every object of the child class.

Interview Questions

What does accessing parent members mean?
It means using the attributes and methods of a parent class through a child class.
Can a child class access the parent's methods?
Yes. A child class automatically inherits and can access the parent's public methods.
Can a child class access the parent's attributes?
Yes. Public attributes of the parent class are inherited by the child class.
Why do we access parent members?
To reuse existing code and avoid writing the same code multiple times.
Can a child class have its own methods?
Yes. A child class can inherit parent members and also define its own methods.

Practice

  1. Create a parent class Vehicle with a method start(). Create a child class Car and call the inherited method.
  2. Create a parent class Person with an attribute country = "India". Create a child class Student and print the inherited attribute.
  3. Create a parent class Animal with a method eat(). Create a child class Dog with an additional method bark(). Call both methods.
  4. Create a parent class Employee with an attribute company and a method work(). Access both using a child class Manager.
  5. Identify the parent member and the child member in the following code:

    Output:

    TEXT
    class Animal:
        def eat(self):
            print("Eating")
    class Dog(Animal):
        def bark(self):
            print("Barking")
    

Explain why accessing parent members is useful in object-oriented programming.

Encapsulation

Encapsulation Basics

What is Encapsulation?

Encapsulation is an Object-Oriented Programming (OOP) concept that bundles data (attributes) and the methods that operate on that data into a single unit (class). It also helps protect an object's data from being accessed or modified directly.

Example:

PYTHON
class Student:
    def __init__(self, name):
        self.name = name
    def display(self):
        print(self.name)
student = Student("Arun")
student.display()

Output:

TEXT
Arun
  • name is the data (attribute).
  • display() is the method.
  • Both are grouped inside the Student class.
  • This is the basic idea of encapsulation.

Why Do We Use Encapsulation?

Encapsulation keeps related data and methods together and helps prevent accidental modification of an object's data.

Without Encapsulation:

PYTHON
name = "Arun"
print(name)
name = 123
print(name)

The variable can be modified from anywhere.

With Encapsulation:

PYTHON
class Student:
    def __init__(self, name):
        self.name = name
    def display(self):
        print(self.name)
student = Student("Arun")
student.display()

Now the data belongs to the object and is managed through the class.

How Does Encapsulation Work?

Encapsulation combines attributes and methods inside a class.

Example:

Output:

TEXT
class BankAccount:
    def __init__(self, balance):
        self.balance = balance
    def show_balance(self):
        print("Balance:", self.balance)
account = BankAccount(5000)
account.show_balance()

Output:

PYTHON
Balance: 5000

Both the data (balance) and the method (show_balance()) belong to the same object.

Types of Members

Python commonly uses four member categories based on how they are shared or accessed.

Example:

Output:

TEXT
class Student:
    school = "ABC School"      # Class Member
    def __init__(self):
        self.name = "Arun"     # Public Member
        self._age = 21         # Protected Member
        self.__marks = 95      # Private Member
student = Student()
print(student.school)
print(student.name)
print(student._age)
# print(student.__marks)   # Gives an AttributeError
Member Type Syntax Access
Class Member school Shared by all objects
Public Member name Accessible from anywhere
Protected Member _age Intended for internal use (convention)
Private Member __marks Name-mangled; should not be accessed directly outside the class

Getter and Setter methods — used to read and update private attributes — are covered in full under Getter and Setter Methods later in this module.

Placement Quick Points

  • Encapsulation combines data and methods into a single class.
  • It helps organize and protect object data.
  • Python has four commonly used member types:
    • Class Members
    • Public Members
    • Protected Members
    • Private Members
  • Getter methods are used to read private data.
  • Setter methods are used to update private data.

Interview Questions

What is encapsulation?
Encapsulation is the process of combining data and methods into a single class while helping protect the object's data.
Why is encapsulation used?
It improves code organization and helps prevent unauthorized or accidental modification of data.
Name the four types of members in Python.

The four member types are:

  • Class Members
  • Public Members
  • Protected Members
  • Private Members
What is the purpose of Getter and Setter methods?
Getter methods are used to read private attributes, while Setter methods are used to update private attributes.
Which member should not be accessed directly outside the class using its original name?
A Private Member (__member).

Practice

  1. Create a class Student with a class member school and a public member name.
  2. Add a protected member _age and a private member __marks to the class.
  3. Write a getter method to display the value of __marks.
  4. Write a setter method to update __marks.
  5. Create an object and use both the getter and setter methods.
  6. Identify the class, public, protected, and private members in the following code:
    PYTHON
    class Employee:
        company = "ABC Technologies"
        def __init__(self):
            self.name = "Arun"
            self._salary = 50000
            self.__bonus = 10000
    

Public, Protected and Private Members

What are Public, Protected and Private Members?

In Python, members (attributes and methods) can have different levels of accessibility. Based on how they are accessed, they are classified into:

  • Public Members
  • Protected Members
  • Private Members

These access levels help control how the data inside a class is used.

Why Do We Use Different Types of Members?

Different members provide different levels of access to an object's data.

  • Public Members can be accessed from anywhere.
  • Protected Members are intended to be used within the class and its child classes.
  • Private Members use name mangling to discourage direct access outside the class.

This helps make programs more organized and reduces accidental misuse of data.

Public Members

A public member is accessible from anywhere inside or outside the class. By default, all members in Python are public.

Example:

Output:

TEXT
class Student:
    def __init__(self):
        self.name = "Arun"
student = Student()
print(student.name)

Output:

PYTHON
Arun

Protected Members

A protected member starts with a single underscore (_).

It is intended to be used within the class and its child classes. Although it can still be accessed outside the class, it is considered an internal member by convention.

Example:

PYTHON
class Student:
    def __init__(self):
        self._age = 21
student = Student()
print(student._age)

Output:

PYTHON
21

Note: A protected member can still be accessed outside the class. The single underscore is a naming convention, not an access restriction.

Private Members

A private member starts with a double underscore (__).

It is name-mangled by Python, so it cannot be accessed directly using its original name outside the class. It is used to discourage direct access to important data.

Example:

Output:

TEXT
class Student:
    def __init__(self):
        self.__marks = 95
student = Student()
print(student.__marks)

Output:

TEXT
AttributeError: 'Student' object has no attribute '__marks'

The private member should normally be accessed inside the class or through methods like getters and setters.

Comparison of Member Types

Member Type Syntax Accessible Outside Class?
Public name Yes
Protected _name Yes (by convention, avoid direct access)
Private __name Not directly by its original name

Common Example

PYTHON
class Student:
    def __init__(self):
        self.name = "Arun"        # Public
        self._age = 21            # Protected
        self.__marks = 95         # Private
student = Student()
print(student.name)
print(student._age)
# print(student.__marks)   # AttributeError

Placement Quick Points

  • Python supports Public, Protected, and Private members.
  • Public members are accessible from anywhere.
  • Protected members use a single underscore (_).
  • Private members use a double underscore (__).
  • Private members cannot be accessed directly outside the class using their original name.
  • Protected members are accessible outside the class but should be treated as internal by convention.

Interview Questions

What are the three types of members in Python?

The three types are:

  • Public Members
  • Protected Members
  • Private Members
Which member is accessible from anywhere?
Public Members.
Which symbol is used for a protected member?
A single underscore (_).
Which symbol is used for a private member?
A double underscore (__).
Can a private member be accessed directly outside the class using its original name?
No. Python changes its name internally, so it should normally be accessed through a method.
What is the difference between protected and private members?

The difference is:

Protected Private
Uses _ Uses __
Accessible outside the class (by convention) Cannot be accessed directly outside the class
Intended for internal use Used to hide important data

Practice

  1. Create a class Student with a public member name.
  2. Add a protected member _age to the class.
  3. Add a private member __marks to the class.
  4. Create an object and access the public and protected members.
  5. Try to access the private member directly and observe the output.
  6. Identify the public, protected, and private members in the following code:
    TEXT
    class Employee:
        def __init__(self):
            self.name = "Arun"
            self._salary = 50000
            self.__bonus = 10000
    

Private Methods

What are Private Methods?

A private method is a method whose name begins with double underscores (__). It is intended to be used only within the class and should not be called directly from outside the class using its original name.

Private methods are used to hide the internal implementation of a class.

Example:

PYTHON
class Student:
    def __welcome(self):
        print("Welcome to Python!")
    def greet(self):
        self.__welcome()
student = Student()
student.greet()

Output:

PYTHON
Welcome to Python!
  • __welcome() is a private method.
  • greet() is a public method.
  • The private method is called from inside the class using self.

Why Do We Use Private Methods?

Private methods help hide the internal logic of a class and prevent them from being called accidentally from outside the class.

Without a Private Method:

PYTHON
class Student:
    def welcome(self):
        print("Welcome!")
student = Student()
student.welcome()

Here, anyone can call the welcome() method directly.

With a Private Method:

Output:

TEXT
class Student:
    def __welcome(self):
        print("Welcome!")
    def greet(self):
        self.__welcome()
student = Student()
student.greet()

Now, __welcome() is meant to be used inside the class.

How to Create a Private Method?

A private method is created by adding two underscores (__) before the method name.

Syntax:

PYTHON
class ClassName:
    def __method_name(self):
        pass

Example:

Output:

TEXT
class BankAccount:
    def __calculate_interest(self):
        print("Interest Calculated")
    def show_interest(self):
        self.__calculate_interest()
account = BankAccount()
account.show_interest()

Accessing a Private Method

A private method should be accessed through a public method inside the class.

Example:

PYTHON
class Student:
    def __display(self):
        print("Private Method")
    def show(self):
        self.__display()
student = Student()
student.show()

Output:

TEXT
Private Method

Calling a Private Method Directly

Trying to call a private method directly from outside the class using its original name results in an error.

Example:

PYTHON
class Student:
    def __display(self):
        print("Private Method")
student = Student()
student.__display()

Output:

TEXT
AttributeError: 'Student' object has no attribute '__display'

Public Method vs Private Method

Public Method Private Method
display() __display()
Can be called from anywhere Should normally be called from inside the class
No underscore prefix Double underscore (__) prefix

Example:

PYTHON
class Student:
    def display(self):
        print("Public Method")
    def __private(self):
        print("Private Method")
    def show(self):
        self.display()
        self.__private()
student = Student()
student.show()

Placement Quick Points

  • A private method starts with double underscores (__).
  • Private methods are intended for internal use within the class.
  • They cannot be called directly from outside the class using their original names.
  • Private methods are usually accessed through public methods.
  • Private methods help hide the internal implementation of a class.

Interview Questions

What is a private method?
A private method is a method whose name begins with double underscores (__) and is intended to be used only within the class.
How do you create a private method in Python?
By adding double underscores (__) before the method name.
Can a private method be called directly outside the class?
No. Attempting to do so results in an AttributeError.
How can a private method be accessed?
It can be accessed through another public method inside the same class.
Why are private methods used?
Private methods hide the internal implementation of a class and prevent accidental access from outside the class.

Practice

  1. Create a class Student with a private method __welcome().
  2. Create a public method greet() that calls __welcome().
  3. Create an object and call the public method.
  4. Try calling the private method directly and observe the output.
  5. Identify the public and private methods in the following code:
    TEXT
    class Employee:
        def work(self):
            print("Working")
        def __calculate_salary(self):
            print("Salary Calculated")
        def show_salary(self):
            self.__calculate_salary()
    

Getter and Setter Methods

What are Getter and Setter Methods?

Getter and Setter methods are special methods used to access and modify private attributes of a class.

A Getter method is used to read the value of a private attribute.

A Setter method is used to update the value of a private attribute.

These methods provide controlled access to private data.

Example:

PYTHON
class Student:
    def __init__(self):
        self.__marks = 90
    def get_marks(self):
        return self.__marks
    def set_marks(self, marks):
        self.__marks = marks
student = Student()
print(student.get_marks())
student.set_marks(95)
print(student.get_marks())

Output:

TEXT
90
95
  • __marks is a private attribute.
  • get_marks() reads the value of __marks.
  • set_marks() updates the value of __marks.

Why Do We Use Getter and Setter Methods?

Since private attributes cannot be accessed directly, Getter and Setter methods provide a safe way to read and modify them.

Without Getter and Setter:

PYTHON
class Student:
    def __init__(self):
        self.__marks = 90
student = Student()
print(student.__marks)

Output:

TEXT
AttributeError: 'Student' object has no attribute '__marks'

With Getter and Setter:

PYTHON
class Student:
    def __init__(self):
        self.__marks = 90
    def get_marks(self):
        return self.__marks
    def set_marks(self, marks):
        self.__marks = marks
student = Student()
print(student.get_marks())
student.set_marks(100)
print(student.get_marks())

Output:

TEXT
90
100

How to Create Getter and Setter Methods?

Create two methods:

  • A Getter method to return the private attribute.
  • A Setter method to update the private attribute.

Syntax:

PYTHON
class ClassName:
    def get_attribute(self):
        return self.__attribute
    def set_attribute(self, value):
        self.__attribute = value

Example:

PYTHON
class Employee:
    def __init__(self):
        self.__salary = 50000
    def get_salary(self):
        return self.__salary
    def set_salary(self, salary):
        self.__salary = salary
employee = Employee()
print(employee.get_salary())
employee.set_salary(60000)
print(employee.get_salary())

Getter vs Setter

Getter Method Setter Method
Reads a private attribute Updates a private attribute
Uses return Assigns a new value
Does not modify data Modifies data

Example:

PYTHON
class Student:
    def __init__(self):
        self.__marks = 90
    def get_marks(self):
        return self.__marks
    def set_marks(self, marks):
        self.__marks = marks

s = Student()
print("Initial Marks:", s.get_marks())
s.set_marks(95)
print("Updated Marks:", s.get_marks())

Output:

TEXT
Initial Marks: 90
Updated Marks: 95

Placement Quick Points

  • Getter and Setter methods are used with private attributes.
  • A Getter method reads the value of a private attribute.
  • A Setter method updates the value of a private attribute.
  • They provide controlled access to private data.
  • Getter methods usually use the return statement.
  • Setter methods assign a new value to the private attribute.

Interview Questions

What is a Getter method?
A Getter method is used to read the value of a private attribute.
What is a Setter method?
A Setter method is used to update the value of a private attribute.
Why are Getter and Setter methods used?
They provide controlled access to private attributes without exposing them directly.
Which type of attribute is commonly used with Getter and Setter methods?
Private attributes (__attribute).
What is the difference between a Getter and a Setter?

The difference is:

Getter Setter
Reads data Updates data
Returns a value Assigns a value

Practice

  1. Create a class Student with a private attribute __marks.
  2. Write a Getter method to return the value of __marks.
  3. Write a Setter method to update the value of __marks.
  4. Create an object and use both the Getter and Setter methods.
  5. Identify the Getter and Setter methods in the following code:
    PYTHON
    class Employee:
        def __init__(self):
            self.__salary = 50000
        def get_salary(self):
            return self.__salary
        def set_salary(self, salary):
            self.__salary = salary
    

Polymorphism

Polymorphism Basics

What is Polymorphism?

Polymorphism is an Object-Oriented Programming (OOP) concept that allows the same method or operation to perform different actions depending on the object it is used with.

The word Polymorphism comes from two Greek words:

Output:

TEXT
Poly = Many
Morph = Forms

So, Polymorphism means "Many Forms."

Example:

PYTHON
class Dog:
    def sound(self):
        print("Dog barks")

class Cat:
    def sound(self):
        print("Cat meows")

dog = Dog()
cat = Cat()
dog.sound()
cat.sound()

Output:

TEXT
Dog barks
Cat meows
  • Both classes have a method named sound().
  • The same method name performs different actions.
  • This is called Polymorphism.

Why Do We Use Polymorphism?

Polymorphism allows us to use the same interface (method name) for different objects without changing the calling code.

Without Polymorphism:

PYTHON
class Dog:
    def dog_sound(self):
        print("Dog barks")

class Cat:
    def cat_sound(self):
        print("Cat meows")

dog = Dog()
cat = Cat()
dog.dog_sound()
cat.cat_sound()

Different method names must be remembered.

With Polymorphism:

PYTHON
class Dog:
    def sound(self):
        print("Dog barks")

class Cat:
    def sound(self):
        print("Cat meows")

dog = Dog()
cat = Cat()
dog.sound()
cat.sound()

Now every object uses the same method name sound().

How Does Polymorphism Work?

Different classes define the same method name, but each class provides its own implementation.

Example:

PYTHON
class Bird:
    def move(self):
        print("Bird flies")

class Fish:
    def move(self):
        print("Fish swims")

bird = Bird()
fish = Fish()
bird.move()
fish.move()

Output:

PYTHON
Bird flies
Fish swims

Real-World Examples of Polymorphism

Object Same Method Different Behavior
Dog sound() Barks
Cat sound() Meows
Cow sound() Moos
Bird move() Flies
Fish move() Swims

Built-in Example of Polymorphism

Python's built-in functions also demonstrate polymorphism.

Example:

PYTHON
print(len("Python"))
print(len([10, 20, 30]))

Output:

TEXT
6
3
  • The same len() function works with different data types.
  • String → Number of characters
  • List → Number of elements

Placement Quick Points

  • Polymorphism means "Many Forms."
  • The same method name can perform different actions.
  • Different classes can define the same method differently.
  • Polymorphism improves code flexibility and readability.
  • Python supports polymorphism through methods, operators, and built-in functions like len().

Interview Questions

What is polymorphism?
Polymorphism is an OOP concept where the same method or operation performs different actions depending on the object.
What does the word "Polymorphism" mean?
It means "Many Forms."
Why is polymorphism used?
It allows different objects to use the same method name while providing different implementations.
Give a real-world example of polymorphism.

Different animals respond differently to the same action sound():

  • Dog → Barks
  • Cat → Meows
  • Cow → Moos
Give an example of built-in polymorphism in Python.
The len() function works with different data types.
PYTHON
len("Python")
len([1, 2, 3])

Practice

  1. Create classes Dog and Cat, each with a sound() method.
  2. Create classes Bird and Fish, each with a move() method.
  3. Write a program where Car and Bike both have a start() method.
  4. Use the len() function with a string and a list.
  5. Identify the polymorphic behavior in the following code:

    Output:

    TEXT
    class Circle:
        def draw(self):
            print("Drawing Circle")
    
    class Rectangle:
        def draw(self):
            print("Drawing Rectangle")
    
    circle = Circle()
    rectangle = Rectangle()
    circle.draw()
    rectangle.draw()
    

Explain why this is an example of polymorphism.

Method Overloading and Method Overriding

What are Method Overloading and Method Overriding?

Method Overloading and Method Overriding are two important concepts of Polymorphism.

Method Overloading means creating multiple methods with the same name but different parameters in languages that support traditional overloading.

Method Overriding means a child class provides its own implementation of a method that already exists in the parent class.

Why Do We Use Method Overloading and Method Overriding?

These concepts allow us to write flexible and reusable code.

  • Method Overloading allows the same method to work with different inputs.
  • Method Overriding allows a child class to customize the behavior of a parent class.

Method Overloading

Method Overloading means creating multiple methods with the same name but different parameters.

Note: Python does not support traditional method overloading like Java or C++. If multiple methods have the same name, the last one overrides the previous ones.

Example:

PYTHON
class Calculator:
    def add(self, a, b):
        return a + b
    def add(self, a, b, c):
        return a + b + c

calc = Calculator()
print(calc.add(10, 20, 30))

Output:

PYTHON
60

Only the last add() method is available.

Achieving Similar Behavior in Python:

Python commonly uses default arguments to achieve similar behavior.

PYTHON
class Calculator:
    def add(self, a, b, c=0):
        return a + b + c

calc = Calculator()
print(calc.add(10, 20))
print(calc.add(10, 20, 30))

Output:

PYTHON
30
60

Method Overriding

Method Overriding occurs when a child class defines a method with the same name as the parent class. The child class method replaces the parent's implementation.

Example:

PYTHON
class Animal:
    def sound(self):
        print("Animal makes a sound")

class Dog(Animal):
    def sound(self):
        print("Dog barks")

dog = Dog()
dog.sound()

Output:

PYTHON
Dog barks
  • Animal has a sound() method.
  • Dog defines its own sound() method.
  • The child class method overrides the parent class method.

Calling Parent Methods with super()

The super() function lets a child class call a method from its parent class. It is most useful for reusing the parent's __init__() and for extending an overridden method instead of fully replacing it.

Calling the parent constructor from the child constructor:

Output:

TEXT
class Animal:
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)
        self.breed = breed

dog = Dog("Tommy", "Labrador")
print(dog.name)
print(dog.breed)

Output:

PYTHON
Tommy
Labrador
  • super().__init__(name) runs the parent's __init__() and sets self.name.
  • The child then adds its own attribute self.breed.

Extending an overridden method with super():

Output:

TEXT
class Animal:
    def sound(self):
        print("Animal makes a sound")

class Dog(Animal):
    def sound(self):
        super().sound()
        print("Dog barks")

dog = Dog()
dog.sound()

Output:

TEXT
Animal makes a sound
Dog barks
  • super().sound() runs the parent's version first.
  • The child then adds its own behavior, so both messages appear.

Method Overloading vs Method Overriding

Method Overloading Method Overriding
Same method name with different parameters Same method name in parent and child classes
Used to handle different inputs Used to change inherited behavior
Traditional overloading is not supported in Python Fully supported in Python
Similar behavior is achieved using default arguments Achieved using inheritance

Placement Quick Points

  • Method Overloading and Method Overriding are concepts of Polymorphism.
  • Python does not support traditional method overloading.
  • Default arguments are commonly used to handle different numbers of inputs.
  • Method Overriding requires inheritance.
  • In overriding, the child class provides its own implementation of the parent method.

Interview Questions

What is Method Overloading?
Method Overloading means creating methods with the same name but different parameters. Python does not support traditional method overloading.
Does Python support Method Overloading?
No. Python does not support traditional method overloading. Similar behavior can be achieved using default arguments.
What is Method Overriding?
Method Overriding is when a child class provides its own implementation of a method that already exists in the parent class.
Does Method Overriding require inheritance?
Yes. Method Overriding is possible only through inheritance.
What is the difference between Method Overloading and Method Overriding?
Method overloading means using the same method name for different inputs. Method overriding means a child class redefines a method inherited from a parent class.

Practice

  1. Create a Calculator class that uses default arguments to add two or three numbers.
  2. Create a parent class Animal with a sound() method and override it in a child class Dog.
  3. Create a parent class Vehicle with a start() method and override it in a child class Car.
  4. Explain why Python uses default arguments instead of traditional method overloading.
  5. Identify whether the following code demonstrates Method Overloading or Method Overriding:
    TEXT
    class Animal:
        def sound(self):
            print("Animal Sound")
    
    class Cat(Animal):
        def sound(self):
            print("Meow")
    
    cat = Cat()
    cat.sound()
    

Explain your answer.

Duck Typing

What is Duck Typing?

Duck Typing is a feature of Python where the type of an object is less important than the methods or behaviors it provides.

In simple words, if an object behaves like the expected object, Python allows it to be used, regardless of its actual class.

This idea comes from the famous saying:

"If it looks like a duck, swims like a duck, and quacks like a duck, then it is a duck."

Example:

TEXT
class Dog:
    def sound(self):
        print("Dog barks")

class Cat:
    def sound(self):
        print("Cat meows")

def make_sound(animal):
    animal.sound()

dog = Dog()
cat = Cat()
make_sound(dog)
make_sound(cat)

Output:

TEXT
Dog barks
Cat meows
  • Dog and Cat are different classes.
  • Both have a sound() method.
  • The function make_sound() doesn't check the object's class.
  • It simply calls sound().
  • This is called Duck Typing.

Why Do We Use Duck Typing?

Duck Typing makes code more flexible because a function can work with different types of objects as long as they provide the required method.

Without Duck Typing:

TEXT
class Dog:
    def sound(self):
        print("Dog barks")

dog = Dog()
dog.sound()

This code works only with Dog objects.

With Duck Typing:

TEXT
class Dog:
    def sound(self):
        print("Dog barks")

class Cat:
    def sound(self):
        print("Cat meows")

def make_sound(animal):
    animal.sound()

make_sound(Dog())
make_sound(Cat())

Now the same function works with multiple objects.

How Does Duck Typing Work?

Duck Typing works by checking whether an object has the required method when the program runs.

Example:

TEXT
class Bird:
    def move(self):
        print("Bird flies")

class Fish:
    def move(self):
        print("Fish swims")

def travel(obj):
    obj.move()

travel(Bird())
travel(Fish())

Output:

TEXT
Bird flies
Fish swims

The travel() function works because both objects provide a move() method.

Real-World Example

Suppose a remote control can operate different devices.

TEXT
class TV:
    def turn_on(self):
        print("TV Turned On")

class AC:
    def turn_on(self):
        print("AC Turned On")

def power_on(device):
    device.turn_on()

power_on(TV())
power_on(AC())

Output:

TEXT
TV Turned On
AC Turned On

The power_on() function doesn't care whether the object is a TV or an AC. It only expects the object to have a turn_on() method.

Duck Typing vs Inheritance

Duck Typing Inheritance
Focuses on an object's behavior Focuses on parent-child relationships
No inheritance is required Requires inheritance
Works if the required method exists Child class inherits methods from the parent
More flexible More structured

Placement Quick Points

  • Duck Typing is based on an object's behavior, not its type.
  • Python checks whether an object has the required method at runtime.
  • Objects from different classes can be used interchangeably if they provide the same behavior.
  • Duck Typing makes code more flexible and reusable.
  • In Duck Typing, what an object can do is more important than what it is.

Interview Questions

What is Duck Typing?
Duck Typing is a feature where Python uses an object based on its behavior (methods) instead of its class type.
Why is it called Duck Typing?
It comes from the saying: "If it looks like a duck, swims like a duck, and quacks like a duck, then it is a duck."
Does Duck Typing require inheritance?
No. Duck Typing does not require inheritance.
What does Duck Typing focus on?
Duck Typing focuses on whether an object provides the required methods.
What is the main advantage of Duck Typing?
It makes programs more flexible because the same function can work with different types of objects.

Practice

  1. Create classes Dog and Cat with a sound() method and write a function make_sound() that works with both.
  2. Create classes Car and Bike with a start() method and write a function start_vehicle() that calls start().
  3. Create classes TV and AC with a turn_on() method and write a common function to turn on both devices.
  4. Explain why the following code demonstrates Duck Typing:

    TEXT
    class Bird:
        def move(self):
            print("Bird flies")
    
    class Fish:
        def move(self):
            print("Fish swims")
    
    def travel(obj):
        obj.move()
    
  5. What will happen if an object passed to travel() does not have a move() method? Explain why.

Abstraction

What Is Abstraction?

Abstraction is an Object-Oriented Programming (OOP) concept that hides the implementation details and shows only the essential features of an object.

In simple words, the user knows what an object does, but not how it does it.

Example:

TEXT
from abc import ABC, abstractmethod
class Animal(ABC):
    @abstractmethod
    def sound(self):
        pass
class Dog(Animal):
    def sound(self):
        print("Dog barks")
dog = Dog()
dog.sound()

Output:

TEXT
Dog barks
  • Animal is an abstract class.
  • sound() is an abstract method.
  • Dog provides the implementation of sound().
  • The user only calls dog.sound() without worrying about how it is implemented.

Why Do We Use Abstraction?

Abstraction hides unnecessary implementation details and exposes only the required functionality.

Without Abstraction:

TEXT
class Dog:
    def sound(self):
        print("Dog barks")
dog = Dog()
dog.sound()

Everything is implemented directly in one class.

With Abstraction:

TEXT
from abc import ABC, abstractmethod
class Animal(ABC):
    @abstractmethod
    def sound(self):
        pass
class Dog(Animal):
    def sound(self):
        print("Dog barks")
dog = Dog()
dog.sound()

The parent class defines what should be done, while the child class defines how it is done.

Understanding abc, ABC, and @abstractmethod

Before creating an abstract class, let's understand the keywords used.

Keyword Purpose
abc A built-in Python module used for creating abstract classes
ABC A class from the abc module used as the base class for abstract classes
@abstractmethod A decorator that marks a method as abstract

Import Statement:

TEXT
from abc import ABC, abstractmethod
  • abc is Python's Abstract Base Class module.
  • ABC is used to create an abstract class.
  • @abstractmethod tells Python that a method must be implemented in every child class.
  • Without importing these, Python cannot create abstract classes.

Abstract Class

An abstract class is a class meant to act as a blueprint for other classes. In Python, a class with at least one @abstractmethod cannot be instantiated until all abstract methods are implemented by a child class.

To create an abstract class, inherit from ABC.

Example:

TEXT
from abc import ABC
class Animal(ABC):
    pass
  • Animal is based on ABC, so it is meant to be used as a blueprint.
  • Because it has no abstract method here, Python can still create an object from it.

Abstract Method

An abstract method is a method declared using the @abstractmethod decorator.

It usually does not contain the final implementation in the abstract class and must be implemented by every concrete child class.

Example:

TEXT
from abc import ABC, abstractmethod
class Animal(ABC):
    @abstractmethod
    def sound(self):
        pass
class Dog(Animal):
    def sound(self):
        print("Dog barks")
dog = Dog()
dog.sound()

Output:

TEXT
Dog barks
  • @abstractmethod tells Python that sound() is incomplete.
  • Every child class must define its own version of sound().
  • Otherwise, Python will not allow an object of that child class to be created.

Placement Quick Points

  • Abstraction hides implementation details and shows only essential features.
  • Python provides the abc module to support abstraction.
  • ABC is used to create an abstract class.
  • @abstractmethod is used to create an abstract method.
  • A class with unimplemented abstract methods cannot be instantiated.
  • Every child class must implement all abstract methods.

Interview Questions

What is abstraction?
Abstraction is the process of hiding implementation details and exposing only the essential features of an object.
Which module is used for abstraction in Python?
The abc module.
What is ABC?
ABC (Abstract Base Class) is the base class used to create abstract classes.
What is @abstractmethod?
@abstractmethod is a decorator that marks a method as abstract and requires child classes to implement it.
Can we create an object of an abstract class?
Not if it still has unimplemented abstract methods.
Why do we use abstract classes?
To define a common blueprint that child classes must follow.

Practice

  1. Import ABC and abstractmethod from the abc module.
  2. Create an abstract class Animal.
  3. Add an abstract method sound() to the class.
  4. Create a child class Dog and implement the sound() method.
  5. Create another child class Cat and implement the sound() method.
  6. Identify the abstract class and the abstract method in the following code:
    TEXT
    from abc import ABC, abstractmethod
    class Vehicle(ABC):
        @abstractmethod
        def start(self):
            pass
    class Car(Vehicle):
        def start(self):
            print("Car Started")
    

Inner Classes

What Are Inner Classes?

An Inner Class is a class that is defined inside another class. The outer class is called the Outer Class, and the class defined inside it is called the Inner Class.

Inner classes are used when one class is closely related to another class and is not intended to be used independently.

Example:

TEXT
class College:
    class Student:
        def display(self):
            print("Student Details")
student = College.Student()
student.display()

Output:

TEXT
Student Details
  • College is the Outer Class.
  • Student is the Inner Class.
  • The inner class is accessed using OuterClass.InnerClass().

Why Do We Use Inner Classes?

Inner classes help organize related classes together and improve code readability.

Without Inner Class:

TEXT
class Student:
    def display(self):
        print("Student Details")
student = Student()
student.display()

Student exists as a separate class.

With Inner Class:

TEXT
class College:
    class Student:
        def display(self):
            print("Student Details")
student = College.Student()
student.display()

Now, Student clearly belongs to College.

How to Create an Inner Class?

Define one class inside another class.

Syntax:

TEXT
class OuterClass:
    class InnerClass:
        pass

Example:

TEXT
class Company:
    class Employee:
        def work(self):
            print("Employee is working")
employee = Company.Employee()
employee.work()

Creating an Object of an Inner Class

To create an object of an inner class, use the outer class name followed by the inner class name.

Syntax:

TEXT
class OuterClass:
object_name = OuterClass.InnerClass()

Example:

TEXT
class School:
    class Student:
        def study(self):
            print("Studying")
student = School.Student()
student.study()

Output:

TEXT
Studying

Real-World Example

Suppose a Car has an Engine. The engine is closely related to the car and usually doesn't exist independently.

TEXT
class Car:
    class Engine:
        def start(self):
            print("Engine Started")
engine = Car.Engine()
engine.start()

Output:

TEXT
Engine Started

Inner Class vs Normal Class

Inner Class Normal Class
Defined inside another class Defined independently
Used for closely related classes Used independently
Accessed using OuterClass.InnerClass() Accessed directly using the class name
Improves code organization General-purpose class

Placement Quick Points

  • An Inner Class is a class defined inside another class.
  • The enclosing class is called the Outer Class.
  • Inner classes help group closely related classes together.
  • An inner class object is created using OuterClass.InnerClass().
  • Inner classes improve code organization and readability.

Interview Questions

What is an Inner Class?
An Inner Class is a class defined inside another class.
Why are Inner Classes used?
They are used to group closely related classes and improve code organization.
How do you create an object of an Inner Class?
Using the syntax OuterClass.InnerClass().
Can an Inner Class exist without an Outer Class?
No. It is defined inside an outer class and is typically accessed through it.
Give a real-world example of an Inner Class.
A Car containing an Engine, or a College containing a Student.

Practice

  1. Create an outer class College and an inner class Student.
  2. Create an object of the inner class and call its method.
  3. Create an outer class Company and an inner class Employee with a work() method.
  4. Create an outer class Car and an inner class Engine with a start() method.
  5. Identify the Outer Class and the Inner Class in the following code:

    TEXT
    class Library:
        class Book:
            def read(self):
                print("Reading Book")
    
  6. Write the statement to create an object of the Book inner class and call the read() method.


End of Level 9