NameError во вложенных представлениях [duplicate]

На этот вопрос уже есть ответ здесь:

Доступ к переменным класса из списка понимания в определении класса 5 ответов

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

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 
    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 
    {(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 ...

РЕДАКТИРОВАТЬ: Это работает, если я использую понимание списка, а не заданное понимание

 user64777204 сент. 2012 г., 10:45
Я могу воспроизвести эту проблему с Python 2.7: он работает в IPython и дает исключение при выполнении в виде скрипта.
 Michał Górny04 сент. 2012 г., 10:31
Эээ, яМне просто интересно, если вы точно хотите наборы в списке. Это кажется немного несимметричным :).
 Michał Górny04 сент. 2012 г., 10:27
Просто чтобы прояснить: не могли бы вы датьточный ожидаемый результат? Я'мне просто интересно, если этоэто именно то, что вы хотите, или если вы будете выполнять еще немного магии позже.
 grifaton04 сент. 2012 г., 11:10
Проблема в том, что понимание находится внутри определения класса. Я подозреваю, что люди, видящие код, работающий в интерпретаторе, просто пытаются понять, а не определить класс.
 mg.06 сент. 2012 г., 09:20
@Eric: вы правы, я думал, что понимание внешнего списка установилоx переменная в блоке класса. Это не так, понимание списка создает новую область.
 user70765004 сент. 2012 г., 11:13
На самом деле, используя интерпретатор 2.7, он тоже ломается. Убедитесь, что вы включили полное определение класса, а не только строку с пониманием. Проблема, очевидно, заключается в том, что локальная переменнаяx Безразлично»Т транспортируется в понимание короткого набора. Я'd подайте это как ошибку; посмотрим что получится
 Eric05 сент. 2012 г., 09:59
@ МГ: Эта ошибка, кажется, относится к чему-то другому - яЯ не пытаюсь ссылаться на любую переменную уровня класса здесь.
 Paolo Moretti04 сент. 2012 г., 10:41
Он отлично работает на Python 3.2 (заменаxrange сrange). Это похоже на ошибку 2.7 (в заданном понимании backport).
 mg.04 сент. 2012 г., 11:31
Эта ошибка теперь устранена, обновите версию Python.Выпуск 11796.
 Eric04 сент. 2012 г., 10:44
@PaoloMoretti: да, ям на 2,7 здесь
 John La Rooy04 сент. 2012 г., 10:53
Еще хуже - если естьявляется глобальныйx, он будет использовать это значение вместо значения из списка.
 Lee Netherton04 сент. 2012 г., 10:31
Это очень странно. Кажется, это очень специфическая проблема, возникающая при использовании понимания вложенного множества в качестве статической переменной-члена. Все остальные комбинации, которые я пробовал, работают, но не эта конкретная комбинация. Смею ли я сказать ошибку в Python? Удушье!
 Eric04 сент. 2012 г., 10:28
@ MichałGóЛюбой вывод без ошибок был бы хорош здесь ...

Ответы на вопрос(5)

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

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
 omu_negru04 сент. 2012 г., 11:39
я могу говорить из моего $, но, возможно, попытка определить COLUMNS как статический член класса делает набор пониманий свободным и проверяет наличие x в списке глобальных переменных (что, во всяком случае, не имеет смысла для меня, смотришь на него). Возможно сообщить как ошибку?

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

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

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

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

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

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

Ошибка в реализации заданного пониманияИспользование предшествующей версии Python, которая не поддерживает набор пониманий.
Решение Вопроса

мы подали ошибкуВот, Этовсе еще сломан дизайн в Python 2.7.5.

Из сообщения об ошибке:

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

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

Может быть, это то, что вы действительно хотите:

[[{x:y} for x in xrange(9)] for y in xrange(9)]
 Pascal Bugnion04 сент. 2012 г., 10:29
Ничего нет "априори" не так с ОП 'установить понимание. Если вы порежете его и вставите в интерпретатор, он даст ожидаемый ответ.
 MaxPowers04 сент. 2012 г., 10:51
Мой интерпретатор вызвал ошибку SyntaxError, поэтому я подумал, что что-то не так. Поэтому я разместил этот ответ, который работает на моей машине. Потом я узнал, что это только потому, что ям еще использую 2.6 :)

Ваш ответ на вопрос