Erweiterte Geschachtelte List-Comprehension-Syntax
Ich war Herumspielen mit Liste Verstehens, um ein besseres Verständnis von Ihnen und ich lief in einige unerwartete Ausgabe, ich bin nicht in der Lage zu erklären. Ich habe nicht gefunden diese Frage gestellt, bevor, aber wenn es /ist/ein wiederholen Sie die Frage bitte ich zu entschuldigen.
War ich im wesentlichen beim schreiben einer generator, Generatoren erzeugt. Eine einfache generator, der verwendet-Liste Verständnis würde so Aussehen:
(x for x in range(10) if x%2==0) # generates all even integers in range(10)
Was ich versucht habe zu tun war, schreiben einen generator, der erzeugt mit zwei Generatoren - von denen das erste erzeugt die geraden zahlen im Bereich(10) und das zweite generiert die ungeraden zahlen in der Reihe(10). Für diese habe ich:
>>> (x for x in range(10) if x%2==i for i in range(2))
<generator object <genexpr> at 0x7f6b90948f00>
>>> for i in g.next(): print i
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>> g = (x for x in range(10) if x%2==i for i in range(2))
>>> g
<generator object <genexpr> at 0x7f6b90969730>
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
Ich nicht verstehen, warum 'ich' verwiesen wird vor der Zuweisung
Dachte ich, es hätte etwas zu tun mit i in range(2)
, so habe ich getan:
>>> g = (x for x in range(10) if x%2==i for i in [0.1])
>>> g
<generator object <genexpr> at 0x7f6b90948f00>
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
Dieser hat nicht Sinn für mich, so dass ich dachte, es am besten zu versuchen, etwas einfacher ersten. Also ging ich zurück zu den Listen und ausprobiert:
>>> [x for x in range(10) if x%2==i for i in range(2)]
[1, 1, 3, 3, 5, 5, 7, 7, 9, 9]
welche ich voraussichtlich das gleiche wie:
>>> l = []
>>> for i in range(2):
... for x in range(10):
... if x%2==i:
... l.append(x)
...
>>> l
[0, 2, 4, 6, 8, 1, 3, 5, 7, 9] # so where is my list comprehension malformed?
Aber wenn ich versuchte es auf eine Ahnung, das funktionierte:
>>> [[x for x in range(10) if x%2==i] for i in range(2)]
[[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]] # so nested lists in nested list comprehension somehow affect the scope of if statements? :S
So, ich dachte, es könnte ein problem mit dem, was Niveau der Umfang der if
- Anweisung arbeitet. Also versuchte ich Folgendes:
>>> [x for x in range(10) for i in range(2) if x%2==i]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Und jetzt bin ich gründlich verwirrt. Kann mir bitte jemand erklären dieses Verhalten. Ich verstehe nicht, warum meine Liste Verstehens zu sein scheinen fehlerhaft ist, noch verstehe ich, wie die Bereiche der if
- Anweisungen arbeiten.
PS: Beim Korrekturlesen die Frage, merkte ich, dass es sieht ein wenig wie eine Hausaufgaben-Frage - ist es nicht.
- Hast
[x for x in range(10) if x%2==i for i in range(2)]
Arbeit? Ich bin immerNameError: name 'i' is not defined
(Python 2.6.2) - Ich habe genau das bekommen, was Sie bekam (Python 2.6.5)
- Verwandte: Python list comprehension rebind Namen auch nach dem Umfang des Verständnisses. Ist das richtig?
Du musst angemeldet sein, um einen Kommentar abzugeben.
müssen Sie einige Klammern:
Arbeitete, weil eine Vorherige Liste Verständnis Leckagen der i-Variablen auf den umgebenden Rahmen, und dem ich für die aktuellen. Starten Sie eine frische python-interpreter, und das würde zu einem Fehler, da Fehler. Der Zähler ist undicht Verhalten entfernt wurde in Python 3.
EDIT:
Die äquivalente for-Schleife:
wäre:
das gibt auch einen name-Fehler.
EDIT2:
den parenthesed version:
ist äquivalent zu:
Liegen Ryan die for-Schleife äquivalent führt mich zu der folgenden, die scheint zu funktionieren:
Ausgänge
Erweiterung Liegen auf Ryan ' s Antwort ein wenig:
etwas = (x for x in range(10) if x%2==i for i in range(2))
ist äquivalent zu:
in der Erwägung, dass die parenthesised-version ist äquivalent zu:
Diese tatsächlich ergeben die beiden Generatoren:
Leider sind die Generatoren, die er liefert, sind etwas instabil, da der Ausgang wird davon abhängen, wie Sie verbrauchen Sie:
Mein Tipp: schreiben Sie die generator-Funktionen in voller: ich denke, zu versuchen, um die korrekte Festlegung des lösungsumfangs auf
i
ohne dabei sein können alle, aber unmöglich.list()
Ursachen es beginnt bei 1 statt 0? (getestet habe ich es mit mehr Generatoren, sieht aus wie die Generatoren sind alle die gleiche Sache zu tun)x%2==i
. Der erste Weg setzti
zu0
dann ergibt sich ein generator verbraucht wird, zu geben, die auch zahlen, danni
wird 1 und ein weiterer generator zurückgegeben, die Ihnen ungeraden Nummern, N. B. es war das gleichei
jedes mal nur mit anderen Werten. Mitlist(gens)
bedeutet, dass beide Generatoren sind so angelegti
festgelegt wurde1
bevor Sie verbrauchen entweder generator.i
ist nicht freigegeben für den ersten Fall?i
ist immer geteilt, aber im ersten Fall die gens sind parallel mit der äußeren Schleife, während im zweiten Fall die gens ausgeführt, nachdem die äußere Schleife wird beendet, so dass Sie beide bekommen den letzten Wert von i ist. Warum isti
nicht eine Kopie, d.h. die Generatoren handeln wie Verschlüsse?Lüge ist die Antwort auf die syntaktische Frage. Ein Vorschlag: nicht Sachen so viel in den Körper eines Generators. Eine Funktion ist viel besser lesbar.