Liste wird in for Schleife geleert?!

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
zackdvd
User
Beiträge: 2
Registriert: Sonntag 20. September 2020, 11:56

Hallo zusammen,

bin bzgl. python noch Anfänger und kann mir folgendes Verhalten nicht erklären.
Ich erstelle eine verschachtelte Liste, gebe sie mir print in einer for Schleife aus, doch danach scheint diese leer zu sein.
Woran liegt es?

Code: Alles auswählen

numbering = [1,2,3,4,5,6,7,8,9,10]
bass   = [70,	80,	80,	80,	0,	0,	0,	0,	0,	0]
treble = [30,	30,	30,	50,	60,	60,	60,	70,	70,	60]


def print_equalizer(eclass, equallist):
    print(eclass, ":")
    for etuple in equallist:
        print(etuple[1], etuple[2], sep=",", end=' ')
    print("")


equalizer = zip(numbering,bass,treble)

print_equalizer("changed", equalizer)
print_equalizer("changed", equalizer)
Ausgabe:

Code: Alles auswählen

changed :
70,30 80,30 80,30 80,50 0,60 0,60 0,60 0,70 0,70 0,60
changed :
Danke euch!
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@zackdvd: Das liegt daran das Du gar keine Liste erstellst, sondern einen Iterator der die Elemente liefert wenn sie angefordert werden. Und wenn der Iterator einmal durchgelaufen ist, dann ist der halt durchgelaufen.

Code: Alles auswählen

In [58]: it=zip([1,2],[3,4])                                                    

In [59]: it                                                                     
Out[59]: <zip at 0x7f61416faec8>

In [60]: next(it)                                                               
Out[60]: (1, 3)

In [61]: next(it)                                                               
Out[61]: (2, 4)

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

StopIteration:

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

StopIteration:
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@zackdvd: Noch Anmerkungen zum Quelltext:

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Falls sich `numbering` nicht ändert, also immer ganze Zahlen von 1 aufwärts bis zur Länge der anderen Listen, dann ist das nichts was man in einer Liste speichert. Und schon gar nicht von Hand die Zahlen alle tippt. Also das wäre mindestens mal ``numbering = list(range(1, len(bass) + 1))``. Aber eigentlich generiert man solche Zahlen dann wenn man sie braucht. Das vorliegende Programm braucht die ja nicht einmal.

Man verwendet keine kryptischen Abkürzungen in Namen und auch keine Grunddatentypen.

Wenn ein Name mit einem Schlüsselwort oder einer eingebauten Funktion kollidiert ist die Konvention da einen Unterstrich am Ende anzuhängen. Also `class_` statt `eclass` weil `class` als Name nicht erlaubt ist.

Magische Indexzugriffe sollte man vermeiden. Man kann in ``for``-Schleifen gleich im Schleifenkopf iterierbare Objekte auf Namen aufteilen:

Code: Alles auswählen

    for bass, treble in equalizer_values:
        print(bass, treble, sep=",", end=" ")
Das mit den ``print``-Argument ist ein bisschen gewöhnungsbedürftig. Statt da an den Schlüsselwortargumenten herum zu fummeln, würde man eher *eine* Zeichenkette erstellen, die den gewünschten Inhalt hat.

Code: Alles auswählen

#!/usr/bin/env python3


def print_equalizer(class_, equalizer_values):
    print(f"{class_}:")
    print(" ".join(",".join(map(str, pair)) for pair in equalizer_values))


def main():
    bass = [70, 80, 80, 80, 0, 0, 0, 0, 0, 0]
    treble = [30, 30, 30, 50, 60, 60, 60, 70, 70, 60]
    assert len(bass) == len(treble)

    print_equalizer("changed", zip(bass, treble))
    print_equalizer("changed", zip(bass, treble))


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
zackdvd
User
Beiträge: 2
Registriert: Sonntag 20. September 2020, 11:56

Hey, entschuldige bitte die zu späte Antwort. Es kamen private Angelegenheiten dazwischen, sodass das Projekt warten musste...

Danke für die extrem ausführliche Antwort inkl. Hilfestellungen. Das ist wirklich eine Seltenheit in Foren, große Anerkennung meinerseits !
Ich versuche das an anderen Stellen wiederzugeben.

Ich habe viel gelernt durch deine Anmerkungen.
Eine Frage noch, wie würdest du am elegantesten (es muss ja auch schön werden nachher :-) ) noch einen Zähler mitziehen und ausgeben?
Am Ende wird quasi folgendes benötigt:
id=1 70,30
id=2 80,30
usw.

Mit i arbeiten und eine Zeile i+=1 hinzufügen? Oder geht das schöner? :-)

Hintergrund zum Ganzen, falls ihr euch fragt wozu das alles: Ich hab auf nem Raspberry Pi einen SW Equalizer über ALSA aktiviert und möchte den per python ansteuern.
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

__blackjack__ hat geschrieben: Sonntag 20. September 2020, 13:30 Man verwendet keine kryptischen Abkürzungen in Namen und auch keine Grunddatentypen.
Dann aber streng genommen auch nicht it statt iterator, wie im Beispiel aus deinem vorherigen Beitrag. ;)
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Okay, ich sollte dazu schreiben das das für Programme gilt. 🙂 In Python-Shell-Sitzungen mache ich sogar Sternchen-Importe. Das ist ja nichts von Dauer oder von einer Länge wo man den Überblick verlieren könnte.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
zackdvd hat geschrieben: Sonntag 4. Oktober 2020, 20:31 Mit i arbeiten und eine Zeile i+=1 hinzufügen? Oder geht das schöner? :-)
Ja, mit der `enumerate` Funktion. Beispiel:

Code: Alles auswählen

>>> bass = [10, 20]
>>> treble = [40, 50]
>>> for count, equilizer_values in enumerate(zip(bass, treble)):
...     print(f'{count}: {equilizer_values[0], equilizer_values[1]}')
...
0: 10,40
1: 20,50
>>>
Gruß, noisefloor
Antworten