[英]How does this Python decorator work?
I was looking at some lazy loading property decorators in Python and happened across this example ( http://code.activestate.com/recipes/363602-lazy-property-evaluation/ ): 我在Python中查看了一些延迟加载属性装饰器,并且发生在这个例子中( http://code.activestate.com/recipes/363602-lazy-property-evaluation/ ):
class Lazy(object):
def __init__(self, calculate_function):
self._calculate = calculate_function
def __get__(self, obj, _=None):
if obj is None:
return self
value = self._calculate(obj)
setattr(obj, self._calculate.func_name, value)
return value
# Sample use:
class SomeClass(object):
@Lazy
def someprop(self):
print 'Actually calculating value'
return 13
o = SomeClass()
o.someprop
o.someprop
My question is, how does this work? 我的问题是,这是如何工作的? My understanding of decorators is that they must be callable (so either a function or a call that implements
__call__
), but Lazy
here clearly is not and if I try Lazy(someFunc)()
it raises an exception as expected. 我对装饰器的理解是它们必须是可调用的(所以函数或实现
__call__
),但是Lazy
在这里显然不是,如果我尝试Lazy(someFunc)()
它会按预期引发异常。 What am I missing? 我错过了什么?
When an attribute named someprop
is accessed on instance o
of class SomeClass
, if SomeClass
contains a descriptor named o
, then that descriptor's class's __get__
method is used. 当在类
SomeClass
实例o
上访问名为someprop
的属性时,如果SomeClass
包含名为o
的描述符 ,则使用该描述符的类的__get__
方法。 For more on descriptors, see this guide . 有关描述符的更多信息,请参阅本指南 。 Don't let the fact that
Lazy
is here used, syntactically, as a decorator, blind you to the fact that its instances are descriptors, because Lazy
itself has a __get__
method. 不要让
Lazy
在语法上作为装饰器使用这个事实,因为它的实例是描述符,因此Lazy
你,因为Lazy
本身有一个__get__
方法。
The decorator syntax 装饰器语法
@Lazy
def someprop(self):
...
is no more, and no less, than syntax sugar for: 不仅仅是语法糖,而且不亚于:
def someprop(self):
...
someprop = Lazy(someprop)
The constraints on Lazy
are no different when it's used with decorator syntax or directly: it must accept someprop
(a function) as its argument -- no constraints whatsoever on what it returns. 当它与装饰器语法或直接一起使用时,对
Lazy
的约束没有什么不同:它必须接受someprop
(一个函数)作为它的参数 - 对它返回的内容没有任何约束。 Here, Lazy
is a class so it returns an instance of itself, and has a __get__
special method so that instance is a descriptor (so said method gets called when the someprop
attribute is accessed on the instance o
of class SomeClass
) -- that's all there is to it, no more, and no less. 这里,
Lazy
是一个类,所以它返回一个自身的实例,并且有一个__get__
特殊方法,因此实例是一个描述符(所以当在SomeClass
类的实例o
上访问someprop
属性时调用所述方法) - 这就是全部有它,不多也不少。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.