2014-01-04 3 views
2

Я имитирую некоторые данные, используя дескриптор python.Когда будет вызван метод дескриптора python?

class Number: 
    def __init__(self): 
     self.num = 0 

    def __get__(self, instance, obj): 
     print("is getting number") 
     return self.number 

    def __set__(self, instance, value): 
     print("is setting number") 
     self.number = value 

    def __str__(self): 
     return str(self.number) 

num = Number() 
num = 2 
print(num + 7) 

выход:

9 

Это кажется успешно вызвать метод __get__ и __set__, но я не знаю, почему нет никакого вывода сообщений is getting number или is setting number.

Я не уверен, вызывает ли python метод дескриптора или нет.

Мой вопрос в том, когда будет называться дескрипторный метод?

Я Резюме мое происхождение догадка:

  1. получить

    • При использовании obj.prop, чтобы получить собственность и пропеллер еще один объект, который устанавливает дескриптор
    • когда высчитывает некоторое выражение должно получить значение например a + 5. Если a имеет дескриптор и вызывается __get__
    • Если объект имитирует функцию, то вызовет __get__, чтобы сначала получить тело функции, а затем вызвать __call__ для запуска функции.
  2. набор

    • Когда объект появится в левой части оператора присваивания, такие как obj = 5

Но я должен быть неправильным, я нужен кто-то сказать мне правильная концепция.

ответ

8

Ваши дескрипторы не вызываются, и нет никакого способа написать дескриптор или что-то еще, чтобы делать то, что вам кажется нужным.

Когда вы num = 2, вы выбросили свой Number объект и установить переменную num к обычному номеру 2. Когда вы добавляете 7 к нему, он равен 9, потому что это просто обычный номер. Ваш класс Number не участвует ни в коем случае.

Дескрипторы позволяют вам подключаться к тому, что происходит, когда вы делаете obj.foo или obj.foo = blah. В этих случаях это foo, который является дескриптором, а не obj, и дескриптор работает только тогда, когда он является атрибутом. Невозможно изменить то, что происходит, когда вы делаете obj = blah, где obj - это голое имя (т. Е. Нет точек или []). В связи с вашей догадке:

  1. получить

    • Когда польза OBJ.prop для получения свойства и пропеллера - другой объект, который устанавливает дескриптор
      • Да, в основном. Когда вы делаете obj.prop и prop является дескриптором, то его __get__ называется. Обратите внимание, что prop является дескриптором, а не obj.
    • при вычислении некоторого выражения должно получить значение, например a + 5. Если это есть дескриптор и будет называть __get__
      • Нет, вы можете переопределить такое поведение с помощью магического метода __add__, или аналогичных методов для других операторов
    • Если объект имитации функции будет вызывать __get__, чтобы получить функцию сначала, затем вызовите __call__ для запуска функции.
      • Я не понимаю, что это значит, но я думаю, что нет. Если объект определяет __call__, то obj() называет его __call__ без привлечения какого-либо дескриптора.
  2. набор

    • Когда объект появится в левой части оператора присваивания, такие как obj = 5
      • No. Только когда дескриптор доступен как атрибут на левая сторона, как в obj.prop = 5, где prop - дескриптор.

Суть заключается в том, что дескрипторы работают только тогда, когда они являются атрибутами классов. Просто создание «голого» дескриптора, как вы пытаетесь сделать (т. Е. Делать obj = SomeDescriptorClass()), ничего не сделает.

Кроме того, в качестве примечания стороны дескрипторы работают только при наборе классов нового стиля. Если вы используете Python 2, это означает, что класс, содержащий дескриптор, должен наследовать от object.

+0

спасибо. так, дескриптор происходит только в свойстве объекта? – FreedomKnight

+0

Я объясняю, что я сказал «эмулировать функцию». В официальном [doc] (http://docs.python.org/3/howto/descriptor.html#static-methods-and-class-methods). эмуляция использует '__get__' для эмуляции' @ classmethod'. поэтому, я думаю, вызов функции вызовет сначала '__get__'. – FreedomKnight

+0

@FreedomKnight: Да. Если вы используете Google, вы можете найти множество других вопросов о дескрипторах на этом сайте и описаниях в Интернете. – BrenBarn

3

num = 2num a int, но не Number больше.

Дескриптор должен быть атрибутом экземпляра и унаследован от object.

class Number(object): 
    def __init__(self): 
     self.num = 0 

    def __get__(self, instance, obj): 
     print("is getting number") 
     return self.num 

    def __set__(self, instance, value): 
     print("is setting number") 
     self.num = value 

    # no need to define this for descriptor 
    def __str__(self): 
     return str(self.num) 

class A(object): 
    num = Number() 

n = A() 
n.num = 5 
print(n.num + 7) 
Смежные вопросы