Slide 72
Slide 72 text
class ReusableDescriptor:
def set_assigned_name(self, name):
self.name = name
class PositiveInteger(RecusableDescriptor):
def __set__(self, instance, value):
if type(value) is not int: raise ValueError(f"value should be int, but {value}")
if value < 0: raise ValueError(f"value souldn't be negative")
instance.__dict__[self.name] = value
def __get__(self, instance, owner):
if not instance: return self
try:
return instance.__dict__[self.name]
except KeyError:
raise AttributeError()
class ReusableDescriptorMetaclass(type):
def __new__(meta, name, bases, class_dict):
for key, item in class_dict.items():
if isinstance(item, ReusableDescriptor):
item.set_assigned_name(key)
return type.__new__(meta, name, bases, class_dict)
https://github.com/tsuyukimakoto/pyconjp2020/blob/master/notebook/04.descriptor_metaclass_01.ipynb
class Spam(metaclass=ReusableDescriptorMetaclass):
value1 = PositiveInteger()
value2 = PositiveInteger()
>>> spam1 = Spam()
>>> spam1.value1 = 10
>>> spam1.value2 = 20
>>> spam2 = Spam()
>>> spam2.value1 = 100
>>> spam2.value2 = 200
>>> print(
spam1.value1, spam1.value2,
spam2.value1, spam2.value2)
10 20 100 200
MetaclassͰରԠ͢Δ໊લΛઃఆ͢Δ