PyQt5: mit pushButton-Klick Schleife weiterlaufen lassen

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
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Hallo,
ich hätte eine Frage zu PyQt5.
Und zwar müssen ja die Methoden wie clicked usw. mit einer Funktion verbunden werden. Nun habe ich folgendes Problem: Ich möchte, dass eine Programmschleife auf Druck eines Pushbuttons weiterläuft(also z.B. das nächste Element einer Liste in der Konsole, einem LineEdit etc... ausgibt). Geht sowas? Und falls nicht, gibt es Alternativen um zu diesem Ziel zu kommen?

Viele Grüße,

Cortez
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst auf Knopfdruck den nächsten wert eines Generators berechnen. Das sollte dem recht nahe kommen.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Also ich möchte folgendes:

Code: Alles auswählen

for zähler in range(0, len(liste)):
		print ("Test")
		if fenster.pushButton.clicked :
			continue
Wie lässt sich das mit dem Generatorwert lösen?

Danke dir für die schnelle Antwort.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bitte niemals mit range über eine Liste laufen. Nie. Wirklich nicht.

Code: Alles auswählen

it = iter(liste)
fenster.pushButton.clicked(lambda: print(next(liste)))
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Ok, vielen Dank. Werde nachher mal damit rumspielen.

P.S.: Warum sollte man die range-Funktion nicht zum Durchlaufen von Listen nehmen?
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Weil man dazu

for ding in liste

macht.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

geht bei mir leider nicht, weil in meiner Liste Objekte gespeichert sind und nicht nur Strings oder integers
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

__deets__ hat übrigens absichtlich einen Fehler in seinem Beispielcode eingebaut, da next() das falsche Objekt übergeben bekommt. Wahrscheinlich nur um zu sehen, ob jemand aufpasst. :)
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Cortez hat geschrieben: Freitag 26. April 2019, 22:20 geht bei mir leider nicht, weil in meiner Liste Objekte gespeichert sind und nicht nur Strings oder integers
Die Art der Objekte ist dabei völlig egal und im Übrigen auch eine haarsträubende Begründung / Vermutung. Wie kommst du darauf, dass sich Zahlen und Strings beim Iterieren anders verhalten als alle übrigen Objekte? Gab es eine Fehlermeldung, die du womöglich falsch verstanden hast?
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

@snafu hat natürlich recht, es muss natürlich it sein. Und auch mit seinen Anmerkungen zur iterierbarkeit. ALLES ist ein Objekt in Python. Ob String, ob int, ob Rumpelstil.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

snafu hat geschrieben: Freitag 26. April 2019, 22:28
Cortez hat geschrieben: Freitag 26. April 2019, 22:20 geht bei mir leider nicht, weil in meiner Liste Objekte gespeichert sind und nicht nur Strings oder integers
Die Art der Objekte ist dabei völlig egal und im Übrigen auch eine haarsträubende Begründung / Vermutung. Wie kommst du darauf, dass sich Zahlen und Strings beim Iterieren anders verhalten als alle übrigen Objekte? Gab es eine Fehlermeldung, die du womöglich falsch verstanden hast?
richtig, gab ne Fehlermeldung. Den Wortlaut krieg ich nicht mehr hin, aber es kam die Meldung, dass das zu Iterierende str oder int sein müsse und nicht Instanz der betreffenden Klasse.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das ist etwas anderes gewesen. Ohne Code und konkrete Fehlermeldung kann man dazu nix sagen, aber nochmal: du kannst problemlos über eine Liste iterieren, egal was darin ist.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wie gesagt, am besten ganz schnell wieder vergessen. So ziemlich jedes Grundlagen-Tutorial sagt einem etwas in dieser Art:

Code: Alles auswählen

for obj in objekte:
    tu_was(obj)
Und etwas anderes sollte man sich auch gar nicht angewöhnen. Spätestens wenn man verschachtelte Schleifen oder List Comprehensions hat, will man range() wirklich nicht mehr ohne Not benutzen. Und falls du mal nur einen Ausschnitt aus einer Liste benötigst, dann hol sie dir per Slicing, aber nicht mit range(). Sonst wird dich kein halbwegs erfahrener Python-Programmierer mehr ernstnehmen, sobald er deinen Code sieht. ;)
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Habe meinen Code nochmals umgebaut um die Fehlermeldung zu bekommen:

