Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NameError in nested comprehensions [duplicate]

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

like image 362
Eric Avatar asked Sep 04 '12 08:09

Eric


People also ask

What is nested comprehension in Python?

It is a smart and concise way of creating lists by iterating over an iterable object. Nested List Comprehensions are nothing but a list comprehension within another list comprehension which is quite similar to nested for loops.

What are dictionary and list comprehensions in Python?

Python comprehensions are syntactic sugar constructs that provide a way to build a list, dictionary or set from a starting list, dictionary or set whilst altering or filtering elements. Comprehensions follow mathematical set builder notation rather than map and filter functions.


2 Answers

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.

like image 139
Eric Avatar answered Oct 18 '22 19:10

Eric


Wild guess, but Python set comprehensions were introduced with Python 2.7 and 3.0: would you happen to use an older version to execute your script, and a recent one as your interpreter ?


After looking at this section of the Python documentation, I see no explanation for this behavior. Furthermore, the fact that it works with list comprehension clearly show that it is not a scope issue.

I see only two possible reasons:

  • A bug in the set comprehensions implementation
  • The use of an anterior Python version which does not support set comprehensions.
like image 27
icecrime Avatar answered Oct 18 '22 19:10

icecrime