What is a class and what is an object in Python?
A class is a blueprint of attributes and methods; an object is one instance built from it, set up by
__init__.Pythonclass BankAccount: bank = "Coddy Bank" # class attribute, shared def __init__(self, owner, balance=0): self.owner = owner # instance attributes self.balance = balance def deposit(self, amount): self.balance += amount return self.balance a = BankAccount("Ravi") b = BankAccount("Asha", 500) a.deposit(100) print(a.owner, a.balance, b.owner, b.balance, a.bank)Each instance has its own
ownerandbalance, while the class attributebankis shared. See classes.What is
selfin Python?selfis the instance a method was called on, passed automatically as the first argument, soa.deposit(100)isBankAccount.deposit(a, 100). It is a convention, not a keyword, and there is no implicitthis, so attributes needself.balance.How do you make a variable private in Python?
Python has no
privatekeyword._balancemarks an attribute as internal by convention;__balanceis name-mangled to_ClassName__balance, so subclasses do not overwrite it by accident.Pythonclass Account: def __init__(self): self._internal = "by convention" self.__secret = 42 acc = Account() print(acc._internal) try: print(acc.__secret) except AttributeError as e: print("AttributeError:", e) print(acc._Account__secret)Mangling prevents clashes, not access. For controlled access, use a
@property.What is polymorphism in Python, and what is duck typing?
Polymorphism means one interface with many implementations. In Python it mostly comes from duck typing: if an object has the method you call, it works, whatever its class.
Pythonclass Dog: def speak(self): return "Woof" class Robot: def speak(self): return "Beep" for thing in [Dog(), Robot()]: print(thing.speak()) print(len("abc"), len([1, 2]), len({"a": 1}))Python has no overloading by signature; a second
defwith the same name replaces the first, so use default arguments orfunctools.singledispatch.What is the difference between
__new__and__init__?__new__creates and returns the object;__init__then initializes it and must returnNone.Pythonclass Point: def __new__(cls, *args): print("__new__ called") return super().__new__(cls) def __init__(self, x, y): print("__init__ called") self.x, self.y = x, y p = Point(1, 2) print(p.x, p.y)You override
__new__mainly to subclass immutable types likeintortuple, or for singletons. If it returns something that is not an instance of the class,__init__is skipped.Is a list defined in the class body shared between instances?
Pythonclass Basket: items = [] def add(self, x): self.items.append(x) a = Basket() b = Basket() a.add(1) b.add(2) print(a.items)items = []in the class body is one list shared by every instance, andself.items.append(x)mutates it, so both objects see both values. Create the list in__init__withself.items = []. An assignment toself.itemswould create an instance attribute; only in-place mutation leaks.What is the difference between
@staticmethodand@classmethod?A class method receives the class (
cls), so it can build instances and read class state; a static method receives nothing implicit and is a plain function in the class namespace.Pythonclass Date: def __init__(self, year, month, day): self.year, self.month, self.day = year, month, day @classmethod def from_string(cls, text): y, m, d = map(int, text.split("-")) return cls(y, m, d) @staticmethod def is_leap(year): return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) d = Date.from_string("2024-02-29") print(d.year, d.month, d.day, Date.is_leap(2024))With
cls,SubDate.from_string(...)returns aSubDate; a static method that hardcodesDate(...)could not.What is the difference between
__str__and__repr__?__str__is the readable form used byprint()andstr();__repr__is the unambiguous developer form used by the REPL,repr()and containers.Pythonclass User: def __init__(self, name): self.name = name def __repr__(self): return f"User(name={self.name!r})" def __str__(self): return self.name u = User("Asha") print(u) print(repr(u)) print([u])A list prints the
reprof its items, as the last line shows. If you implement only one, make it__repr__, becausestr()falls back to it.How do you create an abstract class or interface in Python?
Inherit from
abc.ABCand mark the required methods with@abstractmethod; a class with unimplemented abstract methods cannot be instantiated.Pythonfrom 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 print(Square(3).area()) try: Shape() except TypeError as e: print("TypeError:", e)Python has no
interfacekeyword, so an ABC with only abstract methods plays that role.typing.Protocolgives duck-typed interfaces without inheritance.What does the
@propertydecorator do?@propertyturns a method into an attribute read without parentheses, and its.setterruns on assignment, usually to validate. It replacesget_x()andset_x()methods.Pythonclass Temperature: def __init__(self, celsius): self.celsius = celsius @property def celsius(self): return self._celsius @celsius.setter def celsius(self, value): if value < -273.15: raise ValueError("below absolute zero") self._celsius = value @property def fahrenheit(self): return self._celsius * 9 / 5 + 32 t = Temperature(25) print(t.fahrenheit) try: t.celsius = -300 except ValueError as e: print("ValueError:", e)__init__assigns through the setter, so the validation also applies on creation.In a diamond hierarchy, in what order does
super()call the parents?Pythonclass A: def hi(self): return "A" class B(A): def hi(self): return "B" + super().hi() class C(A): def hi(self): return "C" + super().hi() class D(B, C): def hi(self): return "D" + super().hi() print(D().hi())Python resolves methods along the MRO, computed with C3 linearization; here it is
D, B, C, A, object(checkD.__mro__).super()means the next class in the MRO of the object's actual type, not the parent, sosuper()insideBcallsC.hiandAruns once. See inheritance.What are dataclasses in Python and when would you use one?
@dataclass(Python 3.7+) generates__init__,__repr__and__eq__from the annotated fields.frozen=Truemakes instances immutable and hashable, andorder=Trueadds comparisons.Pythonfrom dataclasses import dataclass, field @dataclass(frozen=True) class Point: x: int y: int @dataclass class Cart: owner: str items: list = field(default_factory=list) p = Point(1, 2) print(p, p == Point(1, 2)) c = Cart("Ravi") c.items.append("book") print(c)Mutable defaults need
field(default_factory=list);items: list = []raisesValueErrorwhen the class is defined, which guards against the mutable default argument trap.
OOPs in Python Interview Questions
Classes, inheritance and the dunder methods that make Python objects behave like built-ins.