[英]Python's new `functools.cached_property` bug or limitation?
[英]Why `functools.cached_property` can work as a decorator without `__new__` or `__call__`?
据我了解,装饰器 class 应该包含__call__
或__new__
方法。 但是 cpython repo中的 cached_property 不遵循规则。 谁能为我解释一下?
class cached_property:
def __init__(self, func):
xxx
def __set_name__(self, owner, name):
xxx
def __get__(self, instance, owner=None):
xxx
__class_getitem__ = classmethod(GenericAlias)
所有装饰器类都需要__call__
吗?
装饰器 class 应该包含
__call__
或__new__
方法
并非所有装饰器类都需要实现__call__
。 只有当我们想用()
调用修饰的 object 时才需要它。
装饰器 class 需要一个可调用对象来生成一个可调用对象,它必须实现__call__
。 在这个例子中, __call__
被实现是因为我们想要做data.calculate()
。
# Decorator to call and cache the function immediately class PreCompute: def __init__(self, func): self.value = func() def __call__(self, *args, **kwds): return self.value class Data: @PreCompute def calculate(): print("Data.calculate called") return 42 data = Data() # This actually calls PreCompute's __call__ print(data.calculate())
这里的class Data
的定义大致是这样的,所以当调用data.calculate()
时,我们实际上是从class PreCompute
调用__call__
function 。
class Data: def calculate(): print("Data.calculate called") return 42 calculate = PreCompute(calculate)
接受可调用但不产生可调用的装饰器 class不必实现__call__
。 例如,我们可以将class Precompute
装饰器修改为以下代码,这样我们就可以像访问属性一样访问data.calculate
。 有关__get__
功能的更多信息,请参阅 Python 文档中的Descriptor HowTo Guide 。
class PreCompute: def __init__(self, func): self.value = func() def __get__(self, instance, owner): return self.value class Data: @PreCompute def calculate(): print("Data.calculate called") return 42 data = Data() # Access.calculate like an attribute print(data.calculate)
__new__
呢?
我不确定 OP 如何获得装饰器类必须定义__call__
或__new__
的印象。 我已经看到__new__
被定义为类的@singleton
decorator这样的用例,但正如上一节关于__call__
所讨论的,这也不是严格要求的。 我们必须定义的唯一 function 是一个__init__
,它接收要装饰的 object 。
那么@functools.cached_property
是如何工作的呢?
现在回到问题,从@functools.cached_property
的文档中注意到它“将 class 的方法转换为属性”,无需括号()
即可访问。 因此, class cached_property
实现__get__
而不是__call__
,这与上面的第二个示例类似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.