@DerSp83: Das sieht noch ziemlich weit von einem funktionierenden, sauberen Programm aus. Das Programm ist ja nicht einmal in Funktionen aufgeteilt, sondern das Hauptprogramm steht einfach so auf Modulebene. Mit den ganzen Variablen.
Zu den Variablen aus Deinem Programm kommen dann noch die knapp 190 Namen die Du durch den Sternchen-Import aus `tkinter` in den Namensraum holst.
Die Programmlogik ist mit der GUI vermischt. Üblicherweise schreibt man erst die Logik und testet die, und wenn das funktioniert, setzt man die GUI darauf auf. Das vermeidet die Gefahr beides zu vermischen.
`x` ist kein guter Name für — ja, wofür eigentlich?
Die Namensschreibweise entspricht nicht immer dem
Style Guide for Python Code.
Daten und Code sollte man nicht wiederholen. Bei den Daten sieht man was für Probleme dadurch entstehen können wenn man sich ColaLight anschaut. Das steht auf der Schaltfläche, aber später im Code wird 'Öttinger' für die Ausgabe bei ColaLight verwendet.
Durchnummerieren von Namen ist ein „code smell“. In der Regel möchte man sich da bessere, passendere Namen ausdenken oder eine Datenstruktur verwenden. Meistens eine Liste. Und falls man dann Daten in Listen hat, möchte man *nicht* mehrere Listen haben, bei denen Werte am gleichen Index jeweils zusammengehören. Informationen wie Getränkename und ob das Getränk vorrätig ist oder nicht, gehören zusammen in ein Objekt und nicht in parallele Listen.
Der lokale Name `x` in der (schlecht benannten) `cola()`-Funktion hat nichts mit dem `x` auf Modulebene zu tun. Du willst in einer Funktion keinen Namen ausserhalb der Funktion Werte zuweisen. Und auch nicht auf Namen (ausser Konstanten) zugreifen, die nicht als Argument übergeben wurden. Für ”Funktionen” bei denen sich Zustand über verschiedene Aufrufe hinweg gemerkt oder verändert werden muss, wurde objektorientierte Programmierung (OOP) erfunden.
Im konkreten Fall sehe ich die Notwendigkeit nicht über so eine Getränkeauswahl-Variable zu gehen, statt die jeweilige Aktion direkt über den Druck der jeweiligen Schaltfläche auszulösen. Da alle Schaltflächen für die Getränke das gleiche machen, nur mit jeweils einem oder mehreren unterschiedlichen Parametern, braucht man am Ende auch nur eine Methode dafür. Für das `command`-Argument kann man dann mit `functools.partial()` dafür sorgen, dass dort für jede Schaltfläche ein spezifisches Argument übergeben wird.
Explizites vergleichen mit boole'schen Literalen ist unnötig. Da kommt am Ende ja nur wieder ein Wahrheitswert heraus. Wenn man mit ``== True`` vergleicht ist das der gleiche Wert mit dem man vergleicht. Und statt ``== False`` kann man einen Test mit ``not`` verwenden. Wobei die ganzen Abfragen sowieso eigenartig strukturiert sind. Es würde mehr Sinn machen erst die Getränkeauswahl zu prüfen und darin dann mit ``if`` ob es davon noch etwas gibt und dann einen ``else``-Zweig für den Fall das nicht. Da nur ein Getränk zu gleichen Zeit ausgewählt sein kann, würden für die Folgefälle ``elif``-Zweige Sinn machen. Und nur zur Sicherheit würde ich ans Ende noch ein ``else`` setzen, mit einer Fehlermeldung, weil dieser Fall nie erreicht werden dürfte wenn der Programmierer keinen Fehler gemacht hat. Da Programmierer das aber machen…
Man bräuchte die ganzen Wiederholungen dieser ``if``-Strukturen nicht, wenn die Daten in einer Datenstruktur abgelegt wären. Zum Beispiel in einer Liste. Wenn die Getränkeauswahl-Werte bei 0 statt bei 1 anfangen würden, könnte man das einfach als Index in die Liste verwenden und kann viel Code einsparen und kann die Getränkeauswahl vergrössern oder verkleinern ohne Code zu ändern, in dem man ganz einfach nur die Liste verkürzt oder durch zusätzliche Getränke erweitert.
``if cola == True:`` wird niemals zutreffen, denn `cola` ist in dem Programm an eine Funktion gebunden und eine Funktion ist niemals der Wert `True`.
IMHO fängst Du am falschen Ende an. Mit dem Entwurf einer GUI kann man ein Projekt anfangen um sich ein Bild von den Aktionen machen zu können, die von der Programmlogik bereitgestellt werden müssen, aber dann sollte man anfangen das Programm von der Logik her aufzubauen. Da man an dem Code nicht sieht was am Ende tatsächlich gemacht werden muss wenn der Benutzer eine Schaltfläche drückt, lässt sich an dieser Stelle nicht wirklich gut sagen, wie dass im Zusammenspiel mit einer GUI am besten funktionieren wird.
Entweder brauchen die Aktionen nicht lange, dann ist das kein Problem. Oder man kann die Logik so aufbauen, dass sie in Schritten in bestimmten Zeitabschnitten von aussen ”getrieben” wird, dann kann man zum Beispiel von Tk aus die `after()`-Methode dafür verwenden. Oder es muss tatsächlich im Hintergrund etwas laufen, also zu OOP und ereignisorientierter Programmierung käme dann auch noch das Thema nebenläufige Programmierung. Und das für ein Programm das noch nicht einmal Listen oder Funktionen verwendet und alles einfach so auf Modulebene stehen hat.