phänomen bei interration?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mrshoul
User
Beiträge: 10
Registriert: Sonntag 22. November 2009, 10:10

Hi,
nach vielen eignen Versuchen, Nachschlagen in verschiedenen Büchern und Suchanfragen im Forum, wage ich es doch hier eine Frage zu stellen.

Code: Alles auswählen

>>> a = [i for i in range(10)]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for i in a:
	if i < 2:
		a.remove(i)

		
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9]
# Wiso wird nur die Zahl 0 und nicht auch die Zahl 1 entfernt?
# Nochmal mit del:
>>> a = [i for i in range(10)]
>>> for i in a:
	if i < 2:
		del a[i]

		
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> # Gleiches Ergebnis
>>> # Prüfung:
>>> a[0]
1
>>> a[0]<2
True
Könnte mir das bitte jemand erklären?

Grüße,

mrshoul
Zuletzt geändert von mrshoul am Dienstag 19. April 2011, 14:47, insgesamt 1-mal geändert.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Tipp: Nicht die Liste modifizieren über die man iteriert.

Code: Alles auswählen

a = [element for element in a if element >= 2]
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
mrshoul
User
Beiträge: 10
Registriert: Sonntag 22. November 2009, 10:10

Danke Leonidas!
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Gibt es für dieses Verhalten eigentlich eine definierte Erklärung? Ansonsten wäre es ja vielleicht nicht schlecht, wenn Python das Modifizieren während des Iterierens gänzlich verbieten würde, damit es nicht zu bösen Überraschungen kommt.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wie möchtest du eine Modifizierung verhindern? Wenn man direkt über eine Liste iteriert ist das kein Problem, aber sobald man über Indizes geht, kann natürlich alles mögliche passieren und sogar sinnvoll sein.
Das Leben ist wie ein Tennisball.
BlackJack

@snafu: Was meinst Du mit "definierter Erklärung"? Der Iterator den ``for`` anfordert ist ja unabhängig, dass heisst der bekommt nichts davon mit wenn die Liste verändert wird. Der zählt bei jedem Aufruf von `__next__()` einfach stur den Index hoch über den er auf die Elemente zugreift. Wenn man die Positionen der Elemente zwischen solchen Aufrufen ändert, bekommt der Iterator davon nichts mit.

Wenn Du das verhindern möchtest, müsstest Du so etwas wie einen "Veränderungszähler" auf Listen einführen, der bei jeder verändernden Listenoperation hochgezählt wird und bei jedem Iteratorzugriff mit dem Stand verglichen wird, als der Iterator erstellt wurde. Falls unterschiedlich müsste der Iterator eine Ausnahme auslösen das man da etwas böses getan hat. Aber da fangen die Probleme ja schon an -- soll das wirklich bei *jedem* verändern der Liste passieren? Auch wenn man Elementen neu zuweist? Oder wenn man Elemente entfernt über die noch nicht iteriert wurde? Das würde das ganze Iterator-Protokoll komplexer machen. Ausserdem wäre es eine nicht rückwärts kompatible Änderung.

IMHO ist das jetzige Verhalten eine gute Mischung aus KISS-Prinzip und dem Vertrauen auf den Programmierer, dass er weiss was er da tut.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich wollte eigentlich nicht sagen, dass es verändert werden soll. Mein Fokus lag auf der Frage nach der Implementierung.

Verstehe ich den Ablauf so richtig:

(1) Zähler auf Index 0. Erstes Element der Liste auf Index 0.
(2) Element auf Index 0 wird gelöscht. Zweites Element rutscht daher von Index 1 auf Index 0.
(3) Zähler springt auf Index 1, wo aber nun das verschobene Element vom ursprünglichen Index 2 sitzt.
(4) Verschobenes Element vom ursprünglichen Index 1 wurde übersprungen und bleibt daher in der Liste erhalten.

EDIT: Ach, ich bin doof. Sehe jetzt erst, dass ja der Index genutzt wird. Dann ist das ja klar. Ich hätte gestern vielleicht weniger Erdbeer-Bowle trinken sollen. :mrgreen:
Antworten