2016-02-03 3 views
2

Я пытаюсь создать последовательность похожих словарей для дальнейшего хранения их в кортеже. Я попробовал два подхода, используя и не используя для циклаПоследовательность словарей в python

Без цикл

dic0 = {'modo': lambda x: x[0]} 
dic1 = {'modo': lambda x: x[1]} 
lst = [] 
lst.append(dic0) 
lst.append(dic1) 
tup = tuple(lst) 
dic0 = tup[0] 
dic1 = tup[1] 
f0 = dic0['modo'] 
f1 = dic1['modo'] 
x = np.array([0,1]) 
print (f0(x) , f1(x)) # 0 , 1 

С для цикла

lst = [] 
for j in range(0,2): 
    dic = {} 
    dic = {'modo': lambda x: x[j]} 
    lst.insert(j,dic) 
tup = tuple(lst) 
dic0 = tup[0] 
dic1 = tup[1] 
f0 = dic0['modo'] 
f1 = dic1['modo'] 
x = np.array([0,1]) 
print (f0(x) , f1(x)) # 1 , 1 

Я действительно не понимаю, почему я получаю разные результаты. Кажется, что последний словарь, который я вставляю, перезаписывает предыдущие, но я не знаю, почему (метод append не работает).

Любая помощь будет действительно приветствовал

+0

in lambda x: x [j]} ',' j' оценивается при выполнении лямбда, поэтому его значение всегда 1 – njzk2

ответ

1

Это происходит из-за того, как обзорное работает в этом случае. Попробуйте поставить j = 0 над окончательным заявлением на печать, и вы увидите, что произойдет.

Кроме того, вы можете попробовать

from operator import itemgetter 

lst = [{'modo': itemgetter(j)} for j in range(2)] 
+0

Большое вам спасибо. Ваши предлагаемые решения отлично работают –

0

Вы случайно создали то, что знают, как через closure. лямбда-функции в вашей второй (петли на основе), например, содержать ссылку на переменную j. Эта переменная на самом деле является переменной цикла, используемой для итерации вашего цикла. Таким образом, вызов lambda действительно создает код со ссылкой на «некоторая переменная с именем« j », которую я не определял, но она где-то здесь».

Это называется «закрытие» или «включение» переменной j, потому что даже когда цикл закончен, эта функция лямбда, которую вы написали, будет ссылаться на переменную j. И поэтому он никогда не получит сбор мусора, пока вы не отпустите ссылки на лямбда-функции.

Вы получаете то же значение (1, 1), потому что j останавливает итерацию по range(0,2) с j = 1, и ничего не меняется. Поэтому, когда ваши лямбда-функции запрашивают x [j], они запрашивают приведенную стоимость от j, а затем получают текущую стоимость от x[j]. В обеих функциях текущее значение j равно 1.

Вы можете обойти это, создав функцию make_lambda, которая принимает номер индекса в качестве параметра. Или вы могли бы сделать то, что предложил @DavisYoshida, и использовать чужой код для создания соответствующего закрытия для вас.

+0

Большое вам спасибо. Ваша проблема очень понятна мне с вашим объяснением –

Смежные вопросы