Имя свойства дескриптора в ООП в Python
В прошлых примерах имя ключа в __dict__
мы передавали в конструктор дескриптора:
Field('name'). Это неудобно:
одно и то же имя приходится писать дважды.
Python может сообщить дескриптору,
как его назвали в классе. Для этого
есть метод __set_name__. Его
вызывают один раз при создании класса,
когда дескриптор только привязывают
к имени.
Давайте перепишем дескриптор без аргумента в конструкторе:
class Field:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, obj, owner):
if obj is None:
return self
return obj.__dict__[self.name]
def __set__(self, obj, value):
obj.__dict__[self.name] = value
def __delete__(self, obj):
del obj.__dict__[self.name]
В классе достаточно указать один экземпляр дескриптора на каждое свойство:
class User:
name = Field()
surn = Field()
При определении класса Python вызовет
__set_name__ у каждого дескриптора
и передаст имя свойства. После этого
каждый дескриптор знает свой ключ
в __dict__.
Проверим запись и чтение:
user = User()
user.name = 'john'
user.surn = 'smit'
print(user.name)
print(user.surn)
Один и тот же класс Field можно
ставить на любое свойство: имя подставится
автоматически. Так проще собирать
классы, похожие на работу property,
но с общей логикой в одном дескрипторе.
Добавим проверку в __set__ уже
после __set_name__:
class NonEmpty:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, obj, owner):
if obj is None:
return self
return obj.__dict__[self.name]
def __set__(self, obj, value):
if len(value) > 0:
obj.__dict__[self.name] = value
else:
print(self.name + ' is incorrect')
class User:
name = NonEmpty()
surn = NonEmpty()
В сообщении об ошибке подставится
имя свойства, которое дескриптор
получил через __set_name__.
Перепишите класс Employee:
используйте дескриптор с __set_name__
для имени, зарплаты и возраста.
Сделайте отдельный дескриптор
AgeField с __set_name__
и проверкой возраста от 0
до 120 при записи.
Сделайте один общий дескриптор
Field с __set_name__,
__get__, __set__
и __delete__. Подключите его
ко всем свойствам Employee.