Мне трудно понять, что происходит, когда я пытаюсь вложить дескрипторы/декораторы. Я использую питон 2.7.
Например, возьмем следующие упрощенные версии property
и classmethod
:
class MyProperty(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, objtype=None):
print 'IN MyProperty.__get__'
return self.fget(obj)
class MyClassMethod(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
print 'IN MyClassMethod.__get__'
def f(*args, **kwargs):
return self.f(objtype, *args, **kwargs)
return f
Попытка вложить их:
class A(object):
# doesn't work:
@MyProperty
@MyClassMethod
def klsproperty(cls):
return 555
# works:
@MyProperty
def prop(self):
return 111
# works:
@MyClassMethod
def klsmethod(cls, x):
return x**2
% print A.klsproperty
IN MyProperty.__get__
...
TypeError: 'MyClassMethod' object is not callable
Метод __get__
внутреннего дескриптора MyClassMethod
не вызывается. Не сумев понять, почему, я попытался добавить (как мне кажется) недействующий дескриптор:
class NoopDescriptor(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
print 'IN NoopDescriptor.__get__'
return self.f.__get__(obj, objtype=objtype)
Попытка использовать дескриптор/декоратор no-op во вложении:
class B(object):
# works:
@NoopDescriptor
@MyProperty
def prop1(self):
return 888
# doesn't work:
@MyProperty
@NoopDescriptor
def prop2(self):
return 999
% print B().prop1
IN NoopDescriptor.__get__
IN MyProperty.__get__
888
% print B().prop2
IN MyProperty.__get__
...
TypeError: 'NoopDescriptor' object is not callable
Я не понимаю, почему B().prop1
работает, а B().prop2
нет.
Вопросы:
- Что я делаю не так? Почему я получаю ошибку
object is not callable
? - Как правильно? например как лучше всего определить
MyClassProperty
при повторном использованииMyClassMethod
иMyProperty
(илиclassmethod
иproperty
)
@MyProperty
создает что-то, что работает как атрибут data, а не как метод, поэтому вы не можете вложить его в дескриптор метода. Это интуитивное понимание заводит вас далеко; полная история в ответе Иседева. - person abarnert   schedule 23.03.2013