Понимание словаря с лямбда-функциями дает неправильные результаты

Я попробовал следующий код в Python 3.5.1:

>>> f = {x: (lambda y: x) for x in range(10)}
>>> f[5](3)
9

Очевидно, что это должно возвращать 5. Я не понимаю, откуда приходит другая ценность, и я ничего не смог найти.

Кажется, что это связано с ссылкой - он всегда возвращает ответ f[9], который является последней назначенной функцией.

Какая ошибка здесь и как это сделать, чтобы она работала правильно?

Ответы

Ответ 1

Обзор Python лексический. Закрытие будет ссылаться на имя и область действия переменной, а не на фактический объект/значение переменной.

Что происходит, так это то, что каждая лямбда захватывает переменную x, а не значение x.

В конце цикла переменная x привязана к 9, поэтому каждая лямбда будет ссылаться на это x, значение которой равно 9.

Почему работает ответ @ChrisP:

make_func заставляет оценивать значение x (поскольку оно передается в функцию). Таким образом, лямбда производится со значением x в настоящее время и мы избегаем вышеуказанной проблемы с охватом.

def make_func(x):
    return lambda y: x

f = {x: make_func(x) for x in range(10)}

Ответ 2

Следующее должно работать:

def make_func(x):
    return lambda y: x

f = {x: make_func(x) for x in range(10)}

x в вашем коде заканчивается ссылкой на последнее значение x, которое равно 9, но по моему это относится к x в области функций.