Code: Alles auswählen

for zähler in objekte:
		if objekte[zähler].attribut1 == "Nikolaus":
			print ("Test")
Ich erhalte folgende Fehlermeldung: list indices must be integers or slices, not (Objekte der betreffenden Klasse)

PS: Blödes Codebeispiel, aber soll nur zur Verdeutlichung dienen
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Zähler IST dein Objekt. Genau darum geht es doch. Du musst genau NICHT per Index auf die Liste zugreifen. Sondern bekommst die Objekte nacheinander geliefert.

Code: Alles auswählen

for zähler in objekte:
		if  zähler.attribut1 == "Nikolaus":
			print ("Test")
Zähler ist dann natürlich ein blöder Name. Aber zur Illustration.
Cortez
User
Beiträge: 115
Registriert: Montag 31. Dezember 2018, 15:28

Danke dir für die Antwort. Ich habe meinen Denkfehler erkannt.
Ich bitte um Verständnis für meine Fragen, die euch erfahrenen Programmierer sicherlich trivial vorkommen - aber als Einsteiger sieht man, trotz Durcharbeiten eines Tutorials, manchmal den Wald vor lauter Bäumen nicht. Alles Wissen von den Tutorials muss halt praktisch umgesetzt werden - und da hat man halt als Neuling mal ein Brett vorm Kopf. Also, wenn ich was frage, dann ist es nicht Faulheit, sondern nur, wenn mir wirklich was im Moment unklar ist.

P.S. Mir ist z.B. noch unklar, warum die for-Schleife mit der range-Funktion für Listen unangebrach ist. Ich habe verstanden, dass man es nicht macht und habe meinen Code auch entsprechend abgeändert - aber was ist an der anderen Lösung besser? Oder hat das schlicht was mit Stil und Lesbarkeit des Codes zu tun?
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es gibt eine Reihe von Gründen, warum das vorzuziehen ist:

- Ästhetische, es ist weniger “rödelig”, kein indexzugriff, weniger Klammern etc.
- weniger Ansprüche an das iterierbare Objekt. Wieviele Zeilen hat denn zb eine Datei, über die du iterieren willst? Weißt du vorher gar nicht. Alles was du wissen musst ist, “gib mir so lange was, bis nix mehr da ist”. Das ist deutlich weniger als “verrate mir wieviele Element du hast. Und erlaube mir wahlfreien(!!) Zugriff darauf”.
- als Konsequenz aus dem letzten Punkt wird der Code generischer. Kann dadurch eben mit Quellen umgehen, die zb Werte nur auf Anforderung generieren können.
- ebenfalls als Konsequenz können Speicher- und Laufzeitgewinne erziehlt werden. Solange durch eine 100GB große Datei Stiefeln, bis eine bestimmte Zeile gefunden wurde? Kein Problem. Musst du die aber erstmal komplett einlesen, brauchst du vorher ein Speicherupgrade.
Benutzeravatar
__blackjack__
User
Beiträge: 13079
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Cortez: Ich hätte gedacht es ist recht offensichtlich warum Code der direkt, ohne den Umweg über einen zusätzlichen Index, über eine Sequenz iteriert besser ist. Wenn man das mal vergleicht:

Code: Alles auswählen

for i in range(len(sequence)):
    do_something(sequence[i])

# vs.

for item in sequence:
    do_something(item)
Die zweite Variante kann man fast wie einen Satz lesen der aussagt was der Code macht. Den gleichen Satz würde man auch zur Beschreibung der ersten Variante vewenden, nur das da der Code das ein bisschen umständlicher formuliert. Und man hat oft auch als erstes in der Schleife immer so etwas wie ``item = sequence[ i ]`` stehen um einen Namen für das Element zu haben. Das ist bei den generischen Namen wie `sequence` und `item` natürlich nicht so wichtig, aber normalerweise gibt man da ja sinnvolle Namen die dem Leser Informationen liefern. Man vergleiche beispielsweise das hier:

Code: Alles auswählen

for i in range(len(table)):
    for j in range(len(table[i])):
        do_something(table[i][j])

# vs.

for row in table:
    for cell in row:
        do_something(cell)
Obwohl das auch noch recht generisch ist, machen die Namen das IMHO lesbarer. Noch grösser wird der Unterschied wenn man da konkrete Namen für die Bedeutung der Werte in der Tabelle verwendet.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten