Odd name shadowing in comprehension

Chris Angelico rosuav at gmail.com
Sat Oct 22 19:57:46 EDT 2016


This surprised me.

Python 3.4.2 (default, Oct  8 2014, 10:45:20)
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> y=6
>>> [(x,y) for x in range(y) for y in range(3)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2,
2), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2), (5, 0), (5, 1),
(5, 2)]
>>> [(x,y) for x in range(3) for z in range(y) for y in range(3)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
UnboundLocalError: local variable 'y' referenced before assignment

Normally, a comprehension is described as being equivalent to an
unrolled loop, inside a nested function. That would be like this:

def temp():
    ret = []
    for x in range(y):
        for y in range(3):
            ret.append((x,y))
    return ret
temp()

But it seems that the first iterator (and only that one) is evaluated
in the parent context:

def temp(iter):
    ret = []
    for x in iter:
        for y in range(3):
            ret.append((x, y))
    return ret
temp(iter(range(y)))

Why is this? It seems rather curious.

ChrisA



More information about the Python-list mailing list