Рассмотрите пример на Python: funcs = [lambda x: i*x for i in range(3)]; что выведет funcs[0](2) и почему, как исправить, если требуется захват текущего значения i при создании каждого замыкания

22 Янв в 09:51
12 +1
0
Ответы
1
Ответ: funcs[0](2) вернёт 4.
Пояснение: в выражении
funcs = [lambda x: i*x for i in range(3)]
переменная iii имеет значения 0,1,20,1,20,1,2 в ходе итерации, но лямбды захватывают саму переменную, а не её текущее значение (late binding). После завершения цикла iii равно 222, поэтому при вызове любой из фукнций вычисляется 2∗2=42*2=422=4.
Исправления (чтобы захватить текущее значение iii при создании замыкания):
1) Через аргумент по умолчанию (самый простой):
funcs = [lambda x, i=i: i*x for i in range(3)]
Теперь funcs[0](2) даст 000, funcs[1](2) — 222, funcs[2](2) — 444.
2) Через фабрику функций:
def make(i):
return lambda x: i*x
funcs = [make(i) for i in range(3)]
3) Через functools.partial:
from functools import partial
def mul(i, x): return i*x
funcs = [partial(mul, i) for i in range(3)]
Везде выше переменная iii фиксируется при создании каждой функции, поэтому замыкания работают как ожидается.
22 Янв в 09:58
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир