Abschnitt 8 · Lektion 8
Ein Programm aufteilen
Programme wachsen. Erst sind es fünf Zeilen, dann zwanzig, dann fünfzig, und irgendwann fährst du beim Lesen mit dem Finger mit, um nicht zu vergessen, wo du gerade bist. Es gibt ein recht zuverlässiges Zeichen dafür, dass ein Programm in Teile zerlegt werden will. Man fängt an, Kommentare zu schreiben, die sagen, wo man gerade ist.
Ein Skript am Stück
# Kaffeekasse: Wer hat wie viel eingezahlt?
einzahlungen = [("Mia", 5.00), ("Ole", 2.50), ("Mia", 3.00), ("Aylin", 10.00), ("Ole", 2.50)]
# jetzt wird zusammengezählt
summen = {}
for name, betrag in einzahlungen:
summen[name] = summen.get(name, 0) + betrag
# und jetzt kommt die Ausgabe
print("Kaffeekasse")
for name in sorted(summen):
print(f"{name:<10}{summen[name]:6.2f}")
print(f"{'Zusammen':<10}{sum(summen.values()):6.2f}") Eine Kaffeekasse im Büro, und du willst wissen, wer diese Woche wie viel eingezahlt hat. Das
Programm ist kurz und tut, was es soll. Die beiden Kommentare # jetzt wird zusammengezählt und
# und jetzt kommt die Ausgabe sind trotzdem ein Hinweis.
Sie trennen Abschnitte, die nichts miteinander zu tun haben, außer dass der eine dem anderen seine Ergebnisse weiterreicht. Dafür gibt es Funktionen. Ein Name erklärt einen Abschnitt besser als ein Kommentar darüber.
In Funktionen zerlegt
def zusammenzaehlen(einzahlungen):
summen = {}
for name, betrag in einzahlungen:
summen[name] = summen.get(name, 0) + betrag
return summen
def bericht(summen):
print("Kaffeekasse")
for name in sorted(summen):
print(f"{name:<10}{summen[name]:6.2f}")
print(f"{'Zusammen':<10}{sum(summen.values()):6.2f}")
def main():
einzahlungen = [("Mia", 5.00), ("Ole", 2.50), ("Mia", 3.00), ("Aylin", 10.00), ("Ole", 2.50)]
summen = zusammenzaehlen(einzahlungen)
bericht(summen)
main() Dasselbe Programm, dieselbe Ausgabe, aber in drei Teilen. zusammenzaehlen rechnet und gibt das
Ergebnis zurück, wie es sich für Funktionen gehört, die etwas ausrechnen. bericht gibt aus, das
ist ihre ganze Aufgabe. Und main ruft beide in der richtigen Reihenfolge auf und reicht weiter,
was die eine liefert und die andere braucht.
main heißt so, weil es die Hauptfunktion ist (main, Haupt-). Der Name ist eine Abmachung und keine
Regel von Python. Wenn du ein fremdes Programm öffnest, suchst du zuerst nach ihr, denn sie liest
sich wie ein Inhaltsverzeichnis. Drei Zeilen, und du weißt, was das Programm tut, ohne eine einzige
Schleife gelesen zu haben. Wie es das im Einzelnen tut, steht in den Funktionen darüber, und die
liest man erst, wenn man es wissen will.
Ganz unten steht dann nur noch ein einziger Aufruf, main(). Er muss unter allen def stehen, denn
erst wenn alle Funktionen angelegt sind, darf die erste laufen. In welcher Reihenfolge die
Funktionen darüber stehen, ist dagegen egal.
Wie fein man zerlegt, ist eine Frage des Augenmaßes. Ein guter Anhaltspunkt ist ein einziges Wort. Wenn du für das, was eine Funktion tut, ein „und“ brauchst, hast du zwei vor dir. „Rechnet die Summen aus“ ist eine Funktion. „Rechnet die Summen aus und druckt sie“ sind zwei, und so ist das Beispiel geschnitten.
Wenn eine andere Datei es benutzt
from kasse import zusammenzaehlen
summen = zusammenzaehlen([("Mia", 1.50), ("Mia", 1.50)])
print("Mia hat diese Woche", summen["Mia"], "Euro eingezahlt.") def zusammenzaehlen(einzahlungen):
summen = {}
for name, betrag in einzahlungen:
summen[name] = summen.get(name, 0) + betrag
return summen
def bericht(summen):
print("Kaffeekasse")
for name in sorted(summen):
print(f"{name:<10}{summen[name]:6.2f}")
print(f"{'Zusammen':<10}{sum(summen.values()):6.2f}")
def main():
einzahlungen = [("Mia", 5.00), ("Ole", 2.50), ("Mia", 3.00), ("Aylin", 10.00), ("Ole", 2.50)]
summen = zusammenzaehlen(einzahlungen)
bericht(summen)
main() Zerlegte Programme haben noch einen Vorteil. Ihre Teile lassen sich woanders benutzen. Hier holt
sich auswertung.py die Funktion zusammenzaehlen mit import aus kasse.py, um eine eigene
kleine Rechnung zu machen. Ausgegeben werden soll nur die eine Zeile über Mia.
Vorher kommt aber der ganze Bericht der Kaffeekasse. Beim Importieren führt Python die Datei
kasse.py einmal von oben bis unten aus, damit die Funktionen darin angelegt werden. Und ganz unten
steht main(). Also läuft das ganze Programm mit.
Die pruefen.py der Aufgaben importiert deine Funktionen seit Lektion 8.2 genauso. Stünde in
main.py ein Programm, liefe es dort jedes Mal mit.
Wie heißt diese Datei?
print("helfer.py heißt hier:", __name__) import helfer
print("main.py heißt hier:", __name__) Die Lösung hängt an einem Namen, den Python jeder Datei gibt, die läuft, nämlich __name__ mit zwei
Unterstrichen davor und dahinter. Bei einer Datei, die importiert wird, ist das ihr eigener Name
ohne .py, hier helfer. Bei der Datei, die gestartet wurde, ist es immer __main__, egal wie sie
heißt. Das stand schon in der ersten Zeile von help().
Nur wenn sie gestartet wird
from kasse import zusammenzaehlen
summen = zusammenzaehlen([("Mia", 1.50), ("Mia", 1.50)])
print("Mia hat diese Woche", summen["Mia"], "Euro eingezahlt.") def zusammenzaehlen(einzahlungen):
summen = {}
for name, betrag in einzahlungen:
summen[name] = summen.get(name, 0) + betrag
return summen
def bericht(summen):
print("Kaffeekasse")
for name in sorted(summen):
print(f"{name:<10}{summen[name]:6.2f}")
print(f"{'Zusammen':<10}{sum(summen.values()):6.2f}")
def main():
einzahlungen = [("Mia", 5.00), ("Ole", 2.50), ("Mia", 3.00), ("Aylin", 10.00), ("Ole", 2.50)]
summen = zusammenzaehlen(einzahlungen)
bericht(summen)
if __name__ == "__main__":
main() Damit lässt sich fragen, ob diese Datei die ist, die gestartet wurde. if __name__ == "__main__":
ist diese Frage, und darunter steht der Aufruf main(). Wird kasse.py gestartet, stimmt die
Bedingung, und der Bericht kommt. Importiert eine andere Datei sie, heißt sie kasse. Dann stimmt
die Bedingung nicht, und es werden nur die Funktionen angelegt. auswertung.py gibt jetzt nur noch
ihre eine Zeile aus.
Beim ersten Mal sieht die Zeile aus wie eine Beschwörungsformel, und man kann sie jahrelang
abschreiben, ohne sie je zu lesen. Gelesen heißt sie, dass etwas nur läuft, wenn diese Datei
gestartet wird, und nicht, wenn eine andere sie benutzt. Mehr dazu und zu import überhaupt steht
in Lektion 10.3. Für jetzt reicht, dass jedes Programm ab hier so endet.
Was die Aufgabe will
Ein Wochenbericht für das Haushaltsbuch, gut dreißig Zeilen am Stück, mit Kommentaren, die sagen, wo
man gerade ist. Er soll in Funktionen zerfallen, ohne dass sich an der Ausgabe etwas ändert. Zuletzt
kommt der Aufruf von main() hinter if __name__ == "__main__":.
Zum Mitnehmen
Ein längeres Skript zerlegt man in Funktionen, von denen jede eine Aufgabe hat, meistens einlesen, rechnen und ausgeben. Dazu kommt eine Funktion main(), die sie der Reihe nach aufruft. main() selbst wird unter if __name__ == "__main__": aufgerufen, damit das Programm nur läuft, wenn die Datei gestartet wird, und nicht, wenn eine andere sie importiert.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 5 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.