Python 传递类变量时类对象中的装饰器

Python 传递类变量时类对象中的装饰器,python,pyqt4,decorator,pyside,Python,Pyqt4,Decorator,Pyside,我想知道如何在可以接受类变量的类中设置装饰器。我认为这可能有用的例子是在Pyside/PyQt中,我需要在函数的开始和结束时阻止和取消阻止小部件上的信号 例如: class Window(QtGui.QMainWindow): .... def updateList(self, *args): self.list.blockSignals(False) //do things on self.list self.list.bloc

我想知道如何在可以接受类变量的类中设置装饰器。我认为这可能有用的例子是在Pyside/PyQt中,我需要在函数的开始和结束时阻止和取消阻止小部件上的信号

例如:

class Window(QtGui.QMainWindow):
    ....

    def updateList(self, *args):
        self.list.blockSignals(False)
        //do things on self.list
        self.list.blockSignals(True)
现在,在不同的小部件上有很多地方可以实现这一点。当然,我可以用这种方法来阻止和取消阻止每个项目,但那很乏味。我必须记住,当我完成时,要解除所有的封锁

进入另一个步骤,我可以将块移动到它自己的功能中

class Window(QtGui.QMainWindow):
    ....

    def updateList(self, *args):
        self.block([self.list])
        //do things on self.list
        self.block([self.list])

    def block(self, items):
        for item in items:
            if item.signalsBlocked():
                item.blockSignals(False)
            else:
                item.blockSignals(True)
好极了!我可以在我的代码中添加这一点,感觉非常有用。但我觉得这里缺少某种最终的老板形式,使其真正在全球范围内有用。就像某种装潢师

使用这个答案,我可以将变量传递给我的装饰器并装饰我的函数!

现在我觉得这真的很有用!除了,@block([self.list])不知道self是什么


所以,我想做的是,假设我能做到这一点,这合理吗?可能吗,还是我在追逐野龙?如果可能,正确的方法是什么?

您不能在类定义时引用属性值,但可以使用它们的名称:

def block(*attrs):
    def dec(fn):
        @functools.wraps(fn)
        def wrap(self,*args,**kwargs):
            for a in attrs: getattr(self,a).blockSignals(True)
            ret=fn(self, *args, **kwargs)
            for a in attrs: getattr(self,a).blockSignals(False)
            return ret
        return wrap
    return dec
不得不写作有点难看

class Window(QtGui.QMainWindow):
    @block("list1","list2")
    def updateList(self, *args): # ...

使用字符串引号和all,但它可以工作。

这里是一个简单的上下文管理器,用于比较:

class blocked(object):
    def __init__(self, *targets):
        self._targets = targets

    def __enter__(self):
        for target in self._targets:
            target.blockSignals(True)

    def __exit__(self, cls, exception, traceback):
        for target in self._targets:
            target.blockSignals(False)
下面是如何使用它:

class Window(QtGui.QMainWindow):
    ...

    def updateList(self, *args):
        with blocked(self.list):
            # do things with self.list

这样做的好处是
blocked
可以在任何地方使用,并且可以动态指定目标。也可以说它更具可读性,因为被阻止的是
self.list
(信号发射器),而不是
self.updateList

@DavisHerring啊,是的,我又看了另一个答案,我修正了它。(清理注释…)这应该是一个上下文管理器,而不是一个装饰器。这样做会更加灵活,因为它不会与任何特定的对象或函数/方法绑定。@ekhumoro:两者都可以。@ekhumoro您能举个例子吗?我对它们不熟悉,到目前为止做了一点研究,我有点困惑。我想我应该在
wrap
中使用
instance
作为参数名,而不是
self
——但是…
instance
会与wrapped函数中同名的参数冲突。函数
wrap
将在描述符返回它时成为类的一个方法,
self
对我来说似乎非常习惯。我可以立即看到在不应该为整个函数阻塞信号的情况下,它的用处。在这些示例中,装饰器会屏蔽整个函数。
class Window(QtGui.QMainWindow):
    ...

    def updateList(self, *args):
        with blocked(self.list):
            # do things with self.list