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

时间:2017-09-21 22:07:31

标签: 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.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)

甜!我可以在我的代码周围加密,感觉很有用。但是我觉得这里有一些最终的老板形式,我在这里失去了它,以使它真正具有全球实用性。就像某种装饰一样。

在这里使用这个答案我可以将变量传递给我的装饰者并装饰我的功能! Decorators with parameters?

def block(items):
    def dec(fn):
        def wrapped(*args, **kwargs):
            for item in items:
                item.blockSignals(True)
            fn(*args, **kwargs)
            for item in items:
                item.blockSignals(False)
        return wrapped
    return dec


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

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

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

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

2 个答案:

答案 0 :(得分:2)

您无法在课程定义时引用属性 values ,但您可以使用其名称:

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,但它可以正常工作。

答案 1 :(得分:2)

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

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