Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗pyOpDsNm 59 of 174 menu
◀ ▶

Имя свойства дескриптора в ООП в 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.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить