Приведён фрагмент Python: "funcs = [lambda x: x+i for i in range(3)]; print([f(0) for f in funcs])" — объясните результат, почему он появляется, и как переписать код, чтобы получить ожидаемое поведение

4 Янв в 04:22
16 +1
0
Ответы
1
Кратко: фрагмент выводит [2,2,2][2, 2, 2][2,2,2]. Почему — потому что лямбды захватывают переменную iii по ссылке (late binding), и к моменту вызова всех функций значение iii равно последнему значению из цикла (222), поэтому каждый f(0)f(0)f(0) даёт 0+2=20+2=20+2=2.
Пример (ваш код):
```
funcs = [lambda x: x+i for i in range(3)]
print([f(0) for f in funcs]) # -> [2, 2, 2]
```
Как исправить (варианты):
1) Привязать текущее значение iii как значение по умолчанию:
```
funcs = [lambda x, i=i: x+i for i in range(3)]
print([f(0) for f in funcs]) # -> [0, 1, 2]
```
2) Использовать фабрику функций:
```
def make(i):
return lambda x: x + i
funcs = [make(i) for i in range(3)]
print([f(0) for f in funcs]) # -> [0, 1, 2]
```
3) Использовать functools.partial:
```
from functools import partial
def add(i, x): return x + i
funcs = [partial(add, i) for i in range(3)]
print([f(0) for f in funcs]) # -> [0, 1, 2]
```
Итого: проблема — захват переменной цикла по ссылке; решение — зафиксировать текущие значения iii (например, через аргумент по умолчанию, фабрику или partial), тогда получите ожидаемый результат [0,1,2][0, 1, 2][0,1,2].
4 Янв в 04:29
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир