Лямбда и замыкания в цикле Python
@python_quizРазберем этот квиз
Коротко: небольшой фрагмент кода с лямбда-функциями в списковом включении часто неожиданно возвращает одно и то же значение для всех функций. Ниже объясню почему так происходит и как этого избежать.
Код задачи

Что происходит и почему
- В лямбдах используются переменные из внешней области видимости — это называется замыканием.
- Лямбда не захватывает *значение* переменной в момент создания, она захватывает ссылку на саму переменную.
- После завершения прохода по range(3) последним значением переменной i становится 2. Все лямбды ссылаются на ту же самую переменную i, поэтому при вызове они возвращают текущее (финальное) значение — 2.
Демонстрация (поведение при запуске):

> Вывод: 2 2
Замечание о версии Python: в Python 3 list comprehension создаёт собственную локальную область видимости для переменной цикла, но лямбды внутри всё равно замыкают эту переменную. Поэтому итоговое поведение (все функции возвращают последнее значение) сохраняется.
Анализ вариантов (кратко)
- "Выведет: 0 2" — такое ожидание возникает, если думать, что каждая лямбда захватывает текущее значение i. Но лямбда захватывает переменную, а не её моментальное значение.
- "Выведет: 2 2" — именно то, что происходит: все функции возвращают последнее значение переменной цикла.
- "Выведет: 0 1" — невозможно в данном фрагменте, потому что к моменту вызова обе функции смотрят на одну и ту же переменную.
- "Ошибка выполнения" — ошибка не возникает; код корректен и отработает, вернув описанное значение.
Как получить "ожидаемое" поведение (каждая функция — своё значение)
Если нужно, чтобы каждая лямбда запоминала текущее значение i при создании, есть несколько распространённых способов:
1) Использовать значение по умолчанию аргумента функции:

2) Сделать фабрику функций:

3) Использовать functools.partial (аналогично фиксированию аргумента):

Все три приёма создают для каждой функции собственное закреплённое значение, вместо общей переменной цикла.
Вывод
При работе с лямбдами и замыканиями важно помнить: замыкается переменная, а не её текущее значение. В практических задачах, когда нужно "запомнить" текущее значение в цикле, используйте параметр по умолчанию, фабрику функций или partial. Это простые и надёжные способы получить ожидаемое поведение.