Возможно, вы можете написать подкласс list
, а также переопределить его функцию __getitem__
, вы будете использовать этот класс всякий раз, когда ваша функция dict
подкласс __getitem__
получит значение типа 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
, таким образом вызывая функцию SettingsTable
__setitem__
.Я добавил строку print(value)
в функцию __setitem__
, чтобы проверить, вызывается ли она или нет, когда код проходит через md['d'][0]='b'
строку
class MyList(list):
def __init__(self, dictionary, key, *args):
super().__init__(*args)
self.dictionary = dictionary
self.key = key
def __setitem__(self, key, val):
new_list = MyList(self.dictionary, self.key, list(self))
list.__setitem__(new_list, key, val)
self.dictionary[self.key] = new_list
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]
if isinstance(value, list):
value = MyList(self, key, value)
super().__setitem__(key, value)
self._run_on_change_funcs(key, value, old_val)
def _run_on_change_funcs(self, key, value, old_val):
print(value)
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]()
md = SettingsTable()
md['a'] = 1
md['d'] = ['c', 'd', 'e', 'f']
md['d'][0] = 'b'