Part 3
Object-Oriented Programming
Classes, Inheritance, Polymorphism & Magic Methods
1. Classes & Objects
A class is a blueprint for creating objects. An object is an instance of a class.
class Student:
def __init__(self, name, roll):
[Link] = name
[Link] = roll
def introduce(self):
return f"I am {[Link]}, roll {[Link]}"
s1 = Student("Nadia", 12)
print([Link]())
2. Instance vs Class Attributes
class Counter:
total = 0 # class attribute
def __init__(self):
[Link] += 1 # shared across all instances
Counter(); Counter(); Counter()
print([Link]) # 3
3. Inheritance
A child class can inherit attributes and methods from a parent class.
class Animal:
def __init__(self, name):
[Link] = name
def speak(self):
return "..."
class Dog(Animal):
def speak(self):
return f"{[Link]} says Woof!"
d = Dog("Rex")
print([Link]()) # Rex says Woof!
4. Encapsulation
Prefixing an attribute with an underscore signals it's intended as internal/private.
class BankAccount:
def __init__(self, balance=0):
self._balance = balance
def deposit(self, amount):
self._balance += amount
def get_balance(self):
return self._balance
acc = BankAccount(100)
[Link](50)
print(acc.get_balance()) # 150
5. Polymorphism
Different classes can implement the same method name in their own way.
class Cat(Animal):
def speak(self):
return f"{[Link]} says Meow!"
for a in [Dog("Rex"), Cat("Tom")]:
print([Link]())
6. Magic Methods
Dunder (double underscore) methods let objects work with built-in operators and functions like
print(), len(), and comparisons.
class Vector:
def __init__(self, x, y):
self.x, self.y = x, y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __repr__(self):
return f"Vector({self.x}, {self.y})"
def __eq__(self, other):
return self.x == other.x and self.y == other.y
v = Vector(1,2) + Vector(3,4)
print(v) # Vector(4, 6)
print(Vector(1,1) == Vector(1,1)) # True
Other common dunder methods:
• __len__ — makes len(obj) work
• __str__ — controls print(obj) output
• __getitem__ — enables obj[index] access
• __lt__ / __gt__ — enables sorting/comparison
7. Class Methods & Static Methods
Regular methods take self. Class methods take the class itself, and static methods take neither.
class Pizza:
def __init__(self, toppings):
[Link] = toppings
@classmethod
def margherita(cls):
return cls(["mozzarella", "tomato"])
@staticmethod
def is_valid_topping(name):
return name in ["cheese", "mushroom", "olive"]
p = [Link]()
print([Link])
print(Pizza.is_valid_topping("cheese"))
8. Abstract Base Classes
Abstract classes define a common interface that subclasses must implement. They prevent direct
instantiation of the base class.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
[Link] = radius
def area(self):
return 3.14159 * [Link] ** 2
c = Circle(4)
print([Link]()) # 50.265...
9. Property Decorators
The @property decorator lets you define methods that behave like attributes, useful for computed
or validated values.
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def area(self):
return 3.14159 * self._radius ** 2
@property
def radius(self):
return self._radius
@[Link]
def radius(self, value):
if value < 0:
raise ValueError("Radius cannot be negative")
self._radius = value
c = Circle(5)
print([Link]) # accessed like an attribute, not a method call
[Link] = 10
print([Link])
10. Multiple Inheritance
A class can inherit from more than one parent class. Python resolves method lookup order using
the MRO (Method Resolution Order).
class Flyer:
def move(self):
return "Flying"
class Swimmer:
def move(self):
return "Swimming"
class Duck(Flyer, Swimmer):
pass
d = Duck()
print([Link]()) # Flying (Flyer comes first in MRO)
print(Duck.__mro__) # shows the resolution order
Practice Exercises
• Create a Shape base class with area() and subclasses Circle, Rectangle overriding it.
• Add a __str__ method to a Book class that returns a formatted description.
• Implement a Stack class using a list with push, pop, and peek methods.
• Create an abstract Vehicle class with subclasses Car and Bike implementing fuel_type().
• Add property validation to a Temperature class so it can't be set below absolute zero.
• Build a simple class hierarchy for Employee -> Manager -> Director with increasing
responsibilities.