Разберите поведение этого Python-фрагмента и объясните результат; for i in range(5): funcs = []; funcs.append(lambda: i); print([f() for f in funcs]) — что здесь не так и как исправить так, чтобы каждая функция возвращала своё i

25 Ноя 2025 в 11:36
20 +1
0
Ответы
1
Разбор поведения
Исходный фрагмент:
for i in range(5):
funcs = []
funcs.append(lambda: i)
print([f() for f in funcs])
Что происходит и почему:
- В этом коде список `funcs` создаётся внутри цикла и сразу содержит одну функцию, которая захватывает имя `i`.
- Эта функция вызывается немедленно в той же итерации, поэтому она возвращает текущее значение `i`.
- Поэтому вывод будет: [0][0][0], [1][1][1], [2][2][2], [3][3][3], [4][4][4] — по одному элементу в каждой итерации.
Типичная проблема замыканий (которая, вероятно, имелась в виду) проявляется, если вы хотите собрать все функции в список и вызвать их после цикла. Например:
funcs = []
for i in range(5):
funcs.append(lambda: i)
print([f() for f in funcs])
В этом случае все функции захватывают одно и то же имя `i` (late binding), и при вызове после цикла все вернут последнее значение `i` — [4,4,4,4,4][4,4,4,4,4][4,4,4,4,4].
Как исправить, чтобы каждая функция «захватила» своё значение `i`:
1) Использовать параметр по умолчанию у lambda (самый простой):
funcs = []
for i in range(5):
funcs.append(lambda i=i: i)
print([f() for f in funcs]) # -> [0, 1, 2, 3, 4]
2) Использовать фабрику функций:
def make(i):
return lambda: i
funcs = [make(i) for i in range(5)]
print([f() for f in funcs]) # -> [0, 1, 2, 3, 4]
3) Использовать functools.partial:
from functools import partial
funcs = []
for i in range(5):
funcs.append(partial(lambda x: x, i))
print([f() for f in funcs]) # -> [0, 1, 2, 3, 4]
Короткое объяснение механизма: lambda захватывает ссылку на переменную `i`, а не её текущее значение; использование `i=i` или явной фабрики создаёт новую локальную переменную со значением на момент создания, тем самым фиксируя его.
25 Ноя 2025 в 11:43
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир