我过去曾经使用装饰器而没有任何问题,但我坚持这一点。似乎当我的装饰函数被PyQt动作调用时,它失败了。我的理论是PyQt以某种方式在内部包装连接函数并弄乱签名或某些此类事情,但我找不到任何证据。
通过连接我的意思是这样的:
from PyQt4 import QtGui
# In my widget init...
self.action_my_method = QtGui.QAction("action_my_method", self)
self.action_my_method.triggered.connect(self.my_method)
这是我的简单装饰:
from functools import wraps
def simple_decorator(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
from inspect import getargspec
print getargspec(fn)
return fn(*args, **kwargs)
return wrapper
当我使用它来装饰没有任何参数的方法(def my_method(self)
),并直接从我的QWidget类执行它时,它工作正常。当我使用菜单触发操作时,我得到:
# Traceback (most recent call last):
# File "[...].py", line 88, in wrapper
# return fn(*args, **kwargs)
# TypeError: my_method() takes exactly 1 argument (2 given)
我正在看一个arg spec:
ArgSpec(args=['self'], varargs=None, keywords=None, defaults=None)
如果我将*args
添加到我的方法中,因此签名为my_method(self, *args)
,装饰器工作正常,arg规范为:
ArgSpec(args=['self'], varargs='args', keywords=None, defaults=None)
我在这里看不到任何线索,因为装饰器在直接调用时工作正常,但在操作触发时失败。
任何人都可以对此有所了解,或者提供一些我可以用来进一步调试它的东西吗?
答案 0 :(得分:1)
这不是解决方法的答案。我希望这没有任何缺点。我在输入简单的重定向功能时想到了它。这使用lambda在运行时执行相同的操作:
self.action_my_method.triggered.connect(lambda: self.my_method())
这足以填补我的修饰函数,防止被破坏并防止错误。
答案 1 :(得分:0)
或者,您可以通过.connect as:
重新定义可以调用的每个方法的签名def my_method(self, qtcallparam=None, **kwargs):
因此该方法将忽略第一个未命名的参数,在该方法中严格使用关键字参数的代价(不是那么糟糕)
但@Rafe的解决方案可能更清晰