1. What is the difference between a class and an object?
Provide a real-world
analogy.
Solution:
A class is a blueprint or template that defines the structure (attributes) and behavior
(methods) of objects. An object is an instance of that class—a concrete realization created in
memory.
Analogy: A class is like an architectural blueprint for a house, specifying room layouts and
dimensions. An object is the actual house built from that blueprint, with unique furnishings
and occupants.
Thus, a class defines the general form, while objects are specific, usable instances.
2. Explain the purpose of the __init__ method in Python. Is it mandatory to define it
in a class?
Solution:
The __init__ method is a special constructor method that is automatically called when an
object is instantiated. Its primary role is to initialize the object’s instance variables with
initial values passed as arguments. It is not mandatory—if omitted, Python provides a
default constructor that does nothing. However, defining __init__ is common to set up an
object’s initial state and ensure it is ready for use upon creation.
3. What is the difference between an instance variable and a class variable? Give
an example.
Solution:
Instance variables belong to individual objects and hold data unique to each instance
(e.g., [Link]). Class variables are shared across all instances of a class and are defined
directly within the class (e.g., college_name).
For example, in a Student class, each student’s name is an instance variable,
while school_name is a class variable shared by all students. Changes to an instance
variable affect only that object; changes to a class variable affect all instances.
4. What happens when you write obj.class_var = value, if class_var is a class
variable?
Solution:
When you assign a value to obj.class_var, Python does not modify the class variable.
Instead, it creates a new instance variable with the same name for that specific object.
The original class variable remains unchanged for the class and other objects. To truly
modify the class variable, you must access it via the class itself: ClassName.class_var =
value.
5. Describe the three types of methods in Python classes with an example of
each.
Solution:
Instance methods operate on an instance and take self as the first parameter. Class
methods operate on the class itself, take cls as the first parameter, and use
the @classmethod decorator. Static methods are utility functions that don’t depend on
instance or class data, use the @staticmethod decorator, and take no special first
parameter.
Example:
def instance_method(self) – works on object data.
@classmethod def class_method(cls) – modifies class-level data.
@staticmethod def static_method() – performs a standalone task.
6. Explain the use of super() in inheritance with an example.
Solution:
The super() function allows a child class to call a method from its parent class. It is
commonly used in the child’s __init__ method to invoke the parent’s constructor, ensuring
proper initialization of inherited attributes.
Example:
python
class Child(Parent):
def __init__(self, x, y):
super().__init__(x) # Calls Parent.__init__
self.y = y
This promotes code reuse and maintains the inheritance chain cleanly.
7. What is multiple inheritance? Give an example where it might be useful.
Solution:
Multiple inheritance occurs when a class inherits from more than one parent class. This
allows the child class to combine features from multiple sources.
A practical example is a SmartWatch class inheriting from both Watch (timekeeping
features) and FitnessTracker (health monitoring features). However, it should be used
carefully to avoid complexity and method conflicts.
8. What is Method Resolution Order (MRO)? How can you check the MRO of a
class?
Solution:
Method Resolution Order (MRO) is the order in which Python searches for methods in a class
hierarchy, especially important in multiple inheritance. It follows the C3 linearization
algorithm to ensure a consistent and predictable search path.
You can check the MRO using either:
ClassName.__mro__ (returns a tuple) or
[Link]() (returns a list).
9. What is the diamond problem in inheritance? How does Python resolve it?
Solution:
The diamond problem occurs in multiple inheritance when a class inherits from two parent
classes that both inherit from a common grandparent class, forming a diamond-shaped
inheritance hierarchy. This creates ambiguity in method resolution because the child class
could inherit the same method from two different paths. For example, consider classes A, B,
C, and D where B and C inherit from A, and D inherits from both B and C. When D calls a
method defined in A, Python must decide whether to use the version from B's path or C's
path. Without a consistent resolution strategy, this leads to unpredictable behavior.
Python resolves this using the C3 Linearization algorithm, which computes a
deterministic Method Resolution Order (MRO). The algorithm follows three key principles:
children precede their parents, the order in inheritance lists is preserved, and the hierarchy
remains monotonic. This results in a linear class ordering that avoids duplication and
ambiguity. For example, with class D(B, C), the MRO becomes D → B → C → A → object,
ensuring each class appears only once and method lookup follows a consistent path.
You can examine the MRO using ClassName.__mro__ or [Link]():
Example:
class A:
def method(self):
return "A"
class B(A):
def method(self):
return "B"
class C(A):
def method(self):
return "C"
class D(B, C):
pass
print(D.__mro__)
# Output: (<class '__main__.D'>, <class '__main__.B'>,
# <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
obj = D()
print([Link]()) # Output: "B" (follows MRO: D → B → ...)
10. What is polymorphism? Explain with an example.
Solution:
Polymorphism allows objects of different classes to be treated as objects of a common
superclass, with the same method name producing different behaviors.
For example, consider a Shape superclass with an area() method. Subclasses
like Circle and Rectangle each implement area() differently. A function that
calls [Link]() will work correctly for any shape object, demonstrating polymorphic
behavior.
11. What is duck typing? Provide a Python example.
Solution:
Duck typing is a programming concept where an object’s suitability is determined by the
presence of certain methods or properties, not its actual type. The phrase “If it walks like a
duck and quacks like a duck, it’s a duck” captures the idea.
Example:
python
def make_sound(animal):
return [Link]()
# Works for any object with a speak() method
This makes Python code flexible and loosely coupled.
12. Differentiate between method overriding and method overloading in Python.
Solution:
Method overriding occurs when a child class provides a new implementation for a method
already defined in its parent class.
Method overloading involves having multiple methods with the same name but different
parameters; Python does not support it natively but simulates it using default arguments
or *args.
Thus, overriding changes behavior in a subclass, while overloading provides multiple ways
to call a method.
13. What is an abstract class? How do you create one in Python?
Solution:
An abstract class is a class that cannot be instantiated and is designed to be inherited by
subclasses. It may contain abstract methods that must be implemented by any concrete
subclass.
In Python, you create an abstract class by inheriting from ABC (Abstract Base Class) and
using the @abstractmethod decorator on methods that require implementation.
14. What is the purpose of the @abstractmethod decorator?
Solution:
The @abstractmethod decorator marks a method as abstract, meaning it has no
implementation in the abstract class and must be overridden in any concrete subclass. If a
subclass fails to implement all abstract methods, it remains abstract and cannot be
instantiated. This enforces a contract and ensures consistent interfaces across related
classes.
15. Write a Python class Book with a constructor that initializes title and author,
and a method display() that prints the book info.
Solution:
python
class Book:
def __init__(self, title, author):
[Link] = title
[Link] = author
def display(self):
print(f"Title: {[Link]}, Author: {[Link]}")
# Usage:
b = Book("1984", "George Orwell")
[Link]() # Output: Title: 1984, Author: George Orwell
16. Create a class Counter with a class variable count that increments each time an
object is created.
Solution:
python
class Counter:
count = 0 # Class variable
def __init__(self):
[Link] += 1 # Increment on each instantiation
# Usage:
c1 = Counter()
c2 = Counter()
print([Link]) # Output: 2
17. Write a class Rectangle with methods area() and perimeter(). Then create a
subclass Square that overrides the constructor appropriately.
Solution:
python
class Rectangle:
def __init__(self, length, width):
[Link] = length
[Link] = width
def area(self):
return [Link] * [Link]
def perimeter(self):
return 2 * ([Link] + [Link])
class Square(Rectangle):
def __init__(self, side):
super().__init__(side, side) # Length = Width = Side
18. What are *args and **kwargs? Show how they can be used in a constructor.
Solution:
*args allows a function or constructor to accept any number of positional arguments,
collected as a tuple. **kwargs allows any number of keyword arguments, collected as a
dictionary.
Example in a constructor:
Python example:
class Product:
def __init__(self, *args, **kwargs):
[Link] = args # Stores positional arguments
[Link] = kwargs # Stores keyword arguments
# Create an object with mixed arguments
laptop = Product("Laptop", "15-inch", price=1200, brand="Dell")
print([Link]) # Output: ('Laptop', '15-inch')
print([Link]) # Output: {'price': 1200, 'brand': 'Dell'}
print([Link]['brand']) # Output: 'Dell'
This provides flexibility for handling variable inputs.
19. Create an abstract class Animal with an abstract method speak(). Then create a
subclass Dog that implements it.
Solution:
python
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof"
# Usage:
d = Dog()
print([Link]()) # Output: Woof
20. What is encapsulation? How can you achieve it in Python?
Solution:
Encapsulation is the bundling of data (attributes) and methods that operate on that data
within a single unit (class), while restricting direct access to some components. In Python,
encapsulation is achieved through naming conventions:
Single underscore _var indicates “protected” (internal use).
Double underscore __var triggers name mangling for “private” attributes.
Properties (@property) provide controlled access with getters and setters.
This helps protect object integrity and hide implementation details.