Seite 1 von 1

For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Dienstag 9. Februar 2016, 10:11
von gerald123
Hey, ich möchte über eine Liste iterieren, wobei sich die Länge der Liste am Ende jeder Iteration ändert -->

Code: Alles auswählen

people = ["A"]

for n in people:
    if len(people) == 3:
        print "OK", n
        break
    people.extend("A")
    
   
Würded ihr diese Methode so empfehlen, oder gibt es elegantere Wege?

Vielen Dank

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Dienstag 9. Februar 2016, 10:21
von Sirius3
@gerald123: das Beispiel ist sinnfrei, denn das würde man ja mit:

Code: Alles auswählen

people = ["A", "A", "A"]

for n in people:
    pass
print "OK", n
oder gleich als

Code: Alles auswählen

print "OK", "A"
schreiben.
Kannst Du Dein wirkliches Problem schildern? So kann man keinen sinnvollen Rat geben.

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Dienstag 9. Februar 2016, 11:20
von noisefloor
Hallo,
Hey, ich möchte über eine Liste iterieren, wobei sich die Länge der Liste am Ende jeder Iteration ändert -->
Also das Beispiel macht aber was anders, nämlich eine Liste solange erweitern, bis sie drei Elemente hat. Und das geht auch anders / eleganter.

Was willst du denn wirklich vor.

Gruß, noisefloor

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Dienstag 9. Februar 2016, 12:01
von snafu
@gerald123
Die elegantere Lösung ist, eine neue Liste zu erzeugen, in der die benötigten Elemente enthalten sind. Gleichzeitiges Iterieren und Verändern des Inhalts ist bei Container-Objekten fast nie eine gute Idee.

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Dienstag 9. Februar 2016, 12:08
von BlackJack
@gerald123: Der Beispielcode ist poblematisch wenn die die Liste bereits mehr als drei Elemente enthält. Dann hat man da nämlich eine Endlosschleife die irgendwann von einem `MemoryError` gestoppt wird, wenn die immer weiter wachsende Liste nicht mehr in den Speicher passt.

Hier mal zwei Varianten ohne über die Liste zu iterieren:

Code: Alles auswählen

In [1]: people = ['A']

In [2]: people.extend(['A'] * (3 - len(people)))

In [3]: people
Out[3]: ['A', 'A', 'A']

In [4]: from itertools import repeat

In [5]: people = ['A']

In [6]: people.extend(repeat('A', 3 - len(people)))

In [7]: people
Out[7]: ['A', 'A', 'A']

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Mittwoch 10. Februar 2016, 08:19
von harryberlin
wenn es um die Länge geht, würde ich while mit kleiner 3 nehmen.

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Mittwoch 10. Februar 2016, 12:11
von BlackJack
@harryberlin: Im gezeigten Beispiel gar kein ``while``. Wenn schon eine Schleife, dann eine ``for``-Schleife, denn es ist vor Eintritt in die Schleife ja bereits bekannt wie oft die durchlaufen werden wird.

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Mittwoch 10. Februar 2016, 16:48
von harryberlin
soweit ich das sehe durchläuft die schleife einmal.
und dann wird die liste einmal erweitert.
und fertig.
für die 3 abfrage, sehe ich gar keine berechtigung.
deswegen war meine annahme, er will solang erweitern, bis sie eine Länge von 3 hat.

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Mittwoch 10. Februar 2016, 17:22
von BlackJack
@harryberlin: Die Schleife wird 2× durchlaufen und durch die Bedingung mit den ``== 3`` abgebrochen. Ist halt gefährlich wenn die Liste schon mehr als drei Einträge enthält, weil man dann eine Endlosschleife mit einer endlos grösser werdenden Liste hat. Darum ging ich ja auch davon aus das 3 das Maximum sein sollte, und dann kann man meine bereits gezeigten Lösungen ohne explizite Schleifen verwenden oder eben eine ``for``-Schleife, denn man kann ja ausrechnen wie oft die durchlaufen werden muss.

Code: Alles auswählen

In [23]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:people = ["A"]
:
:for n in people:
:    if len(people) == 3:
:        print "OK", n
:        break
:    people.extend("A")
:<EOF>
OK A

In [24]: people
Out[24]: ['A', 'A', 'A']

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Mittwoch 10. Februar 2016, 18:27
von harryberlin
da muss ich jetz blöd fragen, wieso durchläuft die schleife 2x, wenn people = ["A"] ist?

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Mittwoch 10. Februar 2016, 19:13
von BlackJack
@harryberlin: Weil `people` nur im ersten Durchlauf (am Anfang) ``['A']`` ist. Im zweiten ist es ``['A', 'A']``. Insofern wird die Schleife 2½ mal durchlaufen, denn beim dritten mal wird am Anfang der Schleife wegen der ``== 3``-Bedingung die Schleife abgebrochen. Ich bin mir auch gar nicht sicher ob sich jede Python-Implementierung so verhalten muss, also ob das Verhalten des Iterators für Listen irgendwo festgelegt ist für den Fall das die Liste während der Iteration verändert wird.

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Mittwoch 10. Februar 2016, 19:28
von harryberlin
hui, wieder was gelernt.
das war mir neu, dass die eingaben für die for schleife erneut geprüft werden.
deswegen hatte ich zuerst an while gedacht.

Re: For-Schleife: Objekt ändert sich in jeder Iteration

Verfasst: Mittwoch 10. Februar 2016, 21:43
von BlackJack
@harryberlin: Ich vermute Du hast da gerade eine falsche Vorstellung von der ``for``-Schleife, beziehungsweise ordnest dem Konstrukt selbst Code zu der nicht fest mit der Schleife verbunden ist. Die fragt das Objekt nach dem ``in``-Schlüsselwort nach einem Iterator und den dann wiederholt nach dem nächsten Element, solange bis der bei so einer Anfrage mit einer `StopIteration`-Ausnahme antwortet. Das ist die einzige Sache die von der ``for``-Schleife getestet wird. Was der Iterator macht hängt von dem Objekt ab das den auf Anfrage liefert. Also in diesem Fall was die Liste beziehungsweise der von ihr gelieferte Iterator macht:

Code: Alles auswählen

In [1]: people = ['A']

In [2]: it = iter(people)

In [3]: next(it)
Out[3]: 'A'

In [4]: people.append('B')

In [5]: next(it)
Out[5]: 'B'

In [6]: next(it)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-6-2cdb14c0d4d6> in <module>()
----> 1 next(it)

StopIteration:
Das bei ``next(it)`` nach dem `append()` nicht schon `StopIteration` ausgelöst wird, ist eine Entscheidung des Programmierers der den `list`-Datentyp implementiert hat. Der hätte sich auch anders entscheiden können. Das hat nichts mit dem Code der Implementierung für ``for``-Schleifen zu tun.