使用Python检测嵌套字典的更改

Wil*_*ich 4 python dictionary

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

这些示例使用Observer模式或重载的变体__setitem__,但所有这些示例都不检测嵌套字典值的更改.

例如,如果我有:

my_dict = {'a': {'b': 1}}
my_dict['a']['b'] = 2
Run Code Online (Sandbox Code Playgroud)

不会检测到2元素的赋值['a']['b'].

我想知道是否有一种优雅的方法来检测更改不仅是字典的基本元素,还有嵌套字典的所有子元素.

ma3*_*oun 5

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

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)
Run Code Online (Sandbox Code Playgroud)

然后:

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

my_dict['a']['b'] = 2
Run Code Online (Sandbox Code Playgroud)

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

my_dict['a'] = 5
Run Code Online (Sandbox Code Playgroud)

您正在将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)
Run Code Online (Sandbox Code Playgroud)

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

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

# update example
my_dict['c'] = {'d':{'e':4}}
Run Code Online (Sandbox Code Playgroud)

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

my_dict['a']['b'] = 2
my_dict['c']['d']['e'] = 6
Run Code Online (Sandbox Code Playgroud)

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

你正在将e的值改为6 !!

  • 好的,也许将嵌套的dicts直接转换为MyDict对象(在`value`上使用`isinstance`)会很有趣 (2认同)