Python装饰器导致PLUGINS字典无法持久化存储函数地址的问题
问题解答
1. 为什么会打印两次空字典?
这两次空字典的打印发生在函数定义阶段,而非调用say_hello的时候。当你用@register装饰函数时,装饰器register会立即执行(此时函数还未被调用):
- 定义
say_hello时,register(say_hello)被触发,内部打印此时仍为空的PLUGINS。 - 定义
be_awesome时,register(be_awesome)被触发,再次打印空的PLUGINS。
这就是两次空字典的来源。
2. 为什么退出wrapper后PLUGINS中的条目消失?
根据你提供的代码,这种情况本不应该发生。当你调用say_hello('Addam')时,实际执行的是wrapper函数:
wrapper内部会将原始的say_hello函数存入PLUGINS,此时PLUGINS会包含该条目。- 除非你在代码未展示的部分重新初始化了
PLUGINS,否则这个条目会一直保留。
不过从代码逻辑来看,你的意图应该是在装饰函数时完成注册,而非等到函数被调用时才注册。当前代码把注册逻辑放在wrapper内部,导致只有调用函数时才会将函数加入PLUGINS。如果要实现装饰阶段注册,需将注册逻辑移到register函数内部、wrapper之外:
PLUGINS = dict() def register(func): """Register a function as a plug-in""" PLUGINS[func.__name__] = func print(PLUGINS) # 装饰函数时就会打印包含当前函数的字典 def wrapper(*args, **kwargs): print('hello', func.__name__) return func(*args, **kwargs) return wrapper @register def say_hello(name): return f"Hello {name}" @register def be_awesome(name): return f"Yo {name}, together we are the awesomest!" print(say_hello('Addam')) print(PLUGINS) # 此时会包含两个函数条目
修改后,say_hello和be_awesome在定义时就会被立即加入PLUGINS,无需等到函数调用。
内容的提问来源于stack exchange,提问作者Santiago Rodríguez
相关产品推荐
相关产品推荐

