CTCaliberTek
Interview Questions

Python OOP and Magic Methods Interview Questions and Answers

15 questions on classes, inheritance, MRO, dunder methods, properties, dataclasses, abstract classes, and duck typing.

  1. 1. How do classes and objects work in Python?

    A class is a blueprint defined with class. Calling it creates an instance, and __init__ initializes the instance's attributes. Attributes assigned on self belong to the instance; attributes defined in the class body are shared by all instances.

    class Dog:
        species = 'canine'            # class attribute
        def __init__(self, name):
            self.name = name          # instance attribute
        def speak(self):
            return self.name + ' says woof'
  2. 2. What is the difference between __init__ and __new__?

    __new__ creates and returns the new instance (it is a static method receiving the class), and __init__ then initializes it. You rarely override __new__, except for immutable types, singletons, and some metaclass patterns.

  3. 3. What is the difference between __str__ and __repr__?

    __str__ returns a readable description for end users and is used by print and str(). __repr__ returns an unambiguous developer-oriented representation, ideally one that could recreate the object, and is used in the shell and by debuggers. If only __repr__ is defined, it is also used as the fallback for str().

  4. 4. What are instance methods, class methods, and static methods?

    Instance methods receive the instance (self). A class method, marked @classmethod, receives the class (cls) and is often used for alternative constructors. A static method, marked @staticmethod, receives neither and is just a function placed in the class namespace for organization.

    class Date:
        def __init__(self, y, m, d):
            self.y, self.m, self.d = y, m, d
        @classmethod
        def from_string(cls, text):
            y, m, d = map(int, text.split('-'))
            return cls(y, m, d)
  5. 5. How does inheritance and method resolution order (MRO) work?

    A class can inherit from several parents. Python decides which method to call using the C3 linearization order, visible in ClassName.__mro__: subclasses come before their parents, and parent order is preserved. super() follows that order, not just the immediate parent, which is what makes cooperative multiple inheritance work.

  6. 6. What does super() do?

    It returns a proxy that delegates method calls to the next class in the MRO. The usual use is calling the parent initializer: super().__init__(...). In multiple inheritance it enables every class in the chain to run its part.

  7. 7. What is duck typing?

    Python cares about what an object can do, not its declared type: if it has the methods you call, it works. If it walks like a duck and quacks like a duck, treat it as a duck. This is why any object with a read method works as a file-like object. Protocols and type hints can describe the expected behavior for static checkers.

  8. 8. What are properties, and why use @property?

    A property lets you expose a method as an attribute, so you can add validation or computation later without changing how callers use the class.

    class Circle:
        def __init__(self, radius):
            self.radius = radius
        @property
        def radius(self):
            return self._radius
        @radius.setter
        def radius(self, value):
            if value < 0:
                raise ValueError('radius must be non-negative')
            self._radius = value
  9. 9. How do you implement private attributes in Python?

    Python has no true private members. By convention a single leading underscore (_name) means internal use. A double leading underscore (__name) triggers name mangling, which prevents accidental clashes in subclasses but is not real security. Document intent and rely on convention.

  10. 10. What are dunder (magic) methods? Give examples.

    Special methods with double underscores that let your objects work with language features. Examples: __len__ for len(), __getitem__ for indexing, __iter__ and __next__ for iteration, __eq__ and __lt__ for comparison, __add__ for +, __enter__ and __exit__ for with statements, __call__ to make an instance callable, and __hash__ to use it as a dictionary key.

  11. 11. How do __eq__ and __hash__ relate?

    Objects that compare equal must have the same hash. If you define __eq__ without __hash__, Python sets __hash__ to None and the objects become unhashable, so they cannot be set members or dictionary keys. Define both, and base the hash on immutable fields.

  12. 12. What are dataclasses?

    The dataclass decorator (Python 3.7 and newer) generates __init__, __repr__, __eq__, and optionally ordering, from annotated fields. Options include frozen=True for immutability, slots=True (3.10 and newer), and field(default_factory=list) for mutable defaults.

    from dataclasses import dataclass, field
    
    @dataclass
    class Order:
        id: int
        items: list[str] = field(default_factory=list)
  13. 13. What is an abstract base class?

    A class that cannot be instantiated and declares methods that subclasses must implement, using the abc module. It enforces an interface: instantiating a subclass that misses an abstract method raises TypeError.

    from abc import ABC, abstractmethod
    
    class Shape(ABC):
        @abstractmethod
        def area(self) -> float: ...
  14. 14. What is __slots__?

    Defining __slots__ in a class tells Python to store attributes in a fixed layout instead of a per-instance dictionary. It reduces memory for programs that create millions of small objects and blocks adding arbitrary attributes, at the cost of flexibility.

  15. 15. Composition or inheritance: which do you prefer?

    Prefer composition: build objects out of other objects they use, which keeps coupling low and avoids fragile deep hierarchies. Use inheritance for true is-a relationships and for sharing behavior in a controlled way, such as abstract base classes or mixins.

Interview Tips

  • Show that you know when to use a dataclass instead of writing boilerplate by hand.
  • Be ready to explain the MRO of a diamond inheritance example.
  • Link magic methods to the built-in features they power, such as len, with, and iteration.