Arka Roy

Quality: Python 3 Deep Dive Part 4 Oop High

class ValidatePlugin(Plugin): name = "validator"

def process(self, data):
    if "id" not in data:
        raise ValueError("Missing ID")
    return data

This design is extensible, testable, and respects LSP, OCP (Open/Closed), and DIP (Dependency Inversion).


Python supports multiple inheritance. Unlike C++, Python resolves method conflicts with the C3 Linearization (Method Resolution Order). Access it via ClassName.__mro__.

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

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

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

class D(B, C): pass

High-quality classes behave like native types. If you have a mathematical object, it should support + and -.

The Golder Rule: Always return a new instance (immutability) from these methods unless you are overriding += (__iadd__).

def __add__(self, other):
    if isinstance(other, Vector2D):
        return Vector2D(self.x + other.x, self.y + other.y)
    return NotImplemented  # Crucial: allows Python to try other.__radd__

Why descriptors matter for high-quality code:

Without descriptors, you’d repeat property boilerplate everywhere.


The dynamic nature of __dict__ consumes significant memory. If you are creating millions of instances, you can optimize memory by using __slots__. This tells Python to use a static array for attributes instead of a dynamic dictionary.

class Optimized:
    __slots__ = ['x', 'y']  # Fixed attribute set
def __init__(self, x, y):
        self.x = x
        self.y = y
o = Optimized(1, 2)
o.z = 3  # Raises AttributeError! Cannot add new attributes.

Trade-off: You save memory but lose the ability to dynamically add attributes.


Abstract base classes define interfaces that subclasses must implement. python 3 deep dive part 4 oop high quality

from abc import ABC, abstractmethod

class Stream(ABC): @abstractmethod def read(self): pass

@abstractmethod
def write(self, data):
    pass

class FileStream(Stream): def read(self): return "data" def write(self, data): print(f"writing data")

Why MRO matters: It determines which method is called when multiple parents define the same method. It also affects super(). This design is extensible, testable, and respects LSP,

High-quality tip: Avoid complicated multiple inheritance (diamonds). If you need mixins, keep them small and method names unique.