Почему метод дескриптора python __get__ принимает класс владельца как arg?
Почему метод __get__
в дескрипторе python принимает класс владельца как третий аргумент? Можете ли вы привести пример использования?
Первый аргумент (self
) самоочевиден, второй (instances
) имеет смысл в контексте типично отображаемого шаблона дескриптора (ex to follow), но я никогда не видел третьего (owner
). Может ли кто-нибудь объяснить, что используется для этого?
Просто в качестве справки и облегчения ответов это типичное использование дескрипторов, которые я видел:
class Container(object):
class ExampleDescriptor(object):
def __get__(self, instance, owner):
return instance._name
def __set__(self, instance, value):
instance._name = value
managed_attr = ExampleDescriptor()
Учитывая, что доступно instance.__class__
, все, что я могу представить, это то, что явно передача класса имеет непосредственное отношение к дескриптору из класса вместо экземпляров (ex Container.managed_attr
). Тем не менее, я не понимаю, что можно было бы сделать в __get__
в этой ситуации.
Ответы
Ответ 1
owner
используется, когда атрибут получает доступ из класса вместо экземпляра класса, и в этом случае instance
будет None
.
В вашем примере попытка выполнить что-то вроде print(Container.managed_attr)
завершится неудачно, потому что instance
есть None
, поэтому instance._name
поднимет AttributeError
.
Вы можете улучшить это поведение, проверив, есть ли instance is None
, и может быть полезно для ведения журнала или создания более полезного исключения, чтобы узнать, к какому классу принадлежит дескриптор, следовательно, атрибуту owner
. Например:
def __get__(self, instance, owner):
if instance is None:
# special handling for Customer.managed_attr
else:
return instance._name
Ответ 2
Когда доступ к дескриптору из класса, instance
будет None
. Если вы не учли эту ситуацию (как не показано в примере вашего кода), тогда в этой точке произойдет ошибка.
Что вы должны делать в этом случае? Что бы ни было разумно.;) Если ничего другого не имеет смысла, вы можете следовать примеру property
и возвращать сам дескриптор при доступе к нему из класса.
Ответ 3
Да, он используется так, чтобы дескриптор мог видеть Контейнер при доступе к контейнеру .managed_attr. Вы можете вернуть некоторый объект, подходящий для использования, например, метод unbound, когда дескрипторы используются для реализации методов.