Как именно Python оценивает атрибуты класса? Я наткнулся на интересную причуду (в Python 2.5.2), которую я хотел бы объяснить.Оценка атрибутов класса и генераторы
У меня есть класс с некоторыми атрибутами, которые определены в терминах других ранее определенных атрибутов. Когда я пытаюсь использовать объект-генератор, Python выдает ошибку, но если я использую простое обычное понимание списка, нет никаких проблем.
Вот пример урезанного. Обратите внимание, что единственная разница заключается в том, что Brie
использует выражение генератора, а Cheddar
использует понимание списка.
# Using a generator expression as the argument to list() fails
>>> class Brie :
... base = 2
... powers = list(base**i for i in xrange(5))
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in Brie
File "<stdin>", line 3, in <genexpr>
NameError: global name 'base' is not defined
# Using a list comprehension works
>>> class Cheddar :
... base = 2
... powers = [base**i for i in xrange(5)]
...
>>> Cheddar.powers
[1, 2, 4, 8, 16]
# Using a list comprehension as the argument to list() works
>>> class Edam :
... base = 2
... powers = list([base**i for i in xrange(5)])
...
>>> Edam.powers
[1, 2, 4, 8, 16]
(мой фактический случай был более сложным, и я создавал Dict, но это минимальный пример, который я смог найти.)
Моя только догадка, что списочные вычисляются на этой линии , но выражения генератора вычисляются после окончания класса, после чего область изменений изменилась. Но я не уверен, почему выражение генератора не действует как замыкание и сохраняет ссылку на базу в области на линии.
Есть ли причина для этого, и если да, то как я должен думать о механизме оценки атрибутов класса?