I just read the answer to this question: Accessing class variables from a list comprehension in the class definition
It helps me to understand why the following code
data
is the source of the list comprehension; it is the one parameter that is passed to the nested scope created.
Everything in the list comprehension is run in a separate scope (as a function, basically), except for the iterable used for the left-most for
loop. You can see this in the byte code:
>>> 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
The <listcomp>
code object is called like a function, and iter(data)
is passed in as the argument (CALL_FUNCTION
is executed with 1 positional argument, the GET_ITER
result).
The <listcomp>
code object looks for that one argument:
>>> 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
The LOAD_FAST
call refers to the first and only positional argument passed in; it is unnamed here because there never was a function definition to give it a name.
Any additional names used in the list comprehension (or set or dict comprehension, or generator expression, for that matter) are either locals, closures or globals, not parameters.