In che modo Python valuta esattamente gli attributi delle classi? Mi sono imbattuto in una stranezza interessante (in Python 2.5.2) che mi piacerebbe spiegare.Valutazione degli attributi di classe e generatori
Ho una classe con alcuni attributi che sono definiti in termini di altri, attributi definiti in precedenza. Quando provo a usare un oggetto generatore, Python genera un errore, ma se uso una semplice lista ordinaria, non ci sono problemi.
Ecco l'esempio sbucciato-giù. Si noti che l'unica differenza è che Brie
utilizza un'espressione di generatore, mentre Cheddar
utilizza una comprensione di lista.
# 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]
(Il mio caso reale era più complicato, e mi è stato la creazione di un dizionario, ma questo è l'esempio minima sono riuscito a trovare.)
mia unica ipotesi è che le list comprehension vengono calcolati in quella linea , ma le espressioni del generatore sono calcolate dopo la fine della classe, a quel punto l'ambito è cambiato. Ma non sono sicuro del motivo per cui l'espressione del generatore non agisca da chiusura e memorizzi il riferimento alla base nello scope sulla linea.
C'è una ragione per questo, e in caso affermativo, come devo pensare della meccanica di valutazione degli attributi di classe?