Eric Eric - 2 months ago 28
Python Question

NameError in nested comprehensions

I have this code in a file

class Sudoku(dict):
COLUMNS = [
{(x, y) for y in xrange(9)} for x in xrange(9)
]


When I run
python broken.py
, I get the traceback:

Traceback (most recent call last):
File "U:\broken.py", line 1, in <module>
class Sudoku(dict):
File "U:\broken.py", line 3, in Sudoku
{(x, y) for y in xrange(9)} for x in xrange(9)
File "U:\broken.py", line 3, in <setcomp>
{(x, y) for y in xrange(9)} for x in xrange(9)
NameError: global name 'x' is not defined
[Finished in 0.1s with exit code 1]


I don't really see the problem here. Isn't
x
defined in the comprehension?




What's stranger is how this seems to execute without an error when pasted directly into the python interpreter...




EDIT: This works if I use a list comprehension rather than a set comprehension

Answer

I've filed a bug here. This is still broken by design in python 2.7.5.

From the bug report:

In Python 2, list comprehensions don't have their own scope, so the x in your initial example lives at class scope. However, the set comprehension does have its own scope. By design, a variable defined at class scope is not visible to inner scopes inside that class.

In Python 3, this works because the list comprehension has its own scope.