pavkozlov
@pavkozlov
Системный администратор

Почему список lambda выражений возвращает одинаковые числа?

Добрый день. На собеседовании на должность Python junа столкнулся с такой задачей:
Есть код:
l1 = [lambda: x for x in range(3)]
l2 = [f() for f in l1]
l2
>>> [2, 2, 2]


Собственно вопрос, почему так? Возникала мысль что это 3 ссылки на один и тот же объект. Но при этом:
>>> l1[0] is l1[1]
False
>>> l1[1] is l1[2]
False
>>> l1[0] == l1[2]
False


Даже идентификаторы у объектов разные:
>>> for i in l1:
...     print(id(i))
... 
139905582396416
139905582396552
139905582396688


Я был уверен что должен быть результат аналогичный:
>>> l3 = [i for i in range(3)]
>>> l3
[0, 1, 2]


К сожалению, интервьюер ответа не дал :(
  • Вопрос задан
  • 250 просмотров
Решения вопроса 2
sergey-gornostaev
@sergey-gornostaev Куратор тега Python
Седой и строгий
Все сгенерированные лямбды используют ссылку на переменную из включения. К моменту, их вызова включение уже завершило свою работу и x имеет значение последней итерации - 2. Чтобы избежать такого поведения, нужно замкнуть значение переменной: l1 = [lambda x=x: x for x in range(3)]
Ответ написан
Комментировать
alternativshik
@alternativshik
Потому что области видимости....
То выражение равносильно
l1 = [(lambda: x) for x in range(3)]
x == 2 потому что в результате лист компрехеншн он последний присваивается
А lambda потом использует этот "глобальный" x
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
NeiroNx
@NeiroNx
Программист
А обойти можно было:
l1=[eval('lambda:%d'%x) for x in range(3)]
Они конечно любят всякую ерунду спрашивать.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы