在python中嵌套描述符/装饰器 [英] Nesting descriptors/decorators in python
问题描述
当我尝试嵌套描述符/装饰器时,我很难理解会发生什么.我使用的是 python 2.7.
I'm having a hard time understanding what happens when I try to nest descriptors/decorators. I'm using python 2.7.
例如,让我们采用以下property
和classmethod
的简化版本:
For example, let's take the following simplified versions of property
and 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
内部描述符 MyClassMethod
的 __get__
方法没有被调用.不知道为什么,我尝试加入(我认为是)一个无操作描述符:
The __get__
method of the inner descriptor MyClassMethod
is not getting called.
Failing to figure out why, I tried throwing in (what I think is) a no-op descriptor:
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)
尝试在嵌套中使用无操作描述符/装饰器:
Trying to use the no-op descriptor/decorator in nesting:
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
无效.
I don't understand why B().prop1
works and B().prop2
does not.
问题:
- 我做错了什么?为什么我收到
object is not callable
错误? - 正确的方法是什么?例如在重用
MyClassMethod
和MyProperty
(或classmethod
和时定义
)MyClassProperty
的最佳方法是什么?属性
- What am I doing wrong? Why am I getting a
object is not callable
error? - What's the right way? e.g. what is the best way to define
MyClassProperty
while re-usingMyClassMethod
andMyProperty
(orclassmethod
andproperty
)
推荐答案
如果您让 MyProperty
将描述符协议应用于其包装对象,您就可以使您的代码工作:
You can make your code work if you make MyProperty
apply the descriptor protocol to its wrapped object:
class MyProperty(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, objtype=None):
print('IN MyProperty.__get__')
try:
return self.fget.__get__(obj, objtype)()
except AttributeError: # self.fget has no __get__ method
return self.fget(obj)
现在您的示例代码有效:
Now your example code works:
class A(object):
@MyProperty
@MyClassMethod
def klsproperty(cls):
return 555
print(A.klsproperty)
输出为:
IN MyProperty.__get__
IN MyClassMethod.__get__
555
这篇关于在python中嵌套描述符/装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!