Что такое дескриптор и как на нём построены property и методы?
- Как работает @property внутри?
- Чем data descriptor отличается от non-data descriptor?
Дескриптор — объект в атрибуте класса, у которого есть __get__ (и, возможно, __set__, __delete__). При обращении obj.attr Python вызывает эти методы вместо простого чтения. На дескрипторах построены property, методы (функции — дескрипторы), staticmethod, classmethod, __slots__.
- Data descriptor (есть __set__ или __delete__) важнее словаря экземпляра
- Non-data (только __get__) уступает словарю экземпляра — так методы можно перекрыть
- __set_name__ сообщает дескриптору имя атрибута
А ещё Применение: валидация полей, ленивые атрибуты, ORM-поля (Django, SQLAlchemy)
Подробно
Порядок поиска obj.x:
- data-дескриптор в классе (и его предках) — вызвать его
__get__; obj.__dict__["x"];- non-data дескриптор или обычный атрибут класса.
Свой дескриптор — валидация:
class Positive:
def __set_name__(self, owner, name):
self.name = "_" + name
def __get__(self, obj, objtype=None):
return getattr(obj, self.name)
def __set__(self, obj, value):
if value <= 0:
raise ValueError("должно быть > 0")
setattr(obj, self.name, value)
class Order:
qty = Positive()
def __init__(self, qty): self.qty = qty
Методы. Функция в классе — non-data дескриптор: obj.method через __get__ возвращает связанный метод, подставляющий obj как self. staticmethod возвращает функцию без связывания, classmethod — связывает с классом.
property — data-дескриптор, вызывающий заданные геттер, сеттер, делитер.
Ленивое вычисление: functools.cached_property — non-data дескриптор: первый вызов кладёт результат в __dict__ экземпляра, и дальше словарь перекрывает дескриптор.
Что хотят услышать
- Протокол __get__, __set__, __delete__.
- Data и non-data, порядок поиска.
- Что на них построено.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Объект в атрибуте экземпляра с методом __call__; non-data дескриптор важнее словаря экземпляра
- ✗property реализован без дескрипторов, на уровне интерпретатора
- ✓Объект в атрибуте класса с __get__ (и, возможно, __set__); на них построены property и методы
- ✗Дескриптором может быть только функция, объявленная через def
Что спросят дальше
Разбор темы
- Модель данных — создание объектов, атрибуты и дескрипторы
__new__ и __init__, согласование __eq__ и __hash__, __getattr__ и __getattribute__, дескрипторы и __slots__.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.