Excellent.
DAY 19 is advanced Python OOP — this is where you cross from “can use classes” to understands how Python builds classes at runtime.

Many senior interviews are decided right here.


🧠 DAY 19 — OOP Internals

(MRO, type, Metaclasses & __new__)


🔑 CORE IDEA OF DAY 19

In Python, classes are created at runtime by a metaclass (type).
Inheritance is resolved dynamically using MRO (C3 linearization).

This is not theory — this explains real bugs and real interview questions.


1️⃣ The Fundamental Truth (Read Twice)

class A:
    pass

This is equivalent to:

A = type("A", (), {})

🧠 class is syntax sugar.
Python executes it like a function call.


2️⃣ The Object Creation Chain (CRITICAL)

When you write:

a = A()

Python does:

  1. Call A.__new__(A)
  2. Allocate memory → instance
  3. Call A.__init__(instance)
  4. Return instance

⚠️ __new__ creates
⚠️ __init__ initializes


3️⃣ __new__ vs __init__ (INTERVIEW FAVORITE)

class A:
    def __new__(cls):
        print("new")
        return super().__new__(cls)

    def __init__(self):
        print("init")

a = A()

Output:

new
init

Key rules:

  • __new__ is a class method
  • Must return an instance
  • If __new__ doesn’t return instance → __init__ is skipped

4️⃣ When Do You Actually Need __new__?

Use cases:

  • Immutable types (int, tuple)
  • Singleton pattern
  • Object caching
  • Controlling instance creation

Example (singleton):

class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

5️⃣ Metaclasses — What They REALLY Are

A metaclass is a class that creates classes.

Default metaclass:

type

Relationship:

object ← instance
type   ← class
type(A) is type        # True

🧠 Classes are instances of type.


6️⃣ Metaclass Execution Flow

When Python sees:

class A(B, C):
    x = 10

It does:

  1. Collect class body into a dict
  2. Determine metaclass
  3. Call metaclass(name, bases, dict)
  4. Create class object

7️⃣ Simple Metaclass Example (Understand, Don’t Fear)

class Meta(type):
    def __new__(cls, name, bases, dct):
        print("Creating class:", name)
        return super().__new__(cls, name, bases, dct)

class A(metaclass=Meta):
    pass

Output:

Creating class: A

⚠️ Metaclasses run at class creation time, not instance creation.


8️⃣ Method Resolution Order (MRO) — VERY IMPORTANT

MRO defines where Python looks for methods.

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

print(D.__mro__)

Output:

(D, B, C, A, object)

9️⃣ Why Python Uses C3 Linearization

Python’s MRO algorithm:

  • Ensures consistent order
  • Prevents ambiguity
  • Respects inheritance hierarchy

Rules:

  1. Child before parents
  2. Left-to-right order
  3. No class appears twice

🧠 This avoids the “diamond problem”.


🔟 Diamond Problem (Classic Interview)

class A:
    def f(self): print("A")

class B(A):
    def f(self): print("B")

class C(A):
    def f(self): print("C")

class D(B, C):
    pass

D().f()

Output:

B

Why?

  • MRO → D → B → C → A → object
  • First f found in B

11️⃣ super() Is NOT Parent (BIG MYTH)

super()

Means:

“Next class in MRO”

Not:

“Parent class”

This matters in multiple inheritance.


12️⃣ super() in Cooperative Multiple Inheritance

class A:
    def f(self):
        print("A")

class B(A):
    def f(self):
        print("B")
        super().f()

class C(A):
    def f(self):
        print("C")
        super().f()

class D(B, C):
    def f(self):
        print("D")
        super().f()

D().f()

Output:

D
B
C
A

🧠 This only works because of MRO cooperation.


13️⃣ Visual: MRO & Metaclass Flow

Image
Image
Image
Image

🔥 INTERVIEW TRAPS (DAY 19)

Q1

class A: pass
print(type(A))

<class 'type'>


Q2

class A:
    def __new__(cls):
        return None

a = A()
print(a)

None
(__init__ never runs)


Q3

Why Python discourages deep inheritance?

✔ MRO complexity
✔ Hard reasoning
✔ Composition cleaner


🧠 DAY 19 MENTAL CHECKLIST

When dealing with advanced OOP:

  1. Who creates this object?
  2. Is this class or instance time?
  3. What does MRO say?
  4. Does super() follow MRO?
  5. Is metaclass overkill here?

📝 DAY 19 ASSIGNMENT (MANDATORY)

1️⃣ Predict output (NO RUNNING):

class A:
    def f(self): print("A")

class B(A):
    def f(self): print("B")

class C(A):
    def f(self): print("C")

class D(C, B):
    pass

D().f()

2️⃣ Explain clearly:

  • Difference between __new__ and __init__
  • Why super() depends on MRO

3️⃣ Interview design question:

When would you use a metaclass instead of a decorator?


🔜 DAY 20 PREVIEW

DAY 20 — Inheritance, Composition & Mixins (Real Design Decisions)

You’ll learn:

  • When inheritance is wrong
  • How mixins actually work
  • Pythonic class design patterns
  • Interview-level design tradeoffs

When ready, say 👉 “START DAY 20”