Klassenattributauswertung und Generatoren

Wie genau wertet Python Klassenattribute aus? Ich bin über eine interessante Eigenheit gestolpert (in Python 2.5.2), die ich gerne erklärt hätte.

Ich habe eine Klasse mit einigen Attributen, die in Bezug auf andere, zuvor definierte Attribute definiert sind. Wenn ich versuche, ein Generator-Objekt zu verwenden, gibt Python einen Fehler aus, aber wenn ich ein einfaches gewöhnliches Listenverständnis verwende, gibt es kein Problem.

Hier ist das reduzierte Beispiel. Beachten Sie, dass der einzige Unterschied darin bestehtBrie verwendet einen Generatorausdruck, währendCheddar verwendet ein Listenverständnis.

# 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]

(Mein tatsächlicher Fall war komplizierter und ich erstellte ein Diktat, aber dies ist das kleinste Beispiel, das ich finden konnte.)

Ich vermute nur, dass das Listenverständnis in dieser Zeile berechnet wird, aber die Generatorausdrücke werden nach dem Ende der Klasse berechnet. Zu diesem Zeitpunkt hat sich der Gültigkeitsbereich geändert. Ich bin mir jedoch nicht sicher, warum der Generatorausdruck nicht als Abschluss fungiert und den Verweis auf base im Gültigkeitsbereich in der Zeile speichert.

Gibt es einen Grund dafür und wenn ja, wie sollte ich über die Bewertungsmechanik von Klassenattributen nachdenken?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage