繁体   English   中英

为什么 `functools.cached_property` 可以在没有 __new__ 或 __call__ 的情况下充当装饰器?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM