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

2024-10-01 07:14:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道如何在一个可以接受类变量的类中设置装饰器。我认为这可能有用的例子是在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)

太好了!我可以在我的代码周围加胡椒粉,感觉非常有用。但我觉得这里缺少某种最终的老板表格,让它真正在全球范围内有用。就像某种装潢师。你知道吗

使用这个答案,我可以把变量传递给我的decorator并修饰我的函数! 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([自我列表])不知道自我是什么。你知道吗

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


Tags: selffalsedefargsitemswindowitemblock
2条回答

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

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。你知道吗

相关问题 更多 >