如何实现支持@Decorator(t=3)用法的类装饰器并正确为self.f赋值
问题根源
你写的类装饰器没有处理带参数调用的场景。当使用@Decorator(t=3)这种带参数的写法时,Python会先实例化一次Decorator类(这时候f参数为None),再把被装饰的函数作为参数传入该实例的__call__方法,原来的__call__逻辑没有处理这一步,所以self.f一直是空的。
解决方案
调整__call__方法的逻辑,判断如果self.f为空,就把传入的第一个参数作为被装饰函数存到self.f并返回当前实例即可,同时补充函数返回值逻辑和参考的函数装饰器对齐,修改后的完整代码如下:
#!/usr/bin/env python3 class Decorator: def __init__(self, f=None, *, t=2): self.t = t self.f = f def __call__(self, *args, **kwargs): # 处理带参数装饰场景:第一次调用接收被装饰函数 if self.f is None: self.f = args[0] return self # 正常调用函数的逻辑 print(f'{self.f = !r}') value = None for _ in range(self.t): value = self.f(*args, **kwargs) return value @Decorator def hello4(name): print(f'Hello {name}') if __name__ == '__main__': hello4("gert") @Decorator(t=3) def hello6(name): print(f'Hello {name}') if __name__ == '__main__': hello6("gert")
运行效果
输出和你提供的函数装饰器完全一致:
self.f = <function hello4 at 0x...> Hello gert Hello gert self.f = <function hello6 at 0x...> Hello gert Hello gert Hello gert
内容的提问来源于stack exchange,提问作者Gert Cuykens
相关产品推荐
相关产品推荐

