How to Use This Page
1. Attempt every exercise on your own before reading the solution. 2. Compare your approach with the solution — focus on the logic, not just the final answer. 3. Type and run the Python code on your computer; reading alone is not enough. 4. Review the Common Mistakes section to avoid errors that cost marks in exams.
Key Concepts
| Concept | Syntax / Description |
|---|---|
| Class | Blueprint for creating objects: class ClassName: |
| Object | Instance of a class: obj = ClassName() |
__init__ | Constructor method — runs automatically when object is created |
self | Reference to the current instance — first parameter of instance methods |
| Instance variable | Unique to each object: self.var = value |
| Class variable | Shared by all objects: defined in class body |
| Instance method | Operates on instance data: def method(self): |
| Class method | Operates on class data: @classmethod def method(cls): |
| Static method | Independent of instance/class: @staticmethod def method(): |
| Inheritance | Child class inherits from parent: class Child(Parent): |
super() | Calls parent class methods |
__str__ | Returns user-friendly string (used by print()) |
__repr__ | Returns developer-friendly string (used by repr()) |
Multiple Choice Questions (MCQs)
Q1. Which method is called automatically when an object is created?
- (a)
__new__ - (b)
__init__ - (c)
__create__ - (d)
__start__
Q2. What does the self parameter refer to in a class method?
- (a) The class itself
- (b) The parent class
- (c) The current instance of the class
- (d) A global variable
Q3. Which of the following is a class variable?
- (a)
self.name = "Arun" - (b)
name = "Arun"(defined directly in the class body) - (c)
obj.name = "Arun" - (d)
def name(self):
Q4. In single inheritance, if class B inherits from class A, which statement is true?
- (a) B can access only its own methods
- (b) B can access methods of A as well as its own
- (c) A can access methods of B
- (d) B cannot add new methods
Q5. What does super().__init__() do?
- (a) Creates a new object
- (b) Calls the parent class constructor
- (c) Deletes the parent class
- (d) Overrides the current class
Fill in the Blanks
Q1. A ______ is a blueprint, and an ______ is an instance created from it.
Q2. The ______ method is the constructor that initializes an object's attributes.
Q3. Variables defined with self inside __init__ are called ______ variables.
Q4. A ______ method uses @classmethod decorator and takes cls as the first parameter.
Q5. When a child class redefines a method from the parent class, it is called method ______.
True or False
Q1. A class can have only one __init__ method.
Q2. self is a keyword in Python.
Q3. A static method can access instance variables directly.
Q4. In inheritance, a child class can access private members of the parent class.
Q5. __str__ is called by the print() function.
Match the Following
| Column A | Column B |
|---|---|
1. __init__ | (a) Blueprint for objects |
2. self | (b) Calls parent class method |
| 3. Class | (c) Constructor method |
4. super() | (d) Reference to current instance |
5. @staticmethod | (e) Method independent of instance/class |
Short Answer Questions
Q1. What is a class? What is an object? How are they related?
A class is a blueprint or template that defines the attributes and methods common to all objects of that type. An object is a specific instance created from a class.
class Car: # Class (blueprint)
def __init__(self, brand, color):
self.brand = brand # Instance variable
self.color = color
c1 = Car("Honda", "Red") # Object (instance)
c2 = Car("Toyota", "Blue") # Another object
print(c1.brand) # Honda
print(c2.color) # Blue
Each object has its own copy of instance variables but shares the class definition.
Q2. Explain the __init__ method with an example.
__init__ is the constructor method. It is called automatically when a new object is created and is used to initialize the object's attributes.
class Student:
def __init__(self, name, roll_no, marks):
self.name = name
self.roll_no = roll_no
self.marks = marks
def display(self):
print(f"Name: {self.name}, Roll: {self.roll_no}, Marks: {self.marks}")
s = Student("Arun", 101, 95) # __init__ is called automatically
s.display()
# Output: Name: Arun, Roll: 101, Marks: 95
Q3. Differentiate between instance variables and class variables.
| Feature | Instance Variable | Class Variable |
|---|---|---|
| Defined in | Inside __init__ using self | Directly in class body |
| Scope | Unique to each object | Shared by all objects |
| Access | self.var or obj.var | ClassName.var or self.var |
| Change | Affects only that object | Affects all objects (if changed via class) |
class Student:
school = "KV" # Class variable (shared)
def __init__(self, name):
self.name = name # Instance variable (unique)
s1 = Student("Arun")
s2 = Student("Bala")
print(s1.school) # KV (shared)
print(s2.school) # KV (shared)
Student.school = "DPS"
print(s1.school) # DPS (changed for all)
Q4. Differentiate between instance method, class method, and static method.
| Feature | Instance Method | Class Method | Static Method |
|---|---|---|---|
| Decorator | None | @classmethod | @staticmethod |
| First param | self | cls | None |
| Access instance data? | Yes | No | No |
| Access class data? | Yes | Yes | No |
| Call via | obj.method() | ClassName.method() or obj.method() | ClassName.method() or obj.method() |
class MyClass:
count = 0 # class variable
def __init__(self):
MyClass.count += 1
def instance_method(self):
return f"Instance method: self.data"
@classmethod
def class_method(cls):
return f"Class method: count={cls.count}"
@staticmethod
def static_method():
return "Static method: no self or cls"
obj = MyClass()
print(obj.instance_method()) # Instance method
print(MyClass.class_method()) # Class method: count=1
print(MyClass.static_method()) # Static method
Q5. What is inheritance? Give an example.
Inheritance allows a child class to acquire properties and methods from a parent class, promoting code reuse.
class Animal: # Parent class
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} makes a sound"
class Dog(Animal): # Child class
def speak(self): # Method overriding
return f"{self.name} barks"
class Cat(Animal): # Child class
def speak(self):
return f"{self.name} meows"
d = Dog("Rex")
c = Cat("Whiskers")
print(d.speak()) # Rex barks
print(c.speak()) # Whiskers meows
Detailed Answers
Q1. Write a Python program to create a Student class with __init__, display, and grade calculation methods.
class Student:
def __init__(self, name, roll_no, marks):
"""Constructor to initialize student details."""
self.name = name
self.roll_no = roll_no
self.marks = marks # marks is a list of subject marks
def display(self):
"""Display student information."""
print(f"Name: {self.name}")
print(f"Roll No: {self.roll_no}")
print(f"Marks: {self.marks}")
def total(self):
"""Calculate total marks."""
return sum(self.marks)
def average(self):
"""Calculate average marks."""
return self.total() / len(self.marks)
def grade(self):
"""Determine grade based on average."""
avg = self.average()
if avg >= 90:
return "A+"
elif avg >= 75:
return "A"
elif avg >= 60:
return "B"
elif avg >= 50:
return "C"
else:
return "D"
def __str__(self):
return f"Student({self.name}, Roll:{self.roll_no}, Grade:{self.grade()})"
# Creating objects
s1 = Student("Arun", 101, [85, 90, 78, 92, 88])
s2 = Student("Bala", 102, [55, 62, 48, 70, 65])
for s in [s1, s2]:
s.display()
print(f"Total: {s.total()}")
print(f"Average: {s.average():.2f}")
print(f"Grade: {s.grade()}")
print(f"String: {s}")
print("---")
Q2. Demonstrate inheritance with a parent class Employee and child classes Manager and Developer.
class Employee:
company = "TechCorp" # Class variable
def __init__(self, name, emp_id, salary):
self.name = name
self.emp_id = emp_id
self.salary = salary
def display(self):
print(f"Name: {self.name}, ID: {self.emp_id}, Salary: ₹{self.salary}")
def annual_salary(self):
return self.salary * 12
class Manager(Employee):
def __init__(self, name, emp_id, salary, team_size):
super().__init__(name, emp_id, salary) # Call parent constructor
self.team_size = team_size
def display(self):
super().display() # Call parent display
print(f"Role: Manager, Team Size: {self.team_size}")
def bonus(self):
return self.salary * 0.2 # 20% bonus
class Developer(Employee):
def __init__(self, name, emp_id, salary, language):
super().__init__(name, emp_id, salary)
self.language = language
def display(self):
super().display()
print(f"Role: Developer, Language: {self.language}")
def bonus(self):
return self.salary * 0.1 # 10% bonus
# Creating objects
m = Manager("Priya", "M101", 80000, 8)
d = Developer("Kumar", "D201", 60000, "Python")
m.display()
print(f"Annual Salary: ₹{m.annual_salary()}")
print(f"Bonus: ₹{m.bonus()}")
print("---")
d.display()
print(f"Annual Salary: ₹{d.annual_salary()}")
print(f"Bonus: ₹{d.bonus()}")
Q3. Write a program to demonstrate __str__ and __repr__ methods.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
"""User-friendly string representation."""
return f"Point({self.x}, {self.y})"
def __repr__(self):
"""Developer-friendly string representation."""
return f"Point(x={self.x}, y={self.y})"
p = Point(3, 5)
# __str__ is called by print() and str()
print(p) # Point(3, 5)
print(str(p)) # Point(3, 5)
# __repr__ is called by repr() and in the interactive shell
print(repr(p)) # Point(x=3, y=5)
# When only __repr__ is defined, it is also used by print()
# When both are defined, print() uses __str__
Q4. Write a BankAccount class with deposit, withdraw, and balance check methods.
class BankAccount:
bank_name = "Indian Bank" # Class variable
def __init__(self, holder, balance=0):
self.holder = holder
self.balance = balance
def deposit(self, amount):
if amount > 0:
self.balance += amount
print(f"Deposited ₹{amount}. Balance: ₹{self.balance}")
else:
print("Deposit amount must be positive")
def withdraw(self, amount):
if amount > self.balance:
print("Insufficient balance!")
elif amount <= 0:
print("Withdrawal amount must be positive")
else:
self.balance -= amount
print(f"Withdrew ₹{amount}. Balance: ₹{self.balance}")
def check_balance(self):
print(f"Account Holder: {self.holder}")
print(f"Bank: {self.bank_name}")
print(f"Balance: ₹{self.balance}")
def __str__(self):
return f"BankAccount({self.holder}, Balance: ₹{self.balance})"
# Using the class
acc = BankAccount("Arun", 5000)
acc.deposit(3000) # Deposited ₹3000. Balance: ₹8000
acc.withdraw(2000) # Withdrew ₹2000. Balance: ₹6000
acc.withdraw(10000) # Insufficient balance!
acc.check_balance()
Q5. Demonstrate method overriding and the use of super().
class Shape:
def __init__(self, name):
self.name = name
def area(self):
return 0
def __str__(self):
return f"{self.name}: area = {self.area()}"
class Rectangle(Shape):
def __init__(self, length, breadth):
super().__init__("Rectangle") # Call parent __init__
self.length = length
self.breadth = breadth
def area(self): # Override parent method
return self.length * self.breadth
class Circle(Shape):
def __init__(self, radius):
super().__init__("Circle")
self.radius = radius
def area(self): # Override parent method
return 3.14159 * self.radius ** 2
r = Rectangle(5, 3)
c = Circle(4)
print(r) # Rectangle: area = 15
print(c) # Circle: area = 50.26544
Q6. Write a program demonstrating class methods and static methods.
class Temperature:
def __init__(self, celsius):
self.celsius = celsius
@classmethod
def from_fahrenheit(cls, fahrenheit):
"""Class method: create object from Fahrenheit."""
celsius = (fahrenheit - 32) * 5 / 9
return cls(celsius) # calls __init__
@staticmethod
def is_freezing(celsius):
"""Static method: check if temperature is freezing."""
return celsius <= 0
def display(self):
print(f"Temperature: {self.celsius:.2f}°C")
# Using instance method
t1 = Temperature(25)
t1.display() # Temperature: 25.00°C
# Using class method as alternative constructor
t2 = Temperature.from_fahrenheit(98.6)
t2.display() # Temperature: 37.00°C
# Using static method
print(Temperature.is_freezing(-5)) # True
print(Temperature.is_freezing(20)) # False
Common Mistakes
| Mistake | Why It's Wrong | Correction |
|---|---|---|
Forgetting self in method definition | def display(): causes TypeError | Always use def display(self): |
Using __init__ as __int__ | Typo — method never called | Spell it as __init__ with double underscores |
Accessing class variable as self.class_var = value | Creates an instance variable shadowing the class variable | Use ClassName.class_var = value to change the class variable |
Not calling super().__init__() in child class | Parent attributes are not initialized | Call super().__init__(args) in child's __init__ |
Using __str__ but not __repr__ | repr() falls back to default | Define both for complete string representation |
| Confusing class method and static method | Class method takes cls, static takes neither | @classmethod uses cls; @staticmethod has no special first param |
Creating a single-element tuple (5) instead of (5,) | Parentheses make it an integer, not tuple | Always use trailing comma for single-element tuples |
Exam Checklist
- [ ] I can define a class with
__init__, instance variables, and methods - [ ] I understand the role of
selfand can use it correctly - [ ] I can differentiate between instance variables and class variables
- [ ] I can write instance methods, class methods (
@classmethod), and static methods (@staticmethod) - [ ] I can implement inheritance using
class Child(Parent): - [ ] I can use
super()to call parent class methods - [ ] I can override methods in child classes
- [ ] I can implement
__str__and__repr__for custom string representation - [ ] I can create and use objects with proper attribute access
- [ ] I can trace through OOP code and predict outputs
