首页 > 解决方案 > 使用 Python 检测对嵌套字典的更改

问题描述

我在 SO 上看到了一些类似的问题,关于检测字典的更改并在字典更改时调用函数,例如:

这些示例使用了观察者模式或重载的变体__setitem__,但所有这些示例都没有检测到嵌套字典值的变化。

例如,如果我有:

my_dict = {'a': {'b': 1}}
my_dict['a']['b'] = 2

不会检测2到对元素的分配。['a']['b']

我想知道是否有一种优雅的方法可以检测不仅对字典的基本元素而且对嵌套字典的所有子元素的更改。

标签: pythondictionary

解决方案


基于此处给出的答案,只需执行以下操作:

class MyDict(dict):
    def __setitem__(self, item, value):
        print("You are changing the value of {} to {}!!".format(item, value))
        super(MyDict, self).__setitem__(item, value)

接着:

my_dict = MyDict({'a': MyDict({'b': 1})})

my_dict['a']['b'] = 2

您正在将 b 的值更改为 2!

my_dict['a'] = 5

您正在将 a 的值更改为 5!

如果您想避免在每个嵌套级别手动调用 MyDict,一种方法是完全重载dict类。例如:

class MyDict(dict):
    def __init__(self,initialDict):
        for k,v in initialDict.items():
          if isinstance(v,dict):
            initialDict[k] = MyDict(v)
        super().__init__(initialDict)

    def __setitem__(self, item, value):
        if isinstance(value,dict):
          _value = MyDict(value)
        else:
          _value = value
        print("You are changing the value of {} to {}!!".format(item, _value))
        super().__setitem__(item, _value)

然后,您可以执行以下操作:

# Simple initialization using a normal dict synthax
my_dict = MyDict({'a': {'b': 1}})

# update example
my_dict['c'] = {'d':{'e':4}}

您正在将 c 的值更改为 {'d': {'e': 4}}!

my_dict['a']['b'] = 2
my_dict['c']['d']['e'] = 6

您正在将 b 的值更改为 2!

您正在将 e 的值更改为 6!


推荐阅读