Descriptor Protocol (__get__, __set__, __delete__)
1Concept
A Descriptor is an object attribute with 'binding behavior' defined by the Descriptor protocol: `__get__()`, `__set__()`, and `__delete__()`. Descriptors power Python's properties, bound methods, `classmethod`, and ORM database columns.
2Architecture Diagram
Attribute Access (obj.age) ---> Intercepted by Descriptor.__get__() Attribute Assign (obj.age = 25) ---> Intercepted by Descriptor.__set__()
3Code Example
Python 3.12
class PositiveInteger:
def __init__(self, name: str):
self.name = name
def __get__(self, instance, owner):
if instance is None: return self
return instance.__dict__.get(self.name, 0)
def __set__(self, instance, value):
if not isinstance(value, int) or value <= 0:
raise ValueError(f"{self.name} must be a positive integer!")
instance.__dict__[self.name] = value
class ProductInventory:
stock_count = PositiveInteger("stock_count")
p = ProductInventory()
p.stock_count = 50
print(f"Validated Stock Count: {p.stock_count}")
try:
p.stock_count = -10
except ValueError as e:
print(f"Descriptor Validation Blocked: {e}")4Expected Output
Validated Stock Count: 50 Descriptor Validation Blocked: stock_count must be a positive integer!
5Key Takeaways
- ✓Data Descriptors implement `__set__` or `__delete__` and take precedence over instance `__dict__`.
- ✓Non-Data Descriptors implement only `__get__` (e.g. standard methods).
- ✓Use `__set_name__(self, owner, name)` (PEP 487) to capture field names automatically.