2011-01-01 21 views
17

einen Blick auf das folgende Stück Code haben, der eine Liste Verständnis zeigt ..Python Liste Verständnis zwingende Wert

>>> i = 6 
>>> s = [i * i for i in range(100)] 
>>> print(i) 

Wenn Sie den Code beispielsweise in 2.6 Python ausführen druckt , aber Wenn Sie es in Python 3.x ausführen, druckt es .

Was war der Grund für das Verhalten zu ändern und warum ist der Ausgang in Python 3.x?

Vielen Dank im Voraus!

+2

Wow. Ich habe Glück, dass ich es hier gefunden habe, ich würde wochenlang nach dem Käfer suchen, wenn ich in meinem eigenen Code darauf stoße. +1 für Frage, -1 für Python :( – Kos

+0

Ähnliche Fragen hier: http://stackoverflow.com/questions/4198906/python-list-comprehension-rebind-names-even-after-scope-of-comprehension-is- –

Antwort

30

Das alte Verhalten war ein Fehler, konnte aber nicht einfach behoben werden, da sich einige Codes darauf stützten.

Die Variable i innerhalb der Liste Verständnis sollte eine andere i von dem einen auf der obersten Ebene sein. Logischerweise sollte es einen eigenen Umfang haben, der nicht außerhalb des Verständnisses liegt, da sein Wert nur innerhalb des Verständnisses Sinn ergibt. Aber in Python 2.x war der Bereich aufgrund eines Implementierungsdetails größer als notwendig, was dazu führte, dass die Variable in den äußeren Bereich "leckte", was zu verwirrenden Ergebnissen führte.

Python 3.0 war absichtlich nicht dazu gedacht, rückwärtskompatibel zu früheren Versionen zu sein, daher nutzten sie die Gelegenheit, dieses unerwünschte Verhalten zu beheben.

In Python 2.3 und späteren Releases "leckt" ein Listenverständnis die Steuervariablen von jedem, die es enthält, in den enthaltenden Bereich. Allerdings ist dieses Verhalten als veraltet, und es verlassen wird in Python 3,0

Source

7

nicht leben? Ja, es gibt einen Grund, und der Grund ist, dass sie nicht die temporäre Variable in einem wollten Listenverständnis auf, um in den äußeren Namensraum zu gelangen. Es ist also eine absichtliche Änderung, die darauf zurückzuführen ist, dass Listenergänzungen nun syntaktischer Zucker sind, um einen Generatorausdruck an list() zu übergeben.

Ref: PEP3100.

0

Sieht aus wie eine Änderung der Festlegung auf mich.

Ich habe Ihr Ergebnis in Python 2.6 bestätigt; es wird tatsächlich 99 gedruckt, was der letzte Wert ist, der i im Listenverständnis zugewiesen wurde.

4

Mark Byers antwortete perfekt.

nur als Randnotiz ..
in Python 2.x, wenn Sie Ihre Klammern Pars ändern (einen Generator Ausdruck anstelle einer Liste Verständnis zu schaffen), werden Sie feststellen, dass die Regelgröße ist nicht durchgesickert .

>>> i = 6 
>>> s = (i for i in range(100)) 
>>> print i 
6 

vs.

>>> i = 6 
>>> s = [i for i in range(100)] 
>>> print i 
99 

(natürlich in Python 3 ist dies festgelegt ist und Listenkomprehensionen Leck nicht mehr Stellgrößen)

+0

Das ist ein guter Punkt, aber es sollte auch beachtet werden, dass 's' auch keine Liste enthält, also müssen Sie' list (s) 'machen, um das gewünschte Endergebnis zu erhalten. – Keith

Verwandte Themen