Словарь с лямбда-значениями обновляет все записи
Я в Python 2.7. У меня есть два класса и один именованный кортеж. Один класс содержит словарь в качестве атрибута экземпляра и функцию, назначаемую этому словарю. (Это очень упрощенная версия ситуации). Именованный кортеж достаточно прост. Другой класс, который добавляет записи в test_dict
через add_to_test_dict
вызов функции.
Затем я создаю экземпляр DictManipulator и вызываю test
функция:
from collections import namedtuple
class DictHolder(object):
def __init__(self):
self.test_dict = {}
def add_to_test_dict(self, key, val):
self.test_dict[key] = val
TestTuple = namedtuple('TestTuple', 'name data')
class DictManipulator(object):
def test(self):
named_tuple_list = [TestTuple(name='key1', data=1), TestTuple(name='key2', data=1000)]
self.my_dh = DictHolder()
for item in named_tuple_list:
self.my_dh.add_to_test_dict(item.name, lambda: item.data)
my_dm = DictManipulator()
my_dm.test()
print('key1 value: ', my_dm.my_dh.test_dict['key1']())
print('key2 value: ', my_dm.my_dh.test_dict['key2']())
# ('key1 value: ', 1000)
# ('key2 value: ', 1000)
Почему оба ключа возвращают одно и то же значение? Я достаточно экспериментировал, чтобы сказать, что оригинальный named_tuple_list не обновляется, и я пытался использовать lambda: copy.deepcopy(item.data)
, но это тоже не работает. Большое спасибо, ребята.
1 ответ
Это типичная проблема позднего связывания (см. Общие ошибки): когда вызываются функции (будучи лямбда / анонимными), они получают доступ к текущему значению item
, который является последним из цикла. Пытаться
lambda x=item: x.data
в вашем цикле вместо. Это работает, поскольку аргументы по умолчанию привязываются к функции во время определения, в то время как общие локальные переменные оцениваются во время вызова.
Подобный (возможно дублирующий) вопрос: Python Lambda в цикле