Python OOP interview questions and answers
15 min readUpdated
Object-oriented programming is asked in almost every fresher interview. These 25 questions cover classes, the four pillars, inheritance and MRO, properties, abstract classes and dunder methods. Every program was run, and the output shown is the real output.
How to use this list
- Say each answer out loud first. OOP questions are about explaining, not only writing code.
- Run every program and compare the output with your guess.
- In an interview, give a small example from your own project. It shows you have used the idea.
Classes and objects
1. What is the difference between a class and an object?
A class is a blueprint: it describes what data and behaviour its objects have. An object (instance) is one thing made from that blueprint, with its own data. Student is a class. Student("Asha") is an object.
2. What is self?
self is the first parameter of an instance method. It refers to the object the method was called on. Python passes it automatically: obj.method() is the same as Class.method(obj). The name self is a convention, but you should always use it.
3. What is __init__? Is it a constructor?
__init__ is the initialiser. Python creates the empty object first (with __new__), then calls __init__ to set up its attributes. In everyday talk people call it the constructor, and that is fine in an interview. It must return None.
class Student:
def __init__(self, name, marks):
self.name = name
self.marks = marks
def grade(self):
return "Pass" if self.marks >= 40 else "Fail"
asha = Student("Asha", 88)
ravi = Student("Ravi", 35)
print(asha.name, asha.grade())
print(ravi.name, ravi.grade())
print(Student.grade(ravi)) # same as ravi.grade()
Output
Asha Pass Ravi Fail Fail
4. What is the difference between instance variables and class variables?
An instance variable belongs to one object and is usually set in __init__ with self.x = .... A class variable is defined in the class body and is shared by all objects. Assigning self.count = ... creates an instance variable and hides the class one. Change the shared value through the class name.
class Counter:
total = 0 # class variable, shared
def __init__(self):
Counter.total += 1 # change it through the class
self.mine = Counter.total
a = Counter()
b = Counter()
print(a.mine, b.mine, Counter.total)
a.total = 100 # creates an instance variable on a only
print(a.total, b.total, Counter.total)
Output
1 2 2 100 2 2
5. What are @classmethod and @staticmethod? When do you use each?
A class method gets the class as cls. Use it for alternative constructors, such as from_string. A static method gets neither self nor cls; it is a plain function kept inside the class because it belongs with it. An instance method gets self and works on one object.
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
@classmethod
def from_string(cls, text):
name, salary = text.split("-")
return cls(name, int(salary))
@staticmethod
def is_valid_salary(amount):
return amount > 0
e = Employee.from_string("Meena-50000")
print(e.name, e.salary)
print(Employee.is_valid_salary(-5))
Output
Meena 50000 False
The four pillars
6. What are the four pillars of OOP? How does Python support them?
Encapsulation: keep data and the code that uses it together, and control access. Abstraction: show what an object does, hide how. Inheritance: a class reuses and extends another. Polymorphism: one interface, many behaviours. Python supports all four, but it relies on conventions and duck typing more than strict rules.
7. How does encapsulation work when Python has no private keyword?
Python uses naming conventions. _name means "internal, please do not touch". __name triggers name mangling: Python renames it to _ClassName__name, which avoids clashes in subclasses. It is not real security. For controlled access, use a property.
class Account:
def __init__(self, balance):
self._balance = balance # internal by convention
@property
def balance(self): # read-only access
return self._balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("amount must be positive")
self._balance += amount
acc = Account(100)
acc.deposit(50)
print(acc.balance)
try:
acc.balance = 0
except AttributeError as error:
print("AttributeError:", error)
Output
150 AttributeError: property 'balance' of 'Account' object has no setter
8. What is a property? Why use @property?
A property lets you access a method like an attribute: obj.balance instead of obj.get_balance(). You can start with a plain attribute and later add validation with a property without changing the code that uses it. Add @name.setter to allow assignment with checks.
9. What is inheritance? What does super() do?
Inheritance lets a child class reuse and extend a parent class. super() gives access to the parent's methods, most often to call super().__init__(...) so the parent sets up its part of the object.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "..."
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
def speak(self): # overrides the parent method
return "Woof"
d = Dog("Bruno", "Labrador")
print(d.name, d.breed, d.speak())
print(isinstance(d, Animal), issubclass(Dog, Animal))
Output
Bruno Labrador Woof True True
10. What is polymorphism? What is duck typing?
Polymorphism means the same call behaves differently for different objects. In Python it does not need a shared parent. If an object has the method you call, it works. That is duck typing: "if it walks like a duck and quacks like a duck, it is a duck".
class Cat:
def speak(self):
return "Meow"
class Robot:
def speak(self):
return "Beep"
for thing in [Cat(), Robot()]: # no common parent needed
print(thing.speak())
Output
Meow Beep
11. What is method overriding? Does Python support overloading?
Overriding means a child class gives its own version of a parent method. Python has no method overloading by signature. If you define two methods with the same name, the later one replaces the first. Use default arguments, *args, or functools.singledispatch instead.
Inheritance in depth
12. What is the MRO? How does Python handle multiple inheritance?
A class can have more than one parent. The Method Resolution Order (MRO) is the order Python searches the classes for a method. It uses the C3 linearisation rule, which keeps the order of the parents and each class before its parents. See it with ClassName.__mro__ or ClassName.mro().
class A:
def hello(self):
return "A"
class B(A):
def hello(self):
return "B"
class C(A):
def hello(self):
return "C"
class D(B, C):
pass
print(D().hello())
print([cls.__name__ for cls in D.__mro__])
Output
B ['D', 'B', 'C', 'A', 'object']
13. What is the diamond problem, and how does Python solve it?
With two parents that share a grandparent, it can be unclear which version of a method to call. Python solves this with the MRO. Each class appears once in the order, and super() follows that order, so the shared parent is not run twice.
14. Composition or inheritance: which is better?
Use inheritance for a true is-a relationship (a Dog is an Animal). Use composition for has-a (a Car has an Engine). Composition is more flexible because you can swap the part without changing the class tree. A good rule: prefer composition when you are unsure.
class Engine:
def start(self):
return "Engine started"
class Car:
def __init__(self):
self.engine = Engine() # Car HAS an Engine
def start(self):
return self.engine.start()
print(Car().start())
Output
Engine started
Abstraction and special methods
15. How do you make an abstract class in Python?
Inherit from abc.ABC and mark methods with @abstractmethod. You cannot create an object of the class until a subclass implements every abstract method. It lets you define a contract that children must follow.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
...
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side ** 2
try:
Shape()
except TypeError:
print("TypeError: Shape is abstract")
print(Square(4).area())
Output
TypeError: Shape is abstract 16
16. What are dunder (magic) methods? Name a few.
Dunder methods have double underscores on both sides. Python calls them for you when you use an operator or a built-in. Examples: __init__ (create), __str__ and __repr__ (text), __eq__ (==), __lt__ (<), __len__ (len()), __getitem__ (obj[i]), __add__ (+).
17. What is the difference between __str__ and __repr__?
__str__ is the readable text for users (used by print and str()). __repr__ is the unambiguous text for developers, ideally something that could recreate the object. If only __repr__ is defined, print uses it too.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
def __str__(self):
return f"({self.x}, {self.y})"
def __eq__(self, other):
return isinstance(other, Point) and (self.x, self.y) == (other.x, other.y)
def __hash__(self):
return hash((self.x, self.y))
p = Point(1, 2)
print(p)
print([p]) # lists use repr
print(p == Point(1, 2))
print(len({p, Point(1, 2)})) # equal points collapse in a set
Output
(1, 2) [Point(1, 2)] True 1
18. If you define __eq__, why must you think about __hash__?
Objects that are equal must have the same hash, or sets and dicts break. When you define __eq__ and not __hash__, Python sets __hash__ to None, so the object becomes unhashable. Define both, and base the hash on the same fields that == compares. Only do this for immutable data.
19. What is a dataclass? Why use it?
@dataclass writes __init__, __repr__ and __eq__ for you from the field list. It is ideal for classes that mostly hold data. Use frozen=True to make instances immutable and hashable.
from dataclasses import dataclass
@dataclass
class Book:
title: str
pages: int = 100
b = Book("Python Basics")
print(b)
print(b == Book("Python Basics", 100))
Output
Book(title='Python Basics', pages=100) True
Design questions
20. What is the difference between an abstract class and an interface in Python?
Python has no interface keyword. An abstract class (ABC) can mix abstract methods with real ones and shared state. A pure interface is just an ABC with only abstract methods. Python also supports typing.Protocol for structural typing: any class with the right methods fits, with no inheritance needed.
21. Is everything an object in Python?
Yes. Numbers, strings, functions, classes and modules are all objects. Even a class is an object, made by its metaclass (type by default). You can check with type(5), which gives int.
22. What is the difference between isinstance and type?
isinstance(obj, Cls) is true for the class and its subclasses, so it respects inheritance. type(obj) == Cls is true only for the exact class. Prefer isinstance in most checks.
23. What is a mixin?
A mixin is a small class that adds one feature and is meant to be combined with other classes through multiple inheritance, for example a JsonMixin that adds to_json(). It is not used on its own. Keep mixins small and without their own state.
24. What does __slots__ do?
__slots__ fixes the list of attributes an object can have. Python then does not create a __dict__ per object, which saves memory when you create very many objects, and it blocks accidental new attributes.
25. How do you design a clean class? Name some good practices.
Give a class one clear job. Keep data private by convention and expose it through methods or properties. Validate input in __init__ or setters. Add __repr__ for easy debugging. Prefer composition. Write small methods that do one thing, and test them.
Tips for OOP rounds
- Always give a tiny real example, such as a
BankAccountorStudent. Avoid abstract talk. - Draw the class diagram when asked to design something: classes, attributes, methods and the arrows between them.
- If asked "design a library system", list the classes first, then the relationships, then the code.
- Know the difference between what Python enforces (little) and what it expects by convention (a lot).
Frequently asked questions
Is Python fully object-oriented?
Python supports OOP fully, but it does not force it. You can write functions and scripts with no classes. Everything in Python is an object, though, including functions and classes.
Does Python have private variables?
Not truly. A leading underscore marks a name as internal, and a double underscore mangles the name. Both are conventions that tell other programmers not to touch it.
Which OOP topics do interviewers ask most?
The four pillars, inheritance with super() and MRO, class vs static methods, properties, abstract classes and __str__ vs __repr__. Be ready to write a small class from scratch.
Do I need design patterns for fresher interviews?
Rarely. Know the idea of composition over inheritance and be able to design a small system like a library or a bank account with clean classes.
Learn it step by step
- Classes, Instances, self and Attributes
- Inheritance, MRO, super() and Duck Typing
- Encapsulation, Properties and Abstract Classes
- Dunder Methods, Dataclasses and Design Questions
- Class Variables vs Instance Variables
- The super() Proxy and Method Resolution Order (MRO)
- Abstract Base Classes (abc Module)
- Has-a versus Is-a: Why Prefer Composition
- Equality and Hashing: __eq__ and __hash__
More interview questions by topic
Practise this, step by step
Short lessons with quizzes, practice and interview questions, from your first program to job-ready.