Descriptors in Python
The protocol properties are built on: __get__ and __set__ on a class attribute.
class Bounded:
def __init__(self, low, high):
self.low = low
self.high = high
def __set_name__(self, owner, name):
self.store = "_" + name
def __get__(self, instance, owner=None):
if instance is None:
return self
return getattr(instance, self.store)
def __set__(self, instance, value):
if not self.low <= value <= self.high:
raise ValueError(f"{value} outside {self.low}..{self.high}")
setattr(instance, self.store, value)
class Step:
stars = Bounded(0, 3)
step = Step()
step.stars = 3
print(step.stars)
How it works
__set_name__learns the attribute name it was assigned to.- One descriptor instance serves every instance of the owner.
- This is how properties, methods and slots all work underneath.
Keywords and builtins used here
BoundedStep__set_name__classdefgetattrifprintraisereturnselfsetattr
The run, in numbers
- Lines
- 26
- Characters to type
- 510
- Tokens
- 153
- Three-star pace
- 105 tpm
At the three-star pace of 105 tokens a minute, this run takes about 87 seconds.
Step 3 of 3 in Attributes & descriptors, step 34 of 53 in Pythonic Python.