Problem mit String in Funktion

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
A4PA1ZZ
User
Beiträge: 3
Registriert: Mittwoch 11. September 2019, 11:18

Mittwoch 11. September 2019, 12:07

Hallo zusammen,

zunächst die vermutlich leidige Information: Ich bin absoluter Python-Neuling. Ich habe allerdings in Schule und Ausbildung einige Zeit programmiert (basic und c bzw. c#).
Seit gut 10 Jahren aber nur noch SPS (hauptsächlich S7). Ich hoffe einfach auf Gnade eurerseits :-)

Ich versuche mich gerade an einem Grundkonstrukt für einen Cocktailautomaten mit einem Raspberry Pi (das Thema ist aber allg. Python).
In der GUI habe ich ein menu mit command_buttons erstellt. Dieser soll eine bestimmte Funktion ausführen und ich übergebe der Funktion einen String.
Hier ein Auszug aus dem Code: (ich hoffe ohne Syntaxfehler, sitze gerade in der Arbeit und habe hier kein IDE):

Code: Alles auswählen

#diverser Code davor

def cocktail(drink):
     str_cocktail = drink
     
     
#diverser Code dazwischen     
hauptmenu = Menu(root, tearoff=0)
hauptmenu.add_command(label="Cuba Libre", command=cocktail("Cuba Libre")
#diverser Code danach
Ich weiß, dass hier noch ein Problem ist, da der command sofort ausgeführt wird. Ich hatte es mit lambda versucht, was funtkionierte, aber lambdas sind doch eigentlich nur für einmalige Aufrufe oder?
Dieses Problem versuche ich selbst noch zu lösen. Mein Ansatz ist der, dass ich den Button für Cuba Libre drücke, dadurch die Funktion "cocktail" ausführe und hier abhänghig vom String eben entscheide, welcher Cocktail gemixt wird. Der erste Aufruf läuft auch noch wie ich es mir vorstelle. Beim zweiten Aufruf zum Beispiel mit dem Button "Vodka" wird der Wert an die Funktion übergeben. Ich erwarte dann den String in der Funktion: "Vodka", allerdings lautet dieser "Vodka Libre"). Es wird also nicht die Variable neu beschrieben, sondern nur die einzelnen Zeichen werden überschrieben.

Ich hoffe, ich konnte mein Problem einigermaßen verständlich erläutern mit genügend, aber auch nicht zu viel Information.
Bestimmt ist es irgendein dummer Anfängerfehler, eben auch, dass ich die Funktion quasi sofort beim init des Buttons ausführe, ohne Argument zu übergeben wäre mir das auch sofort klar, aber so stehe ich bei beiden Dingen momentan auf dem Schlauch.

Egal wie das hier ausgeht, schonmal vielen Dank!

Manuel
Benutzeravatar
__blackjack__
User
Beiträge: 4010
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mittwoch 11. September 2019, 13:58

@A4PA1ZZ: Ein ``lambda``-Ausdruck erstellt eine Funktion. Die kann man so oft aufrufen (lassen) wie man mag. Allerdings würde ich für diesen Fall `functools.partial()` verwenden.

Grunddatentypen haben nichts in Namen verloren und man macht schon gar keine Typpräfixe. Falls Du das bei Basic mal so gelernt hast: das macht man in Python (und den meisten anderen Sprachen) nicht und selbst bei Basic ist das nicht mehr üblich.

Die Zuweisung in `cocktail()` macht auch keinen Sinn – warum nennst Du das Argument nicht gleich so wie das heissen soll?

Funktionsnamen werden üblicherweise nach der Tätigkeit benannt die sie ausführen — `cocktail()` ist keine Tätigkeit, und vor allem wäre das ein guter Name für ein Objekt das einen Cocktail repräsentiert.

Das was Du mit Vodka (Libre) beschreibst kann nicht sein. Zeichenketten sind in Python nicht veränderbar, das heisst man kann in einer Zeichenkette keine Zeichen überschreiben.

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

Bei GUI-Programmierung kommt man bei jeder nicht-trivialen GUI nicht wirklich um objektorientierte Programmierung (OOP) herum. Damit hätte man dann auch eine andere Lösung für ``lambda`` oder `functools.partial()`.
“Programmieren ist ein Hobby, bei dem es einen riesigen Baumarkt mit quasi jedem Bauteil und Werkzeug und fast immer kostenlos gibt. Ob man deswegen in der Lage ist einen Kölner Dom zu bauen ist eine andere Frage. Arbeit steckt auf jeden Fall drin ;).” — Greebo, forum.ubuntuusers.de
A4PA1ZZ
User
Beiträge: 3
Registriert: Mittwoch 11. September 2019, 11:18

Mittwoch 11. September 2019, 16:09

Ok, da hab ich wohl doch mehr Nachholbedarf, als ich dachte.

Dann werde ich mich mal nochmal komplett an die Basics machen.
Was ich allerdings nicht verstehe ist, dass Zeichenketten nicht änderbar sind.

ich habe str_cocktail in einem label als Text ausgegeben und beim ersten Aufruf mit "Cuba Libre" zeigte sich der Text "Cuba Libre" im Fenster. beim erneuten Aufruf der Funktion cocktail() über den Button Vodka, zeigte sich
im Fenster defintiv der Text VodkaLibre...

