python : Listenindex außerhalb des gültigen Bereichs Fehler beim iterativen Popup von Elementen
Lesezeit: 5 Minuten
ein Fernseher
Ich habe ein einfaches Python-Programm geschrieben
l=[1,2,3,0,0,1]
for i in range(0,len(l)):
if l[i]==0:
l.pop(i)
Dies gibt mir online den Fehler “Listenindex außerhalb des Bereichs”. if l[i]==0:
Nach dem Debuggen konnte ich das herausfinden i wird erhöht und die Liste wird reduziert.
Ich habe jedoch eine Schleifenbeendigungsbedingung i < len(l). Warum erhalte ich dann einen solchen Fehler?
“Ich habe Schleifenabbruchbedingung i < len(l)" Warum sagen Sie das? Wo in deinem Code siehst du das?
– S. Lott
25. November 09 um 18:02 Uhr
@ S. Lott , i in range(0,len()) bedeutet ‘ich werde bis len(l)-1 gehen’
– ein Fernseher
25. November 09 um 18:06 Uhr
Ein weiterer Python-Tipp – Sie hätten einfach schreiben können range(len(l))da 0 der Standardstartwert ist.
– Abgrund
25. November 09 um 18:07 Uhr
Ab PEP8: Verwenden Sie niemals die Zeichen l (Kleinbuchstabe el), O (Großbuchstabe oh) oder I (Großbuchstabe Auge) als Einzelzeichen-Variablennamen.python.org/dev/peps/pep-0008
– Stefan202
25. November 09 um 18:09 Uhr
@atv: Was dich zum Nachdenken anregt range(0,len(l)) hat ein Ergebnis, das variiert, wenn l ist geändert? Warum denkst du, dass? Wo hast du es gelesen?
– S. Lott
25. November 09 um 23:44 Uhr
Mark Ruschakoff
Sie reduzieren die Länge Ihrer Liste l Wenn Sie darüber iterieren, also wenn Sie sich dem Ende Ihrer Indizes in der Range-Anweisung nähern, sind einige dieser Indizes nicht mehr gültig.
Es sieht aus wie, was Sie tun möchten, ist:
l = [x for x in l if x != 0]
die eine Kopie von zurückgibt l ohne eines der Elemente, die Null waren (diese Operation heißt a Listenverständnis, übrigens). Sie könnten diesen letzten Teil sogar auf nur verkürzen if xda Zahlen ungleich Null ausgewertet werden True.
Es gibt keine Endbedingung der Schleife i < len(l)so wie du den Code geschrieben hast, weil len(l) ist Vorvor der Schleife berechnet, nicht bei jeder Iteration neu ausgewertet. Sie könnten schreibe es aber so:
i = 0
while i < len(l):
if l[i] == 0:
l.pop(i)
else:
i += 1
Der Ausdruck len(l) wird nur einmal ausgewertet, im Moment die range() Builtin wird ausgewertet. Das damals konstruierte Bereichsobjekt ändert sich nicht; es kann unmöglich etwas über das Objekt wissen l.
PS l ist ein lausiger Name für einen Wert! Es sieht aus wie die Ziffer 1 oder der Großbuchstabe I.
Jathanismus
Sie ändern die Größe der Liste, während Sie darüber iterieren, was wahrscheinlich nicht das ist, was Sie wollen und die Ursache Ihres Fehlers ist.
Bearbeiten: Wie andere geantwortet und kommentiert haben, sind Listenverständnisse besser als erste Wahl und insbesondere als Antwort auf diese Frage. Aus diesem Grund habe ich dies als Alternative angeboten, und obwohl dies nicht die beste Antwort ist, löst es das Problem dennoch.
In diesem Sinne könnten Sie also auch verwenden filtermit der Sie eine Funktion aufrufen können, um die Elemente in der Liste auszuwerten, die Sie nicht möchten.
Beispiel:
>>> l = [1,2,3,0,0,1]
>>> filter(lambda x: x > 0, l)
[1, 2, 3]
Lebe und lerne. Einfach ist besser, außer wenn die Dinge komplex sein müssen.
Sie brauchen nicht einmal das Lambda, da 0 zu False ausgewertet wird. filter(None, l)
– Steve Losch
25. November 09 um 18:10 Uhr
@Steve Losh – Das liebe ich an SO… Einfache kleine Tricks wie diesen zu lernen, um mir langfristig Tastenanschläge zu ersparen! Danke!
– Jathanismus
25. November 09 um 18:23 Uhr
-1: Warum zeigst du einem Anfänger diesen alten Weg? Listenverständnisse sind jetzt der bevorzugte Weg, dies zu tun.
– Nikow
25. November 09 um 18:57 Uhr
-1 für Filter oder Karte. Sie sollten immer ein Listenverständnis verwenden, wenn es die Aufgabe erfüllt.
– Nick Bastin
25. November 09 um 19:16 Uhr
Ihr habt Recht, aber filter ist nach wie vor ein wichtiger Bestandteil des Toolkits, wenn Sie eine weitergehende Auswertung benötigen.
– Jathanismus
26. November 09 um 21:06 Uhr
Pugsley
Was Mark Rushakoff gesagt hat, ist wahr, aber wenn Sie in die entgegengesetzte Richtung iterieren, ist es möglich, Elemente auch in der for-Schleife aus der Liste zu entfernen. Z.B,
x = [1,2,3,0,0,1]
for i in range(len(x)-1, -1, -1):
if x[i] == 0:
x.pop(i)
Es ist wie ein hohes Gebäude, das von oben nach unten einstürzt: Selbst wenn es mitten im Einsturz ist, können Sie es immer noch “betreten” und noch einzustürzende Stockwerke besuchen.
Ich denke, der beste Weg, um dieses Problem zu lösen, ist:
l = [1, 2, 3, 0, 0, 1]
while 0 in l:
l.remove(0)
Anstatt über die Liste zu iterieren, entferne ich 0 bis es keine mehr gibt 0 in Liste
Manisch Tripathi
Das Listenverständnis führt Sie zur Lösung.
Aber der richtige Weg, ein Objekt in Python zu kopieren, ist die Verwendung Kopie des Python-Moduls – Flache und tiefe Kopiervorgänge.
l=[1,2,3,0,0,1]
for i in range(0,len(l)):
if l[i]==0:
l.pop(i)
Wenn stattdessen
import copy
l=[1,2,3,0,0,1]
duplicate_l = copy.copy(l)
for i in range(0,len(l)):
if l[i]==0:
m.remove(i)
l = m
Dann hätte Ihr eigener Code funktioniert. Aber für die Optimierung ist das Listenverständnis eine gute Lösung.
Micho
Das Problem bestand darin, dass Sie versucht haben, die Liste, auf die Sie verwiesen haben, innerhalb der Schleife zu ändern, die die Liste verwendet hat len(). Wenn Sie das Element aus der Liste entfernen, wird das neue len() wird auf der nächsten Schleife berechnet.
Zum Beispiel nach dem ersten Lauf, wenn Sie entfernt haben (i) verwenden l.pop(i), das ist erfolgreich passiert, aber bei der nächsten Schleife hat sich die Länge der Liste geändert, sodass alle Indexnummern verschoben wurden. Bis zu einem bestimmten Punkt versucht die Schleife, über eine kurzgeschlossene Liste zu laufen, was den Fehler auslöst.
Dies außerhalb der Schleife zu tun, funktioniert, es wäre jedoch besser, eine neue Liste zu erstellen, indem Sie zuerst eine leere Liste vor der Schleife deklarieren und später innerhalb der Schleife alles, was Sie behalten möchten, an die neue Liste anhängen.
Für diejenigen unter Ihnen, die möglicherweise auf das gleiche Problem gestoßen sind.
.
7575700cookie-checkpython : Listenindex außerhalb des gültigen Bereichs Fehler beim iterativen Popup von Elementenyes
“Ich habe Schleifenabbruchbedingung i < len(l)" Warum sagen Sie das? Wo in deinem Code siehst du das?
– S. Lott
25. November 09 um 18:02 Uhr
@ S. Lott , i in range(0,len()) bedeutet ‘ich werde bis len(l)-1 gehen’
– ein Fernseher
25. November 09 um 18:06 Uhr
Ein weiterer Python-Tipp – Sie hätten einfach schreiben können
range(len(l))
da 0 der Standardstartwert ist.– Abgrund
25. November 09 um 18:07 Uhr
Ab PEP8: Verwenden Sie niemals die Zeichen
l
(Kleinbuchstabe el),O
(Großbuchstabe oh) oderI
(Großbuchstabe Auge) als Einzelzeichen-Variablennamen. python.org/dev/peps/pep-0008– Stefan202
25. November 09 um 18:09 Uhr
@atv: Was dich zum Nachdenken anregt
range(0,len(l))
hat ein Ergebnis, das variiert, wennl
ist geändert? Warum denkst du, dass? Wo hast du es gelesen?– S. Lott
25. November 09 um 23:44 Uhr