Unit 5 · Advanced Topics
Classes and Objects
Understand how to define classes, create objects, use the __init__ constructor, and work with instance and class variables in Python. The foundation of all OOP programming.
Table of Contents
What is a Class?
University Definition
A class is a user-defined blueprint or template that defines the attributes (data) and methods (functions) that its objects will have. It is a logical entity that does not occupy memory until an object is created from it.
Think of a class as an architect's blueprint for a house. The blueprint itself is not a house — it describes what a house will look like. Similarly, a class describes what objects of that type will contain, but the class itself is not an object.
What is an Object?
University Definition
An object is an instance of a class. It is a runtime entity that occupies memory and contains actual values for the attributes defined in the class. Objects are created through a process called instantiation.
Class vs Object
================
Class: Student (template/blueprint)
Object: Student("Rahul") (actual instance)
Class: Car (template/blueprint)
Object: Car("Toyota") (actual instance)
Class does NOT occupy memory
Object OCCUPIES memory
Creating a Class
# Basic class definition
class Student:
pass # Empty class
# Class with attributes
class Student:
name = "Rahul" # Class attribute
age = 20 # Class attribute
# Creating objects
s1 = Student()
s2 = Student()
# Accessing attributes
print(s1.name) # Rahul
print(s2.name) # Rahul
print(s1.age) # 20
# Modifying attributes
s1.name = "Priya"
print(s1.name) # Priya
print(s2.name) # Rahul (unchanged)
# Class with methods
class Dog:
def bark(self):
print("Woof! Woof!")
def sit(self):
print("The dog is sitting")
# Creating object and calling methods
my_dog = Dog()
my_dog.bark() # Woof! Woof!
my_dog.sit() # The dog is sitting
__init__ Constructor
University Definition
The __init__ method is a special method (constructor) in Python that is automatically called when a new object is created from a class. It initializes the object's attributes with the values passed during creation.
class Student:
def __init__(self, name, age, grade):
self.name = name # Instance variable
self.age = age # Instance variable
self.grade = grade # Instance variable
def display(self):
print(f"Name: {self.name}")
print(f"Age: {self.age}")
print(f"Grade: {self.grade}")
# __init__ is called automatically
s1 = Student("Rahul", 20, "A")
s2 = Student("Priya", 21, "B+")
s1.display()
print("---")
s2.display()
# Accessing attributes directly
print(f"{s1.name} is {s1.age} years old")
print(f"{s2.name} is in grade {s2.grade}")
Output:
Name: Rahul Age: 20 Grade: self.grade --- Name: Priya Age: 21 Grade: self.grade Rahul is 20 years old Priya is in grade B+
self Parameter
University Definition
The self parameter refers to the current instance of the class. It is used to access variables and methods belonging to the object. It must be the first parameter in every instance method but is never passed explicitly when calling the method.
class Person:
def __init__(self, name):
self.name = name # self.name = attribute of the object
def greet(self):
# self refers to the specific object calling this method
print(f"Hello, my name is {self.name}")
print(f"I am {id(self)} years old in memory")
p1 = Person("Alice")
p2 = Person("Bob")
p1.greet()
print("---")
p2.greet()
# self is the object itself
print(f"p1 is: {p1}")
print(f"p2 is: {p2}")
# p1 and p2 are different objects in memory
Output:
Hello, my name is Alice I am 140234567890 years old in memory --- Hello, my name is Bob I am 140234568234 years old in memory p1 is: <__main__.Person object at 0x...> p2 is: <__main__.Person object at 0x...>
University Exam Tip
self is not a keyword — it is a convention. You can name it anything, but using self is the standard Python convention. When you call obj.method(arg), Python automatically passes obj as the first argument (self).
Instance Variables vs Class Variables
class Student:
# CLASS VARIABLES - shared by all objects
school = "ABC University"
total_students = 0
def __init__(self, name, age):
# INSTANCE VARIABLES - unique to each object
self.name = name
self.age = age
Student.total_students += 1
def display(self):
print(f"{self.name}, Age: {self.age}, School: {Student.school}")
# Creating objects
s1 = Student("Rahul", 20)
s2 = Student("Priya", 21)
s3 = Student("Amit", 22)
# Instance variables - different for each object
print(s1.name) # Rahul
print(s2.name) # Priya
print(s3.name) # Amit
# Class variable - same for all objects
print(s1.school) # ABC University
print(Student.school) # ABC University
print(Student.total_students) # 3
# Modifying class variable affects all objects
Student.school = "XYZ University"
print(s1.school) # XYZ University
print(s2.school) # XYZ University
# Modifying instance variable affects only that object
s1.name = "Rahul Sharma"
print(s1.name) # Rahul Sharma
print(s2.name) # Priya (unchanged)
Output:
Rahul Priya Amit ABC University ABC University 3 XYZ University XYZ University Rahul Sharma Priya
| Feature | Instance Variable | Class Variable |
|---|---|---|
| Defined in | __init__ using self.var | Inside class, outside methods |
| Shared | Unique to each object | Shared by all objects |
| Memory | Separate for each object | Single copy for all |
| Access | object.var | ClassName.var or object.var |
__str__ and __repr__
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
def __str__(self):
"""Human-readable string (for print, str())"""
return f"Student({self.name}, Grade: {self.grade})"
def __repr__(self):
"""Developer representation (for debugging)"""
return f"Student('{self.name}', '{self.grade}')"
s = Student("Rahul", "A")
# __str__ is called by print() and str()
print(s) # Student(Rahul, Grade: A)
print(str(s)) # Student(Rahul, Grade: A)
# __repr__ is called in the interpreter/debugger
print(repr(s)) # Student('Rahul', 'A')
# In a list, __repr__ is used
print([s, Student("Priya", "B+")])
# [Student('Rahul', 'A'), Student('Priya', 'B+')]
Output:
Student(Rahul, Grade: A)
Student(Rahul, Grade: A)
Student('Rahul', 'A')
[Student('Rahul', 'A'), Student('Priya', 'B+')]
Multiple Objects Example
class BankAccount:
bank_name = "State Bank of India"
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
self transactions = []
def deposit(self, amount):
if amount > 0:
self.balance += amount
self.transactions.append(f"+{amount}")
print(f"Deposited {amount}. Balance: {self.balance}")
def withdraw(self, amount):
if 0 < amount <= self.balance:
self.balance -= amount
self.transactions.append(f"-{amount}")
print(f"Withdrawn {amount}. Balance: {self.balance}")
else:
print("Insufficient funds!")
def get_statement(self):
print(f"--- Statement for {self.owner} ---")
print(f"Bank: {BankAccount.bank_name}")
print(f"Transactions: {', '.join(self.transactions)}")
print(f"Final Balance: {self.balance}")
# Creating multiple objects
acc1 = BankAccount("Rahul", 5000)
acc2 = BankAccount("Priya", 10000)
acc1.deposit(2000) # Deposited 2000. Balance: 7000
acc1.withdraw(1500) # Withdrawn 1500. Balance: 5500
acc2.deposit(5000) # Deposited 5000. Balance: 15000
acc2.withdraw(3000) # Withdrawn 3000. Balance: 12000
acc1.get_statement()
acc2.get_statement()
# Objects are independent
print(f"Rahul's balance: {acc1.balance}")
print(f"Priya's balance: {acc2.balance}")
Output:
Deposited 2000. Balance: 7000 Withdrawn 1500. Balance: 5500 Deposited 5000. Balance: 15000 Withdrawn 3000. Balance: 12000 --- Statement for Rahul --- Bank: State Bank of India Transactions: +2000, -1500 Final Balance: 5500 --- Statement for Priya --- Bank: State Bank of India Transactions: +5000, -3000 Final Balance: 12000 Rahul's balance: 5500 Priya's balance: 12000
Common Mistakes to Avoid
- Forgetting
selfas the first parameter in methods — causes TypeError. - Confusing class variables with instance variables — class variables are shared.
- Calling a method before defining it in the class body.
- Using class name to access instance variables — must use object reference.
- Forgetting that
__init__is called automatically — no need to call it explicitly.
Practice Questions
- Create a
Circleclass with radius attribute and methods to calculate area and circumference. - Write a
Carclass with class variable tracking total cars manufactured and instance variables for brand, model, and color. - Implement a
Counterclass with increment, decrement, and reset methods. - Create a
Studentclass that stores marks for 3 subjects and calculates the average.
Key Points
A class is a blueprint; an object is an instance of a class.
__init__ is the constructor method called automatically during object creation.
self refers to the current instance and must be the first parameter of all methods.
Instance variables are unique per object; class variables are shared.
__str__ provides human-readable output; __repr__ provides developer representation.
Each object has its own copy of instance variables but shares class variables.