PyQt线程中调用装饰函数时装饰逻辑仅单次执行的问题解析
问题现象与预期偏差
- 预期效果:在
Worker线程的无限循环中每次调用self.random()时,装饰器内的文本打印逻辑都会同步触发,输出'kw_argument'和"In decorator"内容 - 实际现象:上述装饰逻辑仅在程序启动、类定义初始化阶段执行了一次,后续线程内重复调用
self.random()时,没有任何对应的打印输出 - 认知澄清:该问题与PyQt的线程运行逻辑没有关联,即使脱离PyQt环境,用普通Python类复现相同的装饰器结构,也会得到完全一致的执行结果
问题根因
当前实现的带参数装饰器,存在三层独立的执行层级,代码把本该在方法调用时触发的逻辑,放到了仅会在类初始化阶段执行的外层代码块中,具体执行流程可拆解为:
- Python解释器加载到
Worker类的方法定义处,碰到@dec.deco(txt='kw_argument')的装饰语法时,会立刻执行一次dec.deco(txt='kw_argument')调用——这就是你在程序初始化阶段看到一次装饰打印的原因。这一步执行完成后,deco方法会返回内部定义的inner函数引用 - 解释器随后会把被装饰的
random方法作为入参传给inner函数;当前的inner函数没有做任何加工处理,直接把传入的原random方法返回,替换掉类中原有的方法绑定关系 - 等类定义完全加载完成后,后续所有对
self.random()的调用,本质上都是直接执行最初定义的random函数本体,根本不会再进入deco方法内部的打印代码块,自然也就不会重复触发装饰逻辑的输出
实现调整方案
要达到“每次调用被装饰方法时都触发装饰逻辑”的效果,需要把装饰相关的打印逻辑,移到内层的包装函数中——这个包装函数才是每次方法调用时会被实际执行的部分。调整后的装饰器实现如下:
class Decor: def deco(self, *args, **kwargs): # 以下代码仅在类加载、装饰器初始化时执行一次 def inner(func): # 以下代码也仅在类加载、装饰器初始化时执行一次 def wrapper(*func_args, **func_kwargs): # 以下代码会在每次调用被装饰的random方法时执行 print(kwargs['txt']) print("In decorator") # 执行原方法逻辑并返回结果 return func(*func_args, **func_kwargs) return wrapper return inner
完成上述调整后,在线程循环中每次调用self.random(),都会按预期触发装饰逻辑的打印输出。
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

