@Laura98: Okay, vorsicht, viel Kritik, bitte nicht davon erschlagen lassen.
Die Sternchenimporte sollten nicht sein. Dadurch weiss man nicht mehr so einfach wo welcher Name her kommt, und speziell bei `tkinter` holst Du Dir ca. 190 Namen ins Modul von denen dann nur ein ganz kleiner Bruchteil tatsächlich verwendet wird. Zudem besteht bei Sternchenimporten die Gefahr von Namenskollisionen.
Das sich das Programm auf die implizite Erstellung eines `Tk`-Exemplars verlässt ist ungewöhnlich. Das würde ich explizit erstellen. So wie es jetzt ist, kann man `SnakeSpiel` auch nur mit einem `Tk`-Exemplar verwenden und nicht in einen anderen Rahmen einbetten. Das ist ein bisschen unflexibel. Da wäre es besser gleich von `Tk` zu erben, statt von `Frame`.
Auf Modulebene sollte nur Code stehen, der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Wenn man das macht, dann fallen ein paar Fehler im Programm auf, denn an einigen Stellen greifen Methoden in `SnakeSpiel` auf `welt` ausserhalb der Klasse auf Modulebene zu, statt auf das `welt`-Attribut des eigenen Objekts.
Es gibt keinen vernünftigen Grund `canvas` nicht auszuschreiben und stattdessen `canv` zu schreiben. Abkürzungen erschweren das flüssige lesen des Quelltextes, ausser es sich allgemein bekannte Abkürzungen.
Insgesamt stimmen an einigen Stellen die Verantwortlichkeiten nicht, das heisst es wird da von aussen zu tief in Objekte hinein- und durchgegriffen. Das zum Beispiel sie `Snake`-Klasse überhaupt gar keine Methoden hat ist ein Warnzeichen dafür. Und was im Hauptprogramm alles mit `spiel.master` gemacht wird, gehört dort auch nicht hin.
Die `Snake`-Klasse sollte als einzige wissen müssen wie sie intern aufgebaut ist. Wenn man zum Beispiel die Darstellung von einer Python-Liste mit `SnakeKoerperTeil`-Elementen auf eine verkettete Liste mit entsprechend geänderten `SnakeKoerperTeil`-Objekten ändern würde, dann sollten Codeänderungen dafür *nur* in der `Snake`-Klasse nötig sein. Du hast den ganzen Code dafür aber in der `SnakeSpiel`-Klasse stehen.
Was auch etwas mit dem Problem zu tun hat da jetzt noch den Arduino mit zu integrieren. `SnakeSpiel` macht zu viel. Das ist die Spiellogik *und* die GUI in einer Klasse. Das sollte getrennt sein. Dann kann man nämlich die Spiellogik so in einer Klasse kapseln, dass das selbe Objekt als Grundlage für Anzeige und Steuerung für GUI und Arduino-Schnittstelle dienen kann, und auch GUI- und Arduino-Code unabhängig voneinander sind.
Warum wird der `Canvas` ausserhalb der `SnakeSpiel`-Klasse erzeugt? Und wenn man das so macht, waraum wird das `Canvas`-Objekt dann nicht beim erzeugen der `SnakeSpiel`-Klasse übergeben, sondern erst später mit einem trivialen Setter von aussen gesetzt? Nach dem die `__init__()` durchgelaufen ist, sollte eine Klasse alle Attribute besitzen und verwendbar sein. Zudem sind trivialle Getter- und Setter-Methoden ”unpythonisch”. Man greift in solchen Fällen in Python direkt auf die Attribute zu.
Die Namensschreibweisen halten sich nicht an den
Style Guide for Python Code. `Spiellogik` hat neben der Schreibweise als Klasse, noch das Problem das es keine Tätigkeit beschreibt. Denn üblicherweise sind Funktions- und Methodennamen die Tätigkeit die von der Funktion oder Methode durchgeführt wird.