NameError при вложенных установках

У меня есть этот код в файле

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

Когда я запускаю python broken.py, я получаю трассировку:

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]

Я действительно не вижу проблемы здесь. Разве не x определено в понимании?


Какая странность заключается в том, как это, кажется, выполняется без ошибки при вставке непосредственно в интерпретатор python...


EDIT. Это работает, если я использую понимание списка, а не набор понятий

Ответы

Ответ 1

Я подал ошибку здесь. Это все еще сломанный по дизайну в python 2.7.5.

Из отчета об ошибке:

В Python 2 в представлениях списков нет собственной области видимости, поэтому x в вашем первом примере живет в классе. Тем не менее, установленное понимание действительно имеет свою собственную область. По дизайну переменная, определенная в области класса, не видна внутренним областям внутри этого класса.

В Python 3 это работает, потому что понимание списка имеет свою собственную область.

Ответ 2

Дикая догадка, но Python установил понимание с помощью Python 2.7 и 3.0: вы бы использовали более старую версию для выполнения своего script и недавнего в качестве вашего интерпретатора?


Посмотрев этот раздел документации Python, я не вижу объяснений этого поведения. Более того, тот факт, что он работает со списком, ясно показывает, что это не проблема сферы.

Я вижу только две возможные причины:

  • Ошибка реализации набора понятий
  • Использование передней Python-версии, которая не поддерживает установки.

Ответ 3

Боюсь, я понятия не имею, почему ваш код не работает, однако, следующие работы и дает вам то, что вы хотите:

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

Возможно, некоторые из гуру python на этом сайте могут рассказать нам, почему ваш фрагмент кода не работает.

Ответ 4

Мне хотелось бы дать теоретическое объяснение, но это работает:

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

if __name__ == "__main__":
    s = Sudoku()
    print s.COLUMNS

Ответ 5

Возможно, это то, что вы действительно хотите:

[[{x:y} for x in xrange(9)] for y in xrange(9)]