返回

类装饰器何时运行?为何接收绑定方法?解析常见问题

python

装饰器在类构造时运行:探究原因及解决方案

类装饰器:定义及运行时机

当装饰器用于修饰类时,它称为类装饰器。不同于方法装饰器,类装饰器在类定义时运行,并接收类本身作为参数。这意味着,当一个类被定义,例如 Power@cache 装饰器就会运行,并且会接收到 Power 类作为参数。

装饰器接收的参数

@cache 装饰器接收一个参数,即要装饰的方法 ofof 方法是一个实例方法,这意味着它绑定到了类的实例上。因此,当 @cache 运行时,它接收到的就是一个绑定方法,而不是一个未绑定方法。

装饰器函数内部

在装饰器函数 wrapper 的定义中,有一个 @functools.wraps(func) 装饰器。@functools.wraps 用来保留被装饰函数(在本例中是 of)的元数据,包括函数名称和文档字符串。当 @functools.wraps 应用于 wrapper 时,它会将 of 的元数据复制到 wrapper

这意味着 wrapper 具有与 of 相同的名称和文档字符串。但需要注意的是,wrapper 仍然是一个不同的函数,它具有自己的内部状态,包括 cache 属性。

调用装饰后的方法

cube.of(2) 被调用时,wrapper 函数就会被执行。wrapper 会检查 cache 属性是否为 None。由于这是 of 方法的第一次调用,cache 此时为 Nonewrapper 接着会调用 func(即 of),并使用传递给 cube.of(2) 的参数。of 函数计算 2 ** 3,并将结果存储在 wrapper.cache 中。

为什么无法重置 .cache 属性

你收到的 AttributeError 是因为 of 方法是一个绑定方法。绑定方法没有 __dict__ 属性,因此无法直接访问或修改其属性。要重置 cache 属性,可以使用 setattr 函数:

setattr(cube.of, 'cache', None)

总结

  • 类装饰器在类构造时运行,接收类本身作为参数。
  • 装饰器接收一个绑定方法作为参数。
  • @functools.wraps 用来保留被装饰函数的元数据。
  • 绑定方法没有 __dict__ 属性,不能直接访问或修改其属性,需使用 setattr 函数。

常见问题解答

  1. 什么是类装饰器?
    类装饰器在类定义时运行,并接收类本身作为参数。

  2. 为什么装饰器在类构造时运行?
    因为它是类装饰器,类装饰器在类定义时运行。

  3. 为什么装饰器函数内部有 @functools.wraps 装饰器?
    为了保留被装饰函数的元数据,包括函数名称和文档字符串。

  4. 为什么绑定方法没有 __dict__ 属性?
    因为绑定方法的属性是绑定到实例上的,而不是类上的。

  5. 如何重置绑定方法的属性?
    可以使用 setattr 函数,例如 setattr(cube.of, 'cache', None)