Словарь с лямбда-значениями обновляет все записи - PullRequest
0 голосов
/ 29 сентября 2018

Я в 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 Ответ

0 голосов
/ 29 сентября 2018

Это типичная проблема позднего связывания (см. общие ошибки ): когда вызываются функции (будучи лямбда / анонимными), они получают доступ к текущему значению item,который является последним из цикла.Попробуйте вместо этого

lambda x=item: x.data 

в цикле.Это работает, поскольку аргументы по умолчанию привязываются к функции во время определения, в то время как общие локальные переменные оцениваются во время вызова.

Аналогичный (возможно дублирующий) вопрос: Python Lambda в цикле

...