设置值时调用函数

时间:2019-03-14 17:42:24

标签: python python-3.x dictionary observer-pattern

使用观察者模式,我有一个dict的子类,当dict中的值发生更改时,我将覆盖__setitem__来调用函数。这对于直接赋值(例如my_dict[key] = 1234)非常有效,但是当我想更改存储在dict(例如my_dict[key][0] = 1)中的数组中的值时不起作用。

由于这是一个异步应用程序,所以我曾经想在__getitem__中安排一个未来,该应用程序会稍等片刻,然后将键上的旧内容与当前内容进行比较,但这显然会导致比赛条件。

处理此问题的最佳方法是什么?我不想在我想将数组存储在字典中时就不必使用自定义数组。

编辑:这是课程

class SettingsTable(dict):
    def __init__(self, seq=None, **kwargs):
        super().__init__({}, **kwargs)
        self._post_process_map = {}

    def add_post_process(self, key, process, *args):
        if not self._post_process_map.__contains__(key):
            self._post_process_map[key] = []
        self._post_process_map[key].append((process, *args))

    def __setitem__(self, key, value):
        old_val = None
        if self.keys().__contains__(key):
            old_val = self[key]

        super().__setitem__(key, value)
        self._run_on_change_funcs(key, value, old_val)

    def _run_on_change_funcs(self, key, value, old_val):
        if not old_val.__eq__(value):
            if self._post_process_map.__contains__(key):
                for func in self._post_process_map[key]:
                    if func[1]:
                        func[0](func[1])
                    else:
                        func[0]()

2 个答案:

答案 0 :(得分:1)

也许您可以编写list的子类并覆盖其__getitem__函数,只要您的dict子类__getitem__函数收到{{1 }}输入值。这是一个很棘手的解决方案,但应该适合您的情况

list

我得到的输出测试是:

def change_item(val):
    print 'item changed: ' + str(val)

class MyList(list):
    def __setitem__(self, key, val):
        change_item(val)
        list.__setitem__(self, key, val)

class MyDict(dict):
    def __setitem__(self, key, val):
        change_item(val)
        if isinstance(val, list):
            dict.__setitem__(self, key, MyList(val))
        else:
            dict.__setitem__(self, key, val)

md = MyDict()
md['a'] = 1
md['d'] = ['c', 'd', 'e', 'f']
md['d'][0] = 'b'

更新: 我刚刚签出了您的代码。我采取了与我建议的方法相同的方法,但是我还将字典引用及其键存储在item changed: 1 item changed: ['c', 'd', 'e', 'f'] item changed: b 对象中,以便每当MyList对象更改时,它都会创建一个重复的MyList对象,为其分配新值,并在键引用处将字典对象的值分配为等于重复的MyList对象,从而触发MyList的{​​{1}}函数。我在SettingsTable函数中添加了__setitem__行,以测试代码通过print(value)行时是否被调用

__setitem__

答案 1 :(得分:0)

AFAIR,几年前用Python继承内置类型曾经是一个坏主意。除此之外,我认为没有一种简洁的解决方案可以使dict意识到其任何价值的变化。您需要此功能做什么?