Python模型回调

时间:2013-07-22 17:12:27

标签: python callback magic-methods

我试图实现一个简单的模型类,只要在类中设置了属性就执行回调,但是当我在我的应用程序中尝试使用它时,我会得到一个AttributeError。似乎实例没有我在初始化程序中设置的属性,我对于为什么有点困惑。我还没有多少使用魔术方法,所以一些细节可能会有所帮助:

class ReportModel(object):

    def __init__(self):
        self.current_date = None
        self.prior_date = None
        self._callbacks = defaultdict([])

    def __setattr__(self, attr, value):
        object.__setattr__(self, attr, value)
        for func in self._callbacks[attr]:
            func(value)

    def set_callback(self, attr, function):
        self._callbacks[attr].append(function)

回溯:

AttributeError: 'ReportModel' object has no attribute '_callbacks'

2 个答案:

答案 0 :(得分:2)

__setattr__正在运行并设置__init__self.current_date时,在类实例化期间调用self.prior_date方法。

要解决这个问题,你必须使用try,除了阻止回调调用以阻止错误。

    try:
        for func in self._callbacks[attr]:
            func(value)
    except:
        pass

答案 1 :(得分:2)

由于您已覆盖__setattr__(),当您在self.current_date = None__init__()时,它会调用__setattr__()实施,该实施将尝试访问self._callbacks。这就是导致AttributeError的原因。

以下是解决此问题的一个选项:

class ReportModel(object):

     def __init__(self):
         object.__setattr__(self, '_callbacks', defaultdict(list))
         self.current_date = None
         self.prior_date = None

     def __setattr__(self, attr, value):
         object.__setattr__(self, attr, value)
         for func in self._callbacks[attr]:
             func(value)

     def set_callback(self, attr, function):
         self._callbacks[attr].append(function)

这会在添加任何其他属性之前使用_callbacks添加object.__setattr__()属性,以便将来对__setattr__()实例ReportModel的调用不会阻止访问self._callbacks 1}}。

或者,您可以修改__setattr__()以检查是否存在_callbacks属性:

class ReportModel(object):

     def __init__(self):
         object.__setattr__(self, '_callbacks', defaultdict(list))
         self.current_date = None
         self.prior_date = None

     def __setattr__(self, attr, value):
         object.__setattr__(self, attr, value)
         if hasattr(self, '_callbacks'):
             for func in self._callbacks[attr]:
                 func(value)

     def set_callback(self, attr, function):
         self._callbacks[attr].append(function)