Python 3 Deep Dive Part 4 Oop High Quality
Descriptors are the mechanism behind property(), classmethod(), and super(). They allow you to define reusable attribute logic.
A descriptor is a class that implements any of __get__, __set__, or __delete__.
When to NOT use metaclasses:
Almost always. Class decorators and __init_subclass__ (Python 3.6+) solve 99% of metaclass use cases more simply. python 3 deep dive part 4 oop high quality
__init_subclass__ example:
class Base:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
print(f"Subclass cls.__name__ created")
class Child(Base):
pass
Python has no real access control. We rely on naming conventions: When to NOT use metaclasses:
Almost always
Name mangling example:
class Foo:
def __init__(self):
self.__secret = 42
def get_secret(self):
return self.__secret
f = Foo()
print(f._Foo__secret) # 42 – still accessible, but harder to accidentally access
High-quality wisdom: Do not overuse __ (double underscore). It breaks subclassing. Use _ for internal attributes and trust other developers. Python is a "consenting adults" language.
Implement these to integrate with language features:
| Feature | Dunder Method(s) |
|-----------------------|--------------------------------------|
| Object representation | __repr__, __str__ |
| Container protocol | __len__, __getitem__, __setitem__ |
| Callable objects | __call__ |
| Context manager | __enter__, __exit__ |
| Arithmetic ops | __add__, __sub__, __mul__, etc.|
| Hashing / equality | __hash__, __eq__ | Name mangling example : class Foo: def __init__(self):
Example – a sequence‑like class:
class ShoppingCart:
def __init__(self):
self._items = []
def __len__(self):
return len(self._items)
def __getitem__(self, index):
return self._items[index]
def __setitem__(self, index, value):
self._items[index] = value
