Building on the answer given in here, just do the following:
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)
and then:
my_dict = MyDict({'a': MyDict({'b': 1})})
my_dict['a']['b'] = 2
You are changing the value of b to 2!!
my_dict['a'] = 5
You are changing the value of a to 5!!
If you want to avoid manual calls to MyDict at each nesting level, one way of doing it, is to fully overload the dict class. For example:
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)
You can then do the following:
# Simple initialization using a normal dict synthax
my_dict = MyDict({'a': {'b': 1}})
# update example
my_dict['c'] = {'d':{'e':4}}
You are changing the value of c to {'d': {'e': 4}}!!
my_dict['a']['b'] = 2
my_dict['c']['d']['e'] = 6
You are changing the value of b to 2!!
You are changing the value of e to 6!!