0

我刚刚开始掌握 Python 中的装饰器,并使用以下简单模式使用它们向某些实例变量添加回调:

class A(object):
    def __init__(self):
        self._var = 0
        self.var_callbacks = []

    @property
    def var(self):
        return self._var

    @var.setter
    def var(self, x):
        self._var = x
        for f in self.var_callbacks:
            f(x)

属性装饰器是一种简洁的方式,它允许我在必要时引入回调而不更改类接口。但是,在第三个或第四个变量之后,它使代码有点重复。

有没有办法将此模式重构为以下内容:

class A(object):
    def __init__(self):
        self.var = 0
        enable_callback(self, 'var', 'var_callbacks')
4

2 回答 2

3

您需要在类上设置属性(因为它是一个描述符),因此enable_callback在初始化程序中使用调用是行不通的。

您可以使用类装饰器从模式设置属性:

def callback_properties(callbacks_attribute, *names):
    def create_callback_property(name):
        def getter(self):
            return getattr(self, '_' + name)
        def setter(self, value):
            setattr(self, '_' + name, value)
            for f in getattr(self, callbacks_attribute):
                f(value)
        return property(getter, setter)

    def add_callback_properties(cls):
        for name in names:
            setattr(cls, name, create_callback_property(name)

        return cls

    return add_callback_properties

然后将其用作:

@add_callback_properties('var_callbacks', 'var1', 'var2')
class A(object):
    # everything else
于 2013-03-25T11:16:03.690 回答
2

看看Python 描述符协议。本质上,您可以定义一个类来处理属性的获取、设置和删除。因此,您可以定义一个描述符,在设置属性时运行您的回调。

描述符是常规类,可以参数化。因此,您可以实现一个描述符,该描述符将目标变量作为其构造函数。类似于以下内容:

class A(object):
    var = CallbackDescriptor('var')
    foo = CallbackDescriptor('foo')
于 2013-03-25T11:04:14.023 回答