Naja egal. ich mach mich komplett an die Grundlagen. Mal sehen ob ich es schaffe, in absehbarer Zeit eine GUI aufzubauen auf der Cocktails wählbar sind, abhängig davon welche Zutaten vorhanden sind (8 Pumpen zugewiesen sind). Wenn das steht, sollen hinterher die Pumpen einzeln für bestimmte Zeiten angesteuert werden....

Danke nochmal und nichts für ungut.

Gruß
Manuel
__deets__
User
Beiträge: 6190
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mittwoch 11. September 2019, 16:21

Das eine ist, ob du ein GUI-Control manipulieren kannst, einen anderen Text anzuzeigen. Das geht natuerlich. Was NICHT geht, und was __blackjack__ meinte, ist sowas hier:

Code: Alles auswählen

mein_text = "hallo wolt" # ups, ein Fehler
mein_text[-3] = "e"
print(mein_text)
String-Objekte sind unveraenderlich in Python (und vielen anderen Sprachen).
Benutzeravatar
__blackjack__
User
Beiträge: 4010
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mittwoch 11. September 2019, 16:35

@A4PA1ZZ: Kann es sein, dass Du jedes mal ein neues `Label`-Objekt erzeugst und *die* übereinander legst? Dann ist klar das ein kürzeres/kleineres Label ein grösseres/längeres Label nicht komplett verdeckt. Das ist aber auch kein sinnvolles vorgehen. Man erzeugt die GUI in der Regel am Anfang *komplett* und ändert dann die Widgets statt während des Programmablaufs neue zu erstellen.

Um das noch mal zu ergänzen: Auf Modulebene gehören keine Variablen, das heisst die `cocktail()`-Funktion muss alles was sie ausser Konstanten verwendet als Argument(e) übergeben bekommen. Wie gesagt: man braucht objektorientierte Programmierung für jede nicht-triviale GUI.

Edit: Noch eine Nachfrage: Falls ich mit den `Label`\s richtig lag, dann kann das nur bei `grid()` und `place()` passieren. Solltest Du `place()` verwenden: Vergiss das gleich wieder.
“Programmieren ist ein Hobby, bei dem es einen riesigen Baumarkt mit quasi jedem Bauteil und Werkzeug und fast immer kostenlos gibt. Ob man deswegen in der Lage ist einen Kölner Dom zu bauen ist eine andere Frage. Arbeit steckt auf jeden Fall drin ;).” — Greebo, forum.ubuntuusers.de
A4PA1ZZ
User
Beiträge: 3
Registriert: Mittwoch 11. September 2019, 11:18

Mittwoch 11. September 2019, 16:46

@__blackjack__
Ja, ich fürchte fast, dass es so ist. Bin aber leider noch auf Arbeit und kann gerade nicht nachschauen.
Jetzt leuchtet mir das auch ein. Kann mich nur nochmals entschuldigen für meine Unwissenheit...

Und in der tat ich benutze place(), aber wieso soll ich das gleich wieder vergessen?. Ich habe ein 3.5" Touch, welches ich am Raspberry Pi 3B betreibe.
Mein Ansatz war ein Fenster, das größtenteils starr ist. Hauptsächlich soll ein Cocktail ausgewählt werden können. Diesen möchte ich dann an einer festen Stelle darstellen, während er "gemixt" wird
Sirius3
User
Beiträge: 10347
Registriert: Sonntag 21. Oktober 2012, 17:20

Mittwoch 11. September 2019, 16:58

Wenn Du eine Frage stellst, solltest Du den Code zeigen, den Du auch real benutzt. Sonst müssen wir hier raten, was denn bei Dir wirklich passiert. GUIs sind für Anfänger schwierig. Man kann sich wie bei vielen Dingen, eine Weile lang durchmogeln, aber irgendwann kommt der Punkt, wo man mit dieser Methode einfach nicht weiter kommt, und man nochmal komplett von vorne Anfangen muß und alles sauber aufbauen muß.

Du brauchst Dich übrigens nicht immer entschuldigen. Auch wenn sich der Ton manchmal hier im Forum etwas rau anhört, macht Dir niemand einen Vorwurf, dass Du noch nicht alles perfekt machst.

Es nervt erst, wenn jemand konsequent Ratschläge mißachtet und auf seinen falschen Behauptungen beharrt. Leider sind viele Beispiele, die man im Netz findet, einfach nur schlecht.

Mit grid kann man mindestens genauso gut Widgets positionieren, hat aber nicht das Problem, dass man bei jeder Änderung alles neu ausrichten muß. Daher kein `place`.
Benutzeravatar
__blackjack__
User
Beiträge: 4010
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mittwoch 11. September 2019, 17:00

@A4PA1ZZ: Wie gross das Display physikalisch ist, ist ja nur ein Teil der Gleichung. Man kann ja problemlos mit `place()` eine GUI basteln die auf einem 3,5"-Display ”richtig” aussieht, auf einem anderen 3,5"-Display aber entweder viel zu klein mit viel Leerraum oder unbenutzbar weil alles irgendwie übereinander geschoben ist. Man platziert deshalb keine GUI-Elemente absolut, sondern relativ und lässt das GUI-Rahmenwerk von sich aus feststellen wie gross das sein muss.
“Programmieren ist ein Hobby, bei dem es einen riesigen Baumarkt mit quasi jedem Bauteil und Werkzeug und fast immer kostenlos gibt. Ob man deswegen in der Lage ist einen Kölner Dom zu bauen ist eine andere Frage. Arbeit steckt auf jeden Fall drin ;).” — Greebo, forum.ubuntuusers.de
Antworten