如何在PyQt5代码中为QtAwesome Spin实例方法打猴子补丁?
问题解答
为什么调用old_anim_update()不传self能运行?
这是因为你保存的old_anim_update已经是绑定方法:如果是从某个Spin实例上获取的_update方法,Python会自动把该实例和方法绑定,调用时不需要手动传self——绑定方法会自动把绑定的实例作为第一个参数传入原方法。
要是你直接从Spin类上获取_update方法(未绑定方法),调用时必须手动传self,否则就会触发参数数量不匹配的报错。你之前遇到的TypeError就是因为混淆了绑定/未绑定方法的调用规则。
更规范的猴子补丁方式
给类的实例方法打补丁,标准姿势是直接修改类的方法属性,同时保存原类方法(而非实例方法),这样所有实例都会生效。示例代码如下:
from qtawesome import Spin import functools # 保存原类的未绑定方法 original_update = Spin._update # 定义补丁方法,必须接收self作为第一个参数 @functools.wraps(original_update) def patched_update(self): # 先调用原方法,手动传入self original_update(self) # 执行自定义逻辑 print("Spin _update 方法已执行") # 替换类的方法 Spin._update = patched_update
这种写法的优势:
- 所有Spin实例都会应用该补丁,而非仅单个实例
- 使用
functools.wraps保留原方法的元数据(如方法名、文档字符串),避免后续潜在问题 - 逻辑清晰,明确区分绑定/未绑定方法的调用规则
如果只需要给单个实例打补丁,就修改该实例的__dict__,保存实例的绑定方法即可:
# 假设spin_inst是一个已创建的Spin实例 original_update = spin_inst._update def patched_update(): original_update() # 绑定方法无需传self print("单个实例的_update方法已执行") spin_inst._update = patched_update
这也能解释你提到的“只有方式1能保留self”——方式1应该是针对单个实例的补丁,保存的是绑定方法;方式2如果是直接修改类方法但未正确传递self,就会触发报错。
内容的提问来源于stack exchange,提问作者sdbbs
相关产品推荐
相关产品推荐

