Study notes · 11% of the exam

Classes, Inheritance and the MRO

Know how attribute lookup, method binding and the MRO really work, and how dataclasses, enums, ABCs and class-creation hooks build on them.

Key points

  1. 1

    Class attributes are shared; assigning through an instance (even with +=) creates an instance attribute that shadows the class one.

  2. 2

    Functions become bound methods via the descriptor protocol; every access creates a new bound method, so compare with ==, not is.

  3. 3

    The MRO comes from C3 linearization: subclasses before bases, declared base order preserved, or a TypeError if impossible.

  4. 4

    super() means the next class in the MRO of the instance, so cooperative __init__ methods must forward **kwargs.

  5. 5

    dataclass rejects mutable defaults, orders fields with defaults last, removes __hash__ unless frozen, and builds a new class for slots=True.

  6. 6

    Enum members are singletons; duplicate values create aliases, and plain Enum never equals its raw value (IntEnum and StrEnum do).

  7. 7

    Prefer __init_subclass__ and class decorators to metaclasses; reach for a metaclass only to control __call__, __prepare__ or class creation itself.

Common traps

  • A class that defines __eq__ without __hash__ becomes unhashable.

  • Implicit dunder calls such as len(proxy) bypass __getattr__, so delegation proxies must define those methods explicitly.

  • Zero-argument super() needs the compiler-made __class__ cell, so it fails in functions attached after class creation and in @dataclass(slots=True) methods on 3.13.

Test yourself on Classes, Inheritance and the MRO

Ten questions, with the answer and explanation after each one.