class CoordinateValue: def __init__(self, name): self.storage_name = '_' + name def __set__(self, instance, value): setattr(instance, self.storage_name, int(value)) def __get__(self, instance, owner_class): ''' if instance is None: print('__get__ called from class') else: print(f'__get__ called, instance={instance}, owner_class={owner_class}') ''' if instance is None: return self return getattr(instance, self.storage_name, None) class Point: x = CoordinateValue('x') y = CoordinateValue('y') def test_point(): p1 = Point() p1.x = 100 p1.y = 5 print(p1.x, p1.y) print(p1.__dict__) p2 = Point() p2.x = 2 p2.y = 3 print(p2.x, p2.y) print(p2.__dict__) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # __set_name__ # Метод срабатывает в процессе создания класса и все! class StringValidation: def __init__(self, min_length): self.min_length = min_length def __set_name__(self, owner, name): print(f'__set_name__ called: owner={owner}, attr_name={name}') self.attribute_name = name def __get__(self, instance, owner_class): if instance is None: return self else: print(f'calling __get__ for {self.attribute_name}') return instance.__dict__.get(self.attribute_name, None) # key = '_' + self.attribute_name # return getattr(instance, key, None) def __set__(self, instance, value): if not isinstance(value, str): raise ValueError(f'В атрибут {self.attribute_name} можно \ сохранять только строки.') if len(value) < self.min_length: raise ValueError(f'Длина атрибута {self.attribute_name} должна \ быть не меньше {self.min_length} символов') key = '_' + self.attribute_name # setattr(instance, key, value) instance.__dict__[self.attribute_name] = value class Person: name = StringValidation(5) last_name = StringValidation(7) def main(): p = Person() p.name = 'Michail' p.last_name = 'Lermontov' print(p.name, p.last_name) try: p.name = 'M.' except ValueError as ex: print(ex) print(p.name, p.last_name) if __name__ == '__main__': main()