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

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to