Python 3 Deep Dive Part 4 Oop [top] -
The curriculum typically focuses on high-level mechanics that differentiate professional Python code from script-level code:
def area(self): return self.width * self.height
: Understanding the relationship between class objects and instance objects, including class-level data and function attributes. Methods and Binding
If you are creating millions of small instances, you can optimize memory usage by defining __slots__ . This tells Python not to use a dictionary, but instead allocate a fixed amount of space for a static set of attributes. python 3 deep dive part 4 oop
If you only need basic getter/setter logic, using @property is simpler than writing a full descriptor. Properties are the way to replace manual getter/setter methods, and the @property decorator is the recommended approach.
def deposit(self, amount): self.__balance += amount
class Shape(ABC): @abstractmethod def area(self): pass If you only need basic getter/setter logic, using
This distinction is key: if you want to completely control attribute assignment (validation, logging), you need a data descriptor.
Python supports multiple inheritance, allowing a class to inherit from more than one parent class. This introduces a structural vulnerability known as the , where a child class inherits from two parent classes that both share a common ancestor. The C3 Linearization Algorithm
class PositiveNumber: """A descriptor that enforces positive numeric values.""" def __init__(self, name): self._name = name def __get__(self, obj, objtype=None): if obj is None: return self return obj.__dict__.get(self._name, 0) Python supports multiple inheritance, allowing a class to
Prefixing an attribute with two underscores (e.g., __balance ) invokes name mangling. Python automatically changes __balance to _ClassName__balance inside the internal dictionary. This protects attributes from accidentally being overwritten during subclass inheritance, rather than acting as a true security wall. The Descriptor Protocol
dh = DataHolder("Alice") dh.age = 30 # Dynamically adding a new attribute print(dh.__dict__) # 'name': 'Alice', 'age': 30 print(DataHolder.__dict__) # Unchanged; class-level dict remains the same
Consider this classic diamond hierarchy:
By default, Python uses a dynamic dictionary ( __dict__ ) to store instance attributes. This allows you to add new attributes to an object on the fly, but it consumes a significant amount of RAM.
: Understanding the underlying mechanism of properties and how to create custom descriptors.