Abschnitt 8 · Lektion 1
Eine eigene Funktion
Ein Betrag auf Deutsch braucht ein Zwischenzeichen und drei replace hintereinander. Das
funktioniert, und es ist lang. Auf einer Rechnung steht aber selten nur ein Betrag.
fernseher = 1299
halterung = 49.9
gesamt = fernseher + halterung
print(f"{fernseher:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".") + " €")
print(f"{halterung:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".") + " €")
print(f"{gesamt:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".") + " €") Drei Beträge, dreimal dieselbe Kette. Lesen kann man das nur noch mit Mühe, und es gibt ein Problem,
das du erst später merkst. Soll hinter den Beträgen eines Tages EUR stehen statt €, musst du es
an drei Stellen ändern. Vergisst du eine, steht auf der Rechnung beides. In einem echten Programm
sind es nicht drei Stellen, sondern dreißig.
Die Kette ist immer dieselbe, nur der Betrag wechselt. Dafür gibt es Funktionen (functions). Eine Funktion ist ein Stück Code, das einen Namen bekommt, und über diesen Namen benutzt man es danach, so oft man will.
Die Kette bekommt einen Namen
def euro(betrag):
text = f"{betrag:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")
print(text + " €")
euro(1299)
euro(49.9)
euro(1299 + 49.9) Eine Funktion entsteht mit def (von define, festlegen). Dahinter steht ihr Name, hier euro. Dann
kommt in Klammern ein Name für den Wert, mit dem sie arbeiten soll, und am Ende ein Doppelpunkt.
Darunter steht eingerückt der Rumpf (body), also das, was die Funktion tun soll.
Doppelpunkt und Einrückung funktionieren wie bei if und for. Alles, was eingerückt unter dem
def steht, gehört dazu. Für den Namen gelten dieselben Regeln wie für Variablen, und auch hier
steht er in diesem Kurs deutsch, klein und ohne Umlaute da.
Die Zeile mit def tut dabei noch nichts Sichtbares. Sie legt die Funktion nur an, wie ein Rezept,
das man aufschreibt, ohne zu kochen. Der Rumpf läuft erst beim Aufruf (call). Dafür schreibst du
den Namen der Funktion hin, dahinter Klammern und darin den Betrag. So rufst du print schon die
ganze Zeit auf. Nur hast du euro diesmal selbst geschrieben.
Drei Aufrufe, drei Zeilen Ausgabe, und die Kette steht nur noch an einer Stelle. Soll dort EUR
stehen, änderst du eine Zeile. Die zwei leeren Zeilen nach der Funktion sind übrigens Absicht. Damit
sieht man beim Lesen sofort, wo die Funktion aufhört und das Programm anfängt. Python ist es egal,
Menschen nicht.
Wenn du zusehen willst, wie Python dabei durch den Code springt, zeichnest du das Beispiel im Reiter
Debug auf. Der erste Schritt ist die Zeile mit def. Danach geht es gleich weiter zum ersten Aufruf
in Zeile 6, denn beim Anlegen läuft der Rumpf nicht mit. Von dort springt der Lauf hinauf in die
Funktion, nach Zeile 2 und 3, und am Rand steht betrag mit 1299. Danach geht es zurück nach unten
zum nächsten Aufruf und wieder hinauf, diesmal mit 49.9.
Parameter und Argument
def begruesse(name):
print(f"Hallo {name}!")
print("Schön, dass du da bist.")
begruesse("Mia")
begruesse("Ole")
kundin = "Aylin"
begruesse(kundin) Für die beiden Namen in den Klammern gibt es zwei Wörter, und die werden gern verwechselt. name in
der Zeile mit def ist der Parameter (parameter). Wenn du die Funktion schreibst, weißt du noch
nicht, wer begrüßt wird. Also steht da ein Name, unter dem der Wert später zu finden ist.
Was beim Aufruf in den Klammern steht, "Mia" oder "Ole", ist das Argument (argument), also
der echte Wert. Bei jedem Aufruf bekommt der Parameter das Argument dieses Aufrufs, und der Rumpf
läuft damit einmal von oben nach unten.
Das Argument darf auch eine Variable sein, wie beim dritten Aufruf. Wie sie heißt, spielt keine
Rolle. In der Funktion kommt der Wert an, der in kundin steht, und dort heißt er name. Genauso
darf das Argument eine Rechnung sein, wie 1299 + 49.9 im Beispiel davor. Python rechnet sie zuerst
aus und übergibt das Ergebnis.
def begruesse(name):
print(f"Hallo {name}!")
begruesse("Mia")
begruesse() Der erste Aufruf klappt, der zweite nicht. Es kommt
TypeError: begruesse() missing 1 required positional argument: 'name'. Der Funktion fehlt ein
Argument, und Python sagt sogar, welches. Mit einem Argument zu viel heißt es andersherum
takes 1 positional argument but 2 were given. Ein Parameter heißt also, dass beim Aufruf etwas
hinein muss, und zwar genau eins. Wie man einen Parameter freiwillig macht, steht zwei Lektionen
weiter.
Erst anlegen, dann aufrufen
print("Der Fernseher kostet:")
euro(1299)
def euro(betrag):
text = f"{betrag:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")
print(text + " €") Python liest ein Programm von oben nach unten, und eine Funktion gibt es erst, wenn ihr def
gelaufen ist. Hier steht der Aufruf darüber. Die erste Zeile läuft noch, dann kommt
NameError: name 'euro' is not defined. Das ist derselbe Fehler wie bei einem Tippfehler im Namen,
und für Python ist es auch dasselbe. An dieser Stelle kennt es den Namen euro einfach noch nicht.
Deshalb stehen Funktionen oben in der Datei und das Programm, das sie benutzt, darunter. In welcher Reihenfolge die Funktionen selbst stehen, ist dagegen fast egal. Eine Funktion darf eine andere aufrufen, die weiter unten steht, solange beide angelegt sind, bevor der erste Aufruf läuft.
Ein Fehler in der Funktion
def euro(betrag):
text = f"{betrag:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")
print(text + " €")
euro(12.5)
euro("12,50") Beim zweiten Aufruf kommt der Betrag als Text an, und einen Text kann Python mit :,.2f nicht
formatieren. Die Meldung lautet ValueError: Unknown format code 'f' for object of type 'str'.
Neu ist, wie der Traceback darüber aussieht. Er nennt jetzt zwei Fundstellen. Die untere ist Zeile 2
in euro, also in der Funktion euro, wo es geknallt hat. Die obere ist Zeile 7 in <module>,
also im Programm selbst, wo die Funktion aufgerufen wurde. In Lektion 1.4 stand, dass dieses
in <module> erst mit eigenen Funktionen wichtig wird, und hier ist es so weit. Zusammen zeigen die
beiden Zeilen nicht nur, wo es knallte, sondern auch, auf welchem Weg das Programm dorthin kam.
Solche Wege über mehrere Ebenen sind Thema in Lektion 9.1.
Was die Aufgabe will
Auf einem Kassenbon stehen Linien aus Strichen, unter dem Namen des Ladens und über und unter der Summe, und sie sind nicht alle gleich lang. Gesucht ist eine Funktion, die eine solche Linie in jeder gewünschten Länge ausgibt. Dazu kommen drei Stellen auf dem Bon, an denen sie aufgerufen wird.
Zum Mitnehmen
Mit def legst du eine Funktion an. Ihr Rumpf läuft erst, wenn sie aufgerufen wird, und das so oft, wie du willst. Bei jedem Aufruf bekommt der Parameter aus der Zeile mit def das Argument, das in den Klammern steht.
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 6 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.