触发时Python PyQt修饰方法错误

时间:2012-06-13 21:55:06

标签: python qt pyqt action decorator

我过去曾经使用装饰器而没有任何问题,但我坚持这一点。似乎当我的装饰函数被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)

我在这里看不到任何线索,因为装饰器在直接调用时工作正常,但在操作触发时失败。

任何人都可以对此有所了解,或者提供一些我可以用来进一步调试它的东西吗?

2 个答案:

答案 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的解决方案可能更清晰