List comprehension - NameError: name '_[1]' is not defined ?

Terry Reedy tjreedy at udel.edu
Thu Jan 15 17:35:16 EST 2009


Peter Otten wrote:

> List comprehensions delete the helper variable after completion:

I do not believe they did in 2.4.  Not sure of 2.5.  There is certainly 
  a very different implementation in 3.0 and, I think, 2.6.  OP 
neglected to mention Python version he tested on. Code meant to run on 
2.4 to 3.0 cannot depend on subtle listcomp details.

>>>> def f(): [i for i in [1]]
> ...
>>>> dis.dis(f)
>   1           0 BUILD_LIST               0
>               3 DUP_TOP
>               4 STORE_FAST               0 (_[1])
>               7 LOAD_CONST               1 (1)
>              10 BUILD_LIST               1
>              13 GET_ITER
>         >>   14 FOR_ITER                13 (to 30)
>              17 STORE_FAST               1 (i)
>              20 LOAD_FAST                0 (_[1])
>              23 LOAD_FAST                1 (i)
>              26 LIST_APPEND
>              27 JUMP_ABSOLUTE           14
>         >>   30 DELETE_FAST              0 (_[1])
>              33 POP_TOP
>              34 LOAD_CONST               0 (None)
>              37 RETURN_VALUE
>

In 3.0
 >>> def f(): [i for i in [1]]

 >>> import dis
 >>> dis.dis(f)
   1           0 LOAD_CONST               1 (<code object <listcomp> at 
0x01349BF0, file "<pyshell#12>", line 1>)
               3 MAKE_FUNCTION            0
               6 LOAD_CONST               2 (1)
               9 BUILD_LIST               1
              12 GET_ITER
              13 CALL_FUNCTION            1
              16 POP_TOP
              17 LOAD_CONST               0 (None)
              20 RETURN_VALUE

Running OP code in 3.0 with print ()s added gives

pre 0.a 1.b 2.c 3.d  post

Traceback (most recent call last):
   File "C:\Programs\Python30\misc\temp7.py", line 32, in <module>
     """ % gie)
   File "C:\Programs\Python30\misc\temp7.py", line 8, in __getitem__
     return eval(expr, self.globals, self.locals)
   File "<string>", line 7, in <module>
   File "<string>", line 7, in <listcomp>
   File "C:\Programs\Python30\misc\temp7.py", line 12, in ts
     return ts % self
   File "C:\Programs\Python30\misc\temp7.py", line 8, in __getitem__
     return eval(expr, self.globals, self.locals)
   File "<string>", line 2, in <module>
   File "<string>", line 1, in <listcomp>
NameError: global name 'i' is not defined

> If you manage to run two nested listcomps in the same namespace you get a
> name clash and the inner helper variable overwrites/deletes the outer:
> 
>>>> def xeval(x): return eval(x, ns)
> ...
>>>> ns = dict(xeval=xeval)
>>>> xeval("[xeval('[k for k in ()]') for i in (1,)]")
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "<stdin>", line 1, in xeval
>   File "<string>", line 1, in <module>
> NameError: name '_[1]' is not defined

Which Python?  3.0 prints "[[]]"! But I think the nested listcomp *is* 
in a separate namespace here.  I will leave it to you or OP to disect 
how his and your code essentially differ from 3.0 (and maybe 2.6) 
implementation's viewpoint.

Terry Jan Reedy




More information about the Python-list mailing list