Comment exactement Python évalue-t-il les attributs de classe? Je suis tombé sur une bizarrerie intéressante (en Python 2.5.2) que j'aimerais expliquer.Évaluation d'attribut de classe et générateurs
J'ai une classe avec certains attributs qui sont définis en termes d'autres attributs précédemment définis. Lorsque j'essaie d'utiliser un objet générateur, Python renvoie une erreur, mais si j'utilise une simple compréhension de liste ordinaire, il n'y a pas de problème.
Voici l'exemple simplifié. Notez que la seule différence est que Brie
utilise une expression de générateur, alors que Cheddar
utilise une compréhension de liste.
# 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]
(Mon cas réel est plus complexe, et je crée un dict, mais cela est l'exemple minimum que je pouvais trouver.)
Ma seule conjecture est que la liste compréhensions sont calculés à cette ligne , mais les expressions de générateur sont calculées après la fin de la classe, à quel point la portée a changé. Mais je ne sais pas pourquoi l'expression du générateur n'agit pas comme une fermeture et stocke la référence à la base dans la portée à la ligne.
Y at-il une raison à cela, et si oui, comment devrais-je penser à la mécanique d'évaluation des attributs de classe?