#python #python-2.7 #class #getattr
#python #python-2.7 #класс #getattr
Вопрос:
При использовании дескрипторов данных при построении классов я столкнулся со странным поведением функции getattr в классе.
# this is a data descriptor
class String(object):
def __get__(self, instance, owner):
pass
def __set__(self, instance, value):
pass
# This defines a class A with 'dot' notation support for attribute 'a'
class A(object):
a = String()
obj = A()
assert getattr(A, 'a') is A.__dict__['a']
# This raises AssertionError
LHS возвращает пустую строку, в то время как RHS возвращает экземпляр String
. Я думал getattr
, что объект должен был получить значение для ключа внутри __dict__
. Как getattr
функция работает с объектом класса?
Комментарии:
1. Вы уверены, что он возвращает пустую строку, а не
None
?2. LHS точно возвращает пустую строку ? Как я пытаюсь, он возвращается
None
. А почему бы и нет? Вы говорите об этом в дескрипторе!3. Кстати:
A.a
это не то же самое, чтоA.__dict__['a']
. Только первый запускает «весь механизм атрибутов».4. So
getattr(obj, 'a')
и getattr(A, ‘a’)` чем-то похожи? Оказывается, в моем случае дескриптор имел значение по умолчанию » set». Итак, единственный способ восстановить объект дескриптора — это проверить класс__dict__
напрямую?
Ответ №1:
getattr(A, 'a')
так называется запуск протокола дескриптора, даже для классов String.__get__(None, A)
.
Это возвращается None
, потому что ваш String.__get__()
метод не имеет явного return
оператора.
Из дескриптора Как:
Для классов механизм, в
type.__getattribute__()
котором преобразуетсяB.x
вB.__dict__['x'].__get__(None, B)
.
getattr(A, 'a')
это просто динамический A.a
отсюда, поэтому A.__dict__['x'].__get__(None, A)
выполняется, поэтому вы не получаете то же самое, A.__dict__['x']
что и .
Если вы ожидали, что он вернет сам объект дескриптора, вам придется сделать это явно; instance
None
в этом случае будет установлено значение:
class String(object):
def __get__(self, instance, owner):
if instance is None:
return self
def __set__(self, instance, value):
pass
Это то, что property
делает объект дескриптора.
Обратите внимание, что owner
аргумент to descriptor.__get__
является необязательным; если он не установлен, вы должны использовать type(instance)
вместо него.
Ответ №2:
getattr(A, 'a')
то же A.a
самое, что и . Это вызывает соответствующий дескриптор, если он присутствует. Таким образом, он предоставляет значение, представленное дескриптором, которое является None
.