类装饰器何时运行?为何接收绑定方法?解析常见问题
2024-03-01 19:56:41
装饰器在类构造时运行:探究原因及解决方案
类装饰器:定义及运行时机
当装饰器用于修饰类时,它称为类装饰器。不同于方法装饰器,类装饰器在类定义时运行,并接收类本身作为参数。这意味着,当一个类被定义,例如 Power
,@cache
装饰器就会运行,并且会接收到 Power
类作为参数。
装饰器接收的参数
@cache
装饰器接收一个参数,即要装饰的方法 of
。of
方法是一个实例方法,这意味着它绑定到了类的实例上。因此,当 @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
此时为 None
。wrapper
接着会调用 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
函数。
常见问题解答
-
什么是类装饰器?
类装饰器在类定义时运行,并接收类本身作为参数。 -
为什么装饰器在类构造时运行?
因为它是类装饰器,类装饰器在类定义时运行。 -
为什么装饰器函数内部有
@functools.wraps
装饰器?
为了保留被装饰函数的元数据,包括函数名称和文档字符串。 -
为什么绑定方法没有
__dict__
属性?
因为绑定方法的属性是绑定到实例上的,而不是类上的。 -
如何重置绑定方法的属性?
可以使用setattr
函数,例如setattr(cube.of, 'cache', None)
。