Ответ 1
data
является источником понимания списка; это единственный параметр, который передается в созданную вложенную область.
Все в понимании списка выполняется в отдельной области (как функция, в основном), за исключением итерации, используемой для самого левого цикла for
. Вы можете увидеть это в байтовом коде:
>>> def foo():
... return [i for i in data]
...
>>> dis.dis(foo)
2 0 LOAD_CONST 1 (<code object <listcomp> at 0x105390390, file "<stdin>", line 2>)
3 LOAD_CONST 2 ('foo.<locals>.<listcomp>')
6 MAKE_FUNCTION 0
9 LOAD_GLOBAL 0 (data)
12 GET_ITER
13 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
16 RETURN_VALUE
Объект кода <listcomp>
вызывается как функция, а iter(data)
передается в качестве аргумента (CALL_FUNCTION
выполняется с 1 позиционным аргументом, результатом GET_ITER
).
Объект кода <listcomp>
ищет этот один аргумент:
>>> dis.dis(foo.__code__.co_consts[1])
2 0 BUILD_LIST 0
3 LOAD_FAST 0 (.0)
>> 6 FOR_ITER 12 (to 21)
9 STORE_FAST 1 (i)
12 LOAD_FAST 1 (i)
15 LIST_APPEND 2
18 JUMP_ABSOLUTE 6
>> 21 RETURN_VALUE
Вызов LOAD_FAST
относится к первому и только позиционному аргументу, переданному; он не называется здесь, потому что никогда не было определения функции, чтобы дать ему имя.
Любые дополнительные имена, используемые в понимании списка (или, например, для установки или определения dict или выражения генератора), являются либо локальными, либо закрывающими, либо глобальными, а не параметрами.