Ocena atrybutów klasy i generatory
Jak dokładnie Python ocenia atrybuty klasy? Natknąłem się na ciekawy dziwak (w Pythonie 2.5.2), który chciałbym wyjaśnić.
Mam klasę z pewnymi atrybutami, które są zdefiniowane w kategoriach innych, wcześniej zdefiniowanych atrybutów. Kiedy próbuję użyć obiektu generatora, Python zgłasza błąd, ale jeśli używam zwykłego zwykłego rozumienia listy, nie ma problemu.
Oto przykład skrócony. Zauważ, że jedyną różnicą jest toBrie
używa wyrażenia generatora, podczas gdyCheddar
używa rozumienia listy.
# 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]
(Moja rzeczywista sprawa była bardziej skomplikowana i tworzyłem dyktat, ale jest to minimalny przykład, jaki mogłem znaleźć.)
Domyślam się, że wyrażenia listy są obliczane w tej linii, ale wyrażenia generatora są obliczane po zakończeniu klasy, w którym to momencie zakres się zmienił. Ale nie jestem pewien, dlaczego wyrażenie generatora nie działa jako zamknięcie i przechowuje odniesienie do bazy w zakresie na linii.
Czy jest ku temu powód, a jeśli tak, to jak powinienem myśleć o mechanice oceny atrybutów klasowych?