2015-01-26 3 views
5

У меня есть класс дескриптора X здесь. Я пытаюсь использовать дескриптор X в другом классе YПочему методы дескриптора Python не вызываются при вызове с синтаксисом obj.x?

class X: 
    def __init__(self, value): 
     self.value = value 

    def __get__(self, instance, owner): 
     print('#### X.__get__ ####') 
     return self.value 

    def __set__(self, instance, value): 
     print('#### X.__set__ ####') 
     self.value = value 

class Y: 
    def __init__(self): 
     self.x = X(10) 

y = Y() 
print(y.x) 
y.x = 20 

Я надеялся, что заявление print(y.x) будет ссылаться x.__get__ и заявление y.x = 20 будет ссылаться x.__set__, но этого не происходит. Когда я запускаю вышеуказанную программу, я просто получаю этот вывод.

<__main__.X object at 0x7fc65f947950> 

Почему методы дескриптора не вызывались?

+0

@jonrsharpe Я не думаю, что с '__getattr__',' y.x' вызывается 'x .__ getattr__'. Вместо этого 'y.x' будет вызывать' y .__ getattr__'. Тем не менее, я пытаюсь вызывать 'x .__ getattr__' с' y.x', что должны делать дескрипторы. –

+0

Возможный дубликат [Динамическое добавление @property в python] (http://stackoverflow.com/questions/2954331/dynamically-adding-property-in-python) – jonrsharpe

+0

@martineau Спасибо. Починил это. –

ответ

3

Чтобы получить методы протокола дескриптора вызывается, необходимо поместить экземпляр дескриптора (X() в вашем случае) на Yкласса, а не на экземпляре. Это подробно описано в Descriptor HowTo Guide Раймондом Хеттингер:

Для объектов, машины в object.__getattribute__(), который трансформирует b.x в type(b).__dict__['x'].__get__(b, type(b)).

Обратите внимание, как b.x преобразуется в вызов дескриптора, полученного ДИКТ доступа type(b). Y класса должен выглядеть следующим образом:

class Y: 
    x = X(10) 

Однако, так как один экземпляр X будет использоваться всеми экземплярами Y, класс X дескриптора должен быть изменен, чтобы получить и установить значение от instance а чем от self.

+0

Другими словами, 'Y' должен выглядеть следующим образом:' class Y: \ nx = X (10) ' –

+0

@ Асадные модификации' X' также требуются, или все экземпляры 'Y' будут использовать один и тот же' x '. – jonrsharpe

+0

@jonrsharpe Они будут использовать один и тот же экземпляр 'X', но я предполагаю, что вы можете заставить его возвращать некоторый атрибут' instance' вместо 'self', так что возвращаемое значение будет уникальным для экземпляра' Y'. –

Смежные вопросы