【问题标题】:Can I refactor this simple callback pattern that uses the property decorator?我可以重构这个使用属性装饰器的简单回调模式吗?
【发布时间】:2013-03-14 20:08:07
【问题描述】:

我刚刚开始掌握 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')

【问题讨论】:

    标签: python properties callback decorator python-decorators


    【解决方案1】:

    您需要在类上设置属性(因为它是一个描述符),所以在初始化程序中使用 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
    

    【讨论】:

    • 在 return 语句之后有一个 for 循环
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-31
      • 2023-03-16
      • 1970-01-01
      • 2011-02-27
      • 2011-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多