回答问题

Python 装饰器使用起来很有趣,但由于参数传递给装饰器的方式,我似乎碰壁了。在这里,我将一个装饰器定义为基类的一部分(装饰器将访问类成员,因此它需要 self 参数)。

class SubSystem(object):
    def UpdateGUI(self, fun): #function decorator
        def wrapper(*args):
            self.updateGUIField(*args)
            return fun(*args)
        return wrapper

    def updateGUIField(self, name, value):
        if name in self.gui:
            if type(self.gui[name]) == System.Windows.Controls.CheckBox:
                self.gui[name].IsChecked = value #update checkbox on ui 
            elif type(self.gui[name]) == System.Windows.Controls.Slider:
                self.gui[name].Value = value # update slider on ui 

        ...

我省略了其余的实现。现在这个类是从它继承的各种子系统的基类——一些继承的类需要使用 UpdateGUI 装饰器。

class DO(SubSystem):
    def getport(self, port):
        """Returns the value of Digital Output port "port"."""
        pass

    @SubSystem.UpdateGUI
    def setport(self, port, value):
        """Sets the value of Digital Output port "port"."""
        pass

我再次省略了函数实现,因为它们不相关。

简而言之,问题是虽然我可以通过将继承类中定义的装饰器指定为 SubSystem.UpdateGUI 来访问基类中定义的装饰器,但在尝试使用它时最终会得到这个 TypeError:

unbound method UpdateGUI() must be called with SubSystem instance as first argument (got function instance instead)

这是因为我没有立即可识别的方式将self参数传递给装饰器!

有没有办法做到这一点?还是我已经达到了 Python 中当前装饰器实现的极限?

Answers

您需要将UpdateGUI设置为@classmethod,并让您的wrapper了解self。一个工作示例:

class X(object):
    @classmethod
    def foo(cls, fun):
        def wrapper(self, *args, **kwargs):
            self.write(*args, **kwargs)
            return fun(self, *args, **kwargs)
        return wrapper

    def write(self, *args, **kwargs):
        print(args, kwargs)

class Y(X):
    @X.foo
    def bar(self, x):
        print("x:", x)

Y().bar(3)
# prints:
#   (3,) {}
#   x: 3
Logo

学AI,认准AI Studio!GPU算力,限时免费领,邀请好友解锁更多惊喜福利 >>>

更多推荐