Дан код на Python: funcs = [lambda x: i*x for i in range(4)]; print([f(2) for f in funcs]). Объясните, что напечатает этот код и почему, какие механизмы замыканий задействованы, и предложите три способа изменить код, чтобы получить ожидаемые результаты [0,2,4,6]

20 Окт в 16:39
4 +1
0
Ответы
1
Код напечатает \([6,6,6,6]).
Почему: в comprehension каждая лямбда замыкает имя `i`, а не его текущее значение. После выполнения `for i in range(4)` окончательное значение `i` равно `3`, поэтому при вызове каждой функции `f(2)` берёт текущее `i=3` и возвращает \((3\cdot 2 = 6)\).
Механизм: замыкание в Python захватывает ссылку на переменную (late binding) — имя будет разрешаться при вызове функции, а не при её создании.
Три способа получить ожидаемый результат \([0,2,4,6]):
1) Захват значения через аргумент по умолчанию:
```python
funcs = [lambda x, i=i: i*x for i in range(4)]
print([f(2) for f in funcs]) # [0, 2, 4, 6]
```
Аргумент `i=i` вычисляется при создании лямбды и фиксирует текущее значение.
2) Фабрика функций (локальная переменная в новой области):
```python
def make(i):
return lambda x: i*x
funcs = [make(i) for i in range(4)]
print([f(2) for f in funcs]) # [0, 2, 4, 6]
```
Каждый вызов `make(i)` создаёт новую закрытую переменную `i`.
3) Использовать `functools.partial` или `operator.mul`:
```python
from functools import partial
import operator
funcs = [partial(operator.mul, i) for i in range(4)]
print([f(2) for f in funcs]) # [0, 2, 4, 6]
```
`partial(operator.mul, i)` фиксирует первый аргумент равным `i`, возвращая функцию от второго аргумента.
20 Окт в 17:08
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир