2016-07-16 3 views
2

я видел this question, но я до сих пор не понимаю, почему такой простой пример не работает:список лямбды в питоне

mylist = ["alice", "bob", "greta"] 
funcdict = dict(((y, lambda x: x==str(y)) for y in mylist)) 
funcdict['alice']("greta") 
#True 
funcdict['alice']("alice") 
#False 
funcdict['greta']("greta") 
#True 

Как это отличается от:

[(y, y) for y in mylist] 

Почему y не оценивается на каждом этапе итерации?

+0

Почему вы ожидаете оценки 'y': это временная переменная внутри понимания списка. – Evert

ответ

4

y в теле выражения lambda это просто название, не связан с y использовать перебрать mylist. В качестве свободной переменной значение y не будет найдено до тех пор, пока вы фактически не вызовете функцию, и в это время она использует любое значение для y в области вызова.

Чтобы действительно заставить y иметь значение во время определения, что вам нужно сделать его локальным для тела с помощью аргумента:

dict((y, lambda x, y=z: x == str(y)) for z in mylist) 
2
((y, lambda x: x==str(y)) for y in mylist) 

y внутри лямбда не связан в момент определение выражения genration, но оно связано, когда оно называется; Когда он вызывается, итерация уже выполнена, поэтому y ссылается на последний элемент greta.

Один из способов обойти это использовать аргумент ключевое слово, которое вычисляется, когда функция/лямбда определяется:

funcdict = dict((y, lambda x, y=y: x == y) for y in mylist) 
funcdict = {y: lambda x, y=y: x == y for y in mylist} # dict-comprehension 

или вы можете использовать partial:

funcdict = {y: partial(operator.eq, y) for y in mylist} 

y вычисляется в то время как mylist повторяется.

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