Python mit der Schildkröte?
Nach der Entscheidung für Python als Programmiersprache im Informatikunterricht der Mittelstufe zum Sommer 2008 war für mich unstrittig, dass die klassische „EVA-Terminal-Programmierung“ um graphische Darstellung und zeitgemäße Möglichkeiten der Anwenderinteraktion erweitert werden mussten. Bloß wie?
Die Turtle-Grafik-Idee war aus meiner Sicht zwar geeignet, das damalige Python-Modul turtle war aber viel zu schwachbrüstig und unattraktiv. Das hatte vor mir auch schon Gregor Lingl erkannt und daraufhin das Modul xturtle entwickelt. Im Herbst 2008 wurde dieses – nun unter dem Namen turtle – in die offizielle Python-Version 2.6 aufgenommen und ist seitdem fester Bestandteil der Standardbibliothek von Python.
Die neue Schildkröte
Das Modul xturtle bzw. das „neue“ Modul turtle hat – abgesehen vom Grundprinzip und der Abwärtskompatibilität – wenig gemein mit dem alten turtle-Modul. Es ist erheblich umfangreicher und ebenso auch erheblich leistungsfähiger.
Während das alte turtle-Modul aus weniger als 1000 Zeilen Code besteht, kommt das xturtle-Modul auf 3000 Zeilen und als turtle-Modul in der aktuellen Python 3.x-Implementierung sogar auf deutlich mehr als 4000 Zeilen (jeweils mit einem Anteil von schätzungsweise 40-50% an Kommentarzeilen).
Die Schildkröte im Einsatz
Das folgende Beispiel zeigt die Funktionsweise und den Aufbau eines einfachen turtle-Programms, nicht die Leistungsfähigkeit des Moduls. Dazu genügt ein Blick in die vollständige Referenz des turtle-Moduls als Bestandteil der offiziellen Dokumention der Standardbibliothek von Python. Ebenso empfehlenswert ist das (leider schon einige Jahre alte) Buch Python 4 Kids von Gregor Lingl (das Nachfolgewerk von Hans-Georg Schumann mit gleichem Titel aus demselben Verlag möchte ich hingegen ausdrücklich nicht empfehlen).
Beispiel (Python 3 mit turtle):
from turtle import Screen,RawTurtle area = Screen() pen = RawTurtle(area) area.colormode(255) area.bgcolor("#444") pen.pensize(4) for k in range(60,0,-1): pen.pencolor(4*k+10,255-2*k,4*k) pen.forward(200) pen.left(157) pen.penup() pen.backward(40) pen.pendown() pen.right(28) pen.penup() pen.color("lime") pen.goto(122,49) pen.dot(50) area.mainloop()
Den Ablauf des Programms kann man sich im Ausgabefenster ansehen:
Die Schwächen der Schildkröte
Ich habe für die Umsetzung bewusst die objektorientierte Darstellung des xturtle-Moduls gewählt, weil daran deutlicher wird, was mir nicht gefällt. Alternativ (und eher üblich) kann statt mit Objekten und Methoden auch nur mit Funktionen gearbeitet werden.
Im Grunde sind es letztlich drei Aspekte, die mir nicht gefallen und die dazu geführt haben, das turtle-Modul nicht einsetzen zu wollen:
- Die Nutzung der Grundfunktionalität – Bewegen und Zeichnen – ist zu umständlich.
Getrennte Befehle für Vorwärts- und Rückwärtsbewegung ebenso wie für Links- und Rechtsdrehung sind nicht nur überflüssig, sondern verkomplizieren manche Problemlösung und verlängern den Quelltext. Auch die penup()- und pendown()-Methoden bzw. -Funktionen empfinde ich als zu umständlich: Man muss quasi Buch führen über die jeweils aktuelle Stiftposition (oben oder unten). Gerade bei längeren Programmen ist das lästig und fehleranfällig. - Zwischen Methoden (Fähigkeiten) und Datenattributen (Eigenschaften) wird nicht konsequent unterschieden.
An diesem Punkt werden die Kriterien für eine „semantische Programmierung“ nicht erfüllt, und das halte ich gerade im Hinblick auf den vorgesehen Einsatzzweck für unglücklich (und vermeidbar). Die Farbe – sei es der Hintergrund oder die Zeichenfarbe – sind definitiv keine Fähigkeiten von Screen oder Turtle, sondern Eigenschaften. Dementsprechend sollten sie als Datenattribute und nicht als Methoden realisiert werden. - Die Implementation ist unaufgeräumt und unnötig umständlich.
Das kann man am Beispiel nicht erkennen, sondern nur durch Analyse des turtle-Quelltextes. Und da kann ich sagen: Halb so viel Quelltext genügt, um die gleiche Funktionalität sauberer zu implementieren.
Python ohne Schildkröte
Die genannten Kritikpunkte an xturtle waren für mich ausreichend, um dieses Modul nicht im Unterricht einsetzen zu wollen, obwohl mir die Grundidee der turtle-Grafik nach wie für den Informatikunterricht geeignet und tragfähig erschien. Eine Alternative gab es nicht. Also bin ich 2008 selbst tätig geworden und habe ein turtle-Grafik-Modul für Python entwickelt, das die beschriebenen Nachteile von (x)turtle nicht hat.
Python mit dem Frosch
Die Schildkröte war schon vergeben, ein anderes Tierchen musste her: Ein Frosch passt gut, denn der kann – anders als die Schildkröte –
von einem Ort zum anderen „springen“ (= Bewegen ohne Zeichnen) oder „schwimmen“ (= Bewegen mit Zeichnen).
Damit hatte das frog-Modul seinen Namen.
Froschtheorie
Anders als Gregor Lingl, der bei der Entwicklung von xturtle im HInblick auf die Übernahme in die Python-Standardbibliothek auf Abwärtskompatiblität zum (alten) turtle-Modul mit allen seinen Unzulänglichkeiten achten musste, hatte ich diesbezüglich alle Freiheiten. Die habe ich genutzt, um das frog-Modul durchgängig objektorientiert zu gestalten. Das ist nur konsequent, denn ein Frosch ist nun offensichtlich ein Objekt mit bestimmten Eigenschaften und Fähigkeiten; auch der Teich („Pool“) als Lebensraum des Frosches hat gewisse Eigenschaften. Bei der Implementation war mir Klarheit und Stringenz wichtig, und so ist der Umfang des Quelltextes weniger als halb so groß wie der von (x)turtle – bei vergleichbarem Funktionsumfang.
Neben der Grundfunktionalität – Bewegen und Zeichnen – war mir vor allem ein für die Schüler verständlicher und klarer Zugang zur Ereignisbehandlung wichtig. So können z.B. Frosch-Objekte darauf „lauschen“, ob sie mit der Maus angeklickt werden und dann gemäß den Wünschen des Programmierers reagieren. Wie das in der Praxis aussehen kann, zeigt das zweite der beiden folgenden Beispiele.
Froschpraxis
Zunächst zeige ich das frog-Äquivalent zum obigen turtle-Code. Der Quelltext ist nicht nur um einige Zeilen kürzer, sondern zeigt auch
wie meine Lösung der oben formulierten Kritik am turtle-Modul konkret aussieht: Es gibt zwei Methoden für die Bewegung, die entweder mit einer Zeichenaktion
verbunden ist (move
) oder eben nicht (jump
). Zu beiden Methoden gibt es eine Entsprechung zur absoluten Positionierung des
Froschs (moveto
bzw. jumpto
). Für (relative) Drehungen wird nur eine Methode benötigt (turn
), die je nach Vorzeichen
des übergebenen Winkels eine Links- bzw. Rechtsdrehung bewirkt; auch hier gibt es mit turnto
eine Entsprechung zur absoluten Winkelausrichtung.
from frog import Pool,Frog area = Pool() pen = Frog(area) area.bgcolor = "#444" pen.width = 4 for k in range(60,0,-1): pen.color = 4*k+10,255-2*k,4*k pen.move(200) pen.turn(157) pen.jump(-40) pen.turn(-28) pen.color = "lime" pen.jumpto(122,49) pen.dot(50) area.ready()
Das nächste Beispiel demonstriert speziell die Ereignisbehandlung und ihre einfache Zugänglichkeit.
from frog import Pool,Frog from random import randrange as r def draw(event): kermit.jumpto(90,10) kermit.turnto(90) kermit.bodycolor = "lime" for k in range(18): kermit.turn(20) kermit.jump(35) kermit.color=r(256),r(256),r(256) kermit.dot(r(4,30)) kermit.home() kermit.bodycolor = "forestgreen" kermit.color = "black" pool = Pool() pool.bgcolor = "#2e86c1" kermit = Frog(pool) kermit.shape = "frog" kermit.bodycolor = "forestgreen" kermit.visible = True kermit.listen("<Button>",draw) pool.ready()
Hier kann man sich den Programmablauf ansehen. Dazu öffnet sich ein neues Browserfenster. Der Frosch reagiert auf Mausklick und legt dann los ...