class NoisyDict(dict):

    def __init__(self, *args, **kwargs):
        self.handlers = {}
super().__init__(*args, **kwargs)

def add_handler(self, key, callback):
    self.handlers[key] = self.handlers.get(key, [])
self.handlers[key].append(callback)

def __getitem__(self, key):
    for handler in self.handlers.get(key, []):
        handler('get', key, super().__getitem__(key))
return super().__getitem__(key)

def __setitem__(self, key, value):
    for handler in self.handlers.get(key, []):
        handler('set', key, value)
return super().__setitem(value)
Pythonic способ опроса словаря - использование значения ключа, когда оно существует