[Python-de] Namens-Lookup in Comprehensions
Stefan Behnel
python-de at behnel.de
Sa Aug 6 06:58:37 CEST 2011
Torsten Bronger, 06.08.2011 04:08:
> Folgender Code:
>
> class Test(object):
> s = 2
> dict([(x, s) for x in range(10)])
> dict((x, s) for x in range(10))
>
> Warum bricht Python (zumindest CPython) die Ausführung der letzten
> Zeile ab, weil er "s" nicht findet?
>
> CPython3 mag schon die Zeile davor nicht. Ich weiß, daß Python3
> dahingehend geändert wurde, daß "x" nicht mehr nach draußen sichtbar
> ist, aber darum geht es hier ja nicht.
>
> Und überhaupt: Was ist der Grund, warum in solchen Ausdrücken der
> Klassenvariablen-Namensraum quasi übersprungen wird und der
> Interpreter gleich im umgebenden Namensraum sucht?
Klassen haben in Python keinen Scope. Das hat erstmal auch nichts mit
Generator-Expressions zu tun. Siehe z.B.
http://stackoverflow.com/questions/1765677/python-nested-classes-scope
Die Python-Doku enthält einen längeren Abschnitt über Scopes und Namespaces.
http://docs.python.org/tutorial/classes.html#python-scopes-and-namespaces
> Man kann das Beispiel noch etwas weitertreiben:
>
> def super():
> s = 4
> class Test(object):
> s = 2
> print(dict([(x, s) for x in range(10)]))
> print(dict((x, s) for x in range(10)))
> super()
>
> Führt das mal in python und python3 aus. Das Ergebnis ist in beiden
> Fällen unterschiedlich (soweit okay) aber auch in beiden Fällen --
> gelinde gesagt -- überraschend.
Na ja, sagen wir mal, es ist inkonsistent in Python 2.x, wo
List-Comprehensions noch keinen eigenen Scope hatten. Das führt dann zu
solchen Auswüchsen hier:
Python 2.7.1+ (2.7:c821d3d335e8, Apr 22 2011, 18:45:36)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def super():
... s = 4
... class Test(object):
... s = 2
... print(dict([(x, s) for x in range(10)]))
... print({x : s for x in range(10)})
... print(dict((x, s) for x in range(10)))
...
>>> super()
{0: 2, 1: 2, 2: 2, 3: 2, 4: 2, 5: 2, 6: 2, 7: 2, 8: 2, 9: 2}
{0: 4, 1: 4, 2: 4, 3: 4, 4: 4, 5: 4, 6: 4, 7: 4, 8: 4, 9: 4}
{0: 4, 1: 4, 2: 4, 3: 4, 4: 4, 5: 4, 6: 4, 7: 4, 8: 4, 9: 4}
Das wurde in Python 3 vereinheitlicht und nun funktionieren die Scopes von
Generator-Expressions und allen Comprehensions genauso wie die von Funktionen.
Stefan
Mehr Informationen über die Mailingliste python-de