Python OOP — Complete
Presentation Guide
1. Class
A class is a blueprint/template for creating objects. It defines
attributes (data) and methods (behavior) that its objects will
have.
class Student:
pass
class keyword defines a class.
By convention, class names use PascalCase (e.g., Student ,
BankAccount ).
A class itself doesn't hold real data — it's just a design.
2. Instance (Object)
An instance is a real object created from a class. Creating an
instance is called instantiation.
class Student:
def __init__(self, name, age):
[Link] = name
[Link] = age
s1 = Student("Alia", 20)
s2 = Student("Ravi", 22)
print([Link]) # Alia
print([Link]) # Ravi
s1 and s2 are instances of Student .
__init__ is the constructor — runs automatically when an
object is created.
self refers to the current instance being created/used.
3. Methods (Instance Methods)
A method is a function defined inside a class that operates on
an instance.
class Student:
def __init__(self, name, marks):
[Link] = name
[Link] = marks
def display(self): # instance method
print(f"{[Link]} scored {[Link]}")
s1 = Student("Alia", 90)
[Link]() # Alia scored 90
Every instance method's first parameter is self
(automatically passed).
Instance methods can read/modify instance data ( self.x )
and access class data too.
4. Class vs Instance — Key Differences
Aspect Class Instance
Actual object built from
Definition Blueprint/template
the blueprint
One copy exists (the Each instance has its
Memory
definition) own memory
Class variables Instance variables
Data
(shared) (unique per object)
Defined once using Created every time you
Creation
class call ClassName()
s1 =
Example Student
Student("Alia", 20)
print(type(s1)) # <class
'__main__.Student'>
print(isinstance(s1, Student)) # True
Think of the class as a cookie cutter and instances as the actual
cookies — same shape, different cookie each time.
5. Class Variables vs Instance Variables
Instance variables: unique to each object, usually defined
inside __init__ using [Link] .
Class variables: shared by all instances, defined directly
inside the class body.
class Student:
school_name = "Green Valley School" # class
variable (shared)
def __init__(self, name, marks):
[Link] = name # instance variable
[Link] = marks # instance variable
s1 = Student("Alia", 90)
s2 = Student("Ravi", 85)
print(s1.school_name) # Green Valley School
print(s2.school_name) # Green Valley School
Student.school_name = "Blue Ridge School" # change
via class
print(s1.school_name) # Blue Ridge School (both
affected)
print(s2.school_name) # Blue Ridge School
⚠️ Common trap: if you do s1.school_name = "X" , it creates a
new instance variable for s1 only — it does NOT change the
class variable.
s1.school_name = "Only for Alia"
print(s1.school_name) # Only for Alia (instance
var created)
print(s2.school_name) # Blue Ridge School
(unaffected)
Use case for class variables: counters, constants, shared config.
class Student:
count = 0 # tracks number of students created
def __init__(self, name):
[Link] = name
[Link] += 1
Student("A")
Student("B")
print([Link]) # 2
6. Instance Methods vs Class Methods vs
Static Methods
a) Instance Method (normal, uses self )
Operates on individual object data.
class Student:
def __init__(self, name):
[Link] = name
def greet(self):
return f"Hi, I'm {[Link]}"
b) Class Method ( @classmethod , uses cls )
Operates on the class itself, not a specific instance. Often used
as alternate constructors.
class Student:
school_name = "Green Valley"
def __init__(self, name, age):
[Link] = name
[Link] = age
@classmethod
def from_string(cls, data_string):
name, age = data_string.split("-")
return cls(name, int(age)) # creates and
returns a new instance
@classmethod
def change_school(cls, new_name):
cls.school_name = new_name
s3 = Student.from_string("Kabir-21")
print([Link], [Link]) # Kabir 21
Student.change_school("New Age School")
print(Student.school_name) # New Age School
c) Static Method ( @staticmethod , no self / cls )
A utility function placed inside a class because it's logically
related, but doesn't need access to instance or class data.
class MathUtils:
@staticmethod
def is_even(n):
return n % 2 == 0
print(MathUtils.is_even(10)) # True
Comparison Table
First
Type Decorator Access Typical Use
Param
instance
Instance normal
none self + class
method behavior
data
alternate
class
Class constructors,
@classmethod cls data
method class-wide
only
changes
First
Type Decorator Access Typical Use
Param
Static helper/utility
@staticmethod none neither
method functions
7. Inheritance and Subclasses
Inheritance allows a class (child/subclass) to reuse and extend
the properties/methods of another class (parent/superclass).
class Animal: # Parent / Base /
Super class
def __init__(self, name):
[Link] = name
def speak(self):
print(f"{[Link]} makes a sound")
class Dog(Animal): # Child / Derived /
Sub class
def speak(self): # method overriding
print(f"{[Link]} barks")
class Cat(Animal):
pass # inherits speak() as-
is
d = Dog("Rex")
c = Cat("Whiskers")
[Link]() # Rex barks
[Link]() # Whiskers makes a sound
super() — calling the parent's method
class Animal:
def __init__(self, name):
[Link] = name
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # call parent
constructor
[Link] = breed
def speak(self):
print(f"{[Link]} ({[Link]}) barks")
d = Dog("Rex", "Labrador")
[Link]() # Rex (Labrador) barks
Types of Inheritance
Single: one parent, one child
Multiple: child inherits from more than one parent
Multilevel: grandparent → parent → child
Hierarchical: one parent, multiple children
class A:
def show(self): print("A")
class B:
def show(self): print("B")
class C(A, B): # multiple inheritance
pass
c = C()
[Link]() # "A" (follows Method Resolution Order —
MRO)
print(C.__mro__)
Polymorphism (closely related concept)
Different classes providing the same method name but different
behavior (as seen with speak() above). Enables writing generic
code:
for animal in [Dog("Rex","Lab"), Cat("Kitty")]:
[Link]()
Abstract Classes (using abc module)
Force subclasses to implement certain methods.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
class Circle(Shape):
def __init__(self, r):
self.r = r
def area(self):
return 3.14 * self.r ** 2
# s = Shape() # Error! Cannot instantiate abstract
class
c = Circle(5)
print([Link]()) # 78.5
8. Special Methods (Dunder / Magic
Methods)
Methods surrounded by double underscores that let objects
work with built-in Python syntax/operators.
class Book:
def __init__(self, title, pages):
[Link] = title
[Link] = pages
def __str__(self):
return f"Book: {[Link]}" # used
by print(), str()
def __repr__(self):
return f"Book('{[Link]}', {[Link]})"
# used in debugging/console
def __len__(self):
return [Link] #
used by len()
def __eq__(self, other):
return [Link] == [Link] #
used by ==
def __add__(self, other):
return [Link] + [Link] #
used by +
b1 = Book("Python 101", 300)
b2 = Book("OOP Guide", 300)
print(b1) # Book: Python 101
(__str__)
print(repr(b1)) # Book('Python 101', 300)
(__repr__)
print(len(b1)) # 300
(__len__)
print(b1 == b2) # True
(__eq__)
print(b1 + b2) # 600
(__add__)
Commonly used dunder methods
Method Purpose
__init__ Constructor (object initialization)
Human-readable string
__str__
( print(obj) )
Developer-facing string
__repr__
(debugging)
__len__ Enables len(obj)
__eq__ , __lt__ ,
Enables == , < , > comparisons
__gt__
__add__ , __sub__ Enables + , - operators
__getitem__ ,
Enables obj[i] indexing
__setitem__
__iter__ , __next__ Makes object iterable (for loops)
Makes an instance callable like a
__call__
function
Destructor, called when object is
__del__
deleted
9. Property Decorator ( @property )
Lets you access a method like an attribute — used for getters,
setters, and computed values, enabling encapsulation without
changing how the attribute is accessed from outside.
class Circle:
def __init__(self, radius):
self._radius = radius # "protected"
convention (single underscore)
@property
def radius(self): # getter
return self._radius
@[Link]
def radius(self, value): # setter
if value < 0:
raise ValueError("Radius cannot be
negative")
self._radius = value
@property
def area(self): # computed/read-
only property
return 3.14 * self._radius ** 2
c = Circle(5)
print([Link]) # 5 (called like an attribute,
not [Link]())
print([Link]) # 78.5
[Link] = 10 # uses the setter
print([Link]) # 314.0
[Link] = -5 # raises ValueError
Why use @property instead of plain attributes?
Add validation logic without breaking existing code that uses
[Link] .
Create read-only computed attributes ( area above has no
setter → can't be reassigned directly).
Standard "Pythonic" way to do encapsulation (vs Java-style
getX() / setX() ).
10. Encapsulation & Access Modifiers
(related topic)
Python doesn't have true "private" like Java, but uses naming
conventions:
class Account:
def __init__(self, balance):
[Link] = balance # public
self._pin = 1234 # protected
(convention only)
self.__password = "secret" # private
(name-mangled)
a = Account(1000)
print([Link]) # OK
print(a._pin) # works but "shouldn't" be
accessed directly
# print(a.__password) # AttributeError
print(a._Account__password) # 'secret' — name
mangling reveals real name
_var → protected (convention: "internal use")
__var → private (Python mangles it to _ClassName__var )
Quick Summary Table
One-line
Concept Keyword/Syntax
meaning
Blueprint for
Class class Name:
objects
Actual object
Instance obj = Name()
from the class
Instance Data unique to
self.x = x
variable each object
Data shared by
Class variable defined in class body
all objects
Instance Works with
def m(self):
method instance data
Works with class
Class method @classmethod / cls
data
Utility, no access
Static method @staticmethod
to self/cls
class Reuse parent's
Inheritance
Child(Parent): code
Call parent
super() super().__init__()
method
Dunder __init__ , Hook into built-in
methods __str__ ... behavior
Controlled
@property getter/setter
attribute access
One-line
Concept Keyword/Syntax
meaning
Restrict/protect
Encapsulation _x , __x
access
Tip for your presentation
Use one running example throughout (e.g., Student or Animal )
and build it up feature-by-feature: class → instance → class
variable → classmethod/staticmethod → inheritance → dunder
methods → property. It keeps the audience anchored to one
story instead of many unrelated snippets.