我可以重构这个使用属性装饰器的简单回调模式吗?

时间:2013-03-25 10:55:42

标签: python properties callback decorator python-decorators

我正在处理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')

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

查看Python descriptor protocol。实质上,您可以定义一个处理属性的获取,设置和删除的类。因此,您可以定义一个描述符,用于在设置属性时运行回调。

描述符是常规类,可以参数化。所以你可以实现一个描述符,它将目标变量作为构造函数。如下所示:

class A(object):
    var = CallbackDescriptor('var')
    foo = CallbackDescriptor('foo')