Abschnitt 8 · Lektion 4
Mehrere Rückgaben
return gibt einen Wert zurück, und mit return ist die Funktion zu Ende. Manche Fragen haben aber
zwei Antworten. Wie viele Minuten und wie viele Sekunden sind 135 Sekunden? Wie viel kam diesen
Monat herein, und wie viel ging hinaus? Zwei Funktionen, die beide dieselbe Liste durchgehen, wären
doppelte Arbeit.
Ein Tupel zurückgeben
def minuten_und_sekunden(gesamt):
return gesamt // 60, gesamt % 60
ergebnis = minuten_und_sekunden(135)
print(ergebnis)
print(type(ergebnis))
minuten, sekunden = minuten_und_sekunden(135)
print(f"{minuten} Minuten und {sekunden} Sekunden") Hinter return dürfen mehrere Werte stehen, mit Kommas getrennt. Zurück kommt dann ein Tupel, und
in ergebnis siehst du es als (2, 15), Klammern inklusive.
In Lektion 5.7 stand, dass ein Tupel durch das Komma entsteht und nicht durch die Klammer. Hier
zahlt sich das aus. return gesamt // 60, gesamt % 60 ist ein einziger Wert, ein Tupel aus zwei
Zahlen. Die Funktion gibt also auch hier genau eine Sache zurück. Die besteht nur aus zwei Teilen.
Mit einem Tupel in einer Variablen bist du aber noch nicht weit, denn bei ergebnis[0] und
ergebnis[1] weiß niemand, was drinsteht. Deshalb packt man es beim Aufruf meistens gleich aus.
Links stehen so viele Namen, wie Werte zurückkommen, und jeder Name bekommt seinen Wert in der
Reihenfolge, in der sie hinter dem return stehen. Die Rechnung selbst kennst du schon, ganzzahlig
geteilt und der Rest.
Python hat für genau diese Rechnung übrigens schon eine eingebaute Funktion, divmod(135, 60), und
die gibt ebenfalls ein Tupel zurück, (2, 15).
def bilanz(buchungen):
rein = 0
raus = 0
for betrag in buchungen:
if betrag > 0:
rein += betrag
else:
raus += betrag
return rein, raus
kontoauszug = [2450.00, -890.00, -64.90, -23.40, 120.00, -310.75]
einnahmen, ausgaben = bilanz(kontoauszug)
print(f"Rein: {einnahmen:.2f} Euro")
print(f"Raus: {ausgaben:.2f} Euro")
print(f"Übrig: {einnahmen + ausgaben:.2f} Euro") Ein Kontoauszug wird einmal durchgegangen, und am Ende stehen zwei Summen fest. Was hereinkam und
was hinausging. In der Schleife landet jeder Betrag nach seinem Vorzeichen auf einem der beiden
Stapel, und return rein, raus gibt beide zurück.
Beim Aufruf heißen sie anders als in der Funktion, nämlich einnahmen und ausgaben. Das ist in
Ordnung, denn ausgepackt wird nach der Reihenfolge und nicht nach dem Namen. Wer die Namen links
vertauscht, hat deshalb die Ausgaben unter einnahmen stehen, und Python merkt nichts davon. Das
ist derselbe leise Fehler wie bei den vertauschten Argumenten in der letzten Lektion.
Ein Name zu viel
def minuten_und_sekunden(gesamt):
return gesamt // 60, gesamt % 60
stunden, minuten, sekunden = minuten_und_sekunden(4000) Die Funktion gibt zwei Werte zurück, links stehen aber drei Namen. Das endet mit
ValueError: not enough values to unpack (expected 3, got 2). Python sollte drei Werte auspacken
und hat nur zwei bekommen. Mit zu wenigen Namen heißt es andersherum too many values to unpack.
Beide Meldungen nennen die Zahlen, und damit findest du fast immer die Zeile, in der ein Wert
vergessen oder einer zu viel erwartet wurde.
Wenn es nichts zu rechnen gibt
def spanne(preise):
return min(preise), max(preise)
print(spanne([2.49, 0.99, 7.99]))
print(spanne([])) Der billigste und der teuerste Preis einer Liste, das sind min und max. Bei drei Preisen klappt
das, bei keinem nicht. Dann kommt ValueError: min() iterable argument is empty. Von nichts gibt es
kein Kleinstes.
Eine leere Liste ist aber nichts Ungewöhnliches. Ein Monat ohne Buchungen, eine Suche ohne Treffer, ein Zettel, auf dem noch nichts steht. Die Funktion sollte das aushalten, und zwar so, dass man es an der Stelle des Aufrufs merkt.
def spanne(preise):
if not preise:
return None, None
return min(preise), max(preise)
billigste, teuerste = spanne([2.49, 0.99, 7.99])
print(billigste, teuerste)
billigste, teuerste = spanne([])
if billigste is None:
print("Keine Preise, keine Spanne.") Wenn die Liste leer ist, gibt die Funktion jetzt gleich am Anfang zurück, mit dem frühen return
aus Lektion 8.2. Sie gibt zweimal None zurück, das „kein Wert“. Beim Aufruf werden wie immer zwei
Namen ausgepackt, und danach wird mit is None gefragt, ob es überhaupt eine Spanne gibt.
Zweimal None und nicht einmal, denn wer zwei Werte verspricht, liefert auch im leeren Fall zwei.
An dieser Stelle vertut man sich gern. Mit nur return None käme beim Auspacken ein einzelnes
None an, wo zwei Werte erwartet werden, und das Programm endet mit
TypeError: cannot unpack non-iterable NoneType object.
Ein Tupel oder ein Dictionary
def kassensturz(buchungen):
rein = sum([b for b in buchungen if b > 0])
raus = sum([b for b in buchungen if b < 0])
return {
"rein": rein,
"raus": raus,
"uebrig": rein + raus,
"buchungen": len(buchungen),
}
ergebnis = kassensturz([2450.00, -890.00, -64.90, -23.40, 120.00, -310.75])
print(f"{ergebnis['buchungen']} Buchungen, übrig: {ergebnis['uebrig']:.2f} Euro") Ein Tupel ist gut, solange es wenige Werte sind und sich ihre Reihenfolge von selbst versteht. Minuten vor Sekunden, das Kleinste vor dem Größten. Bei vier Werten weiß beim Aufruf niemand mehr, ob die Zahl der Buchungen an dritter oder an vierter Stelle kam. Dann ist ein Dictionary die bessere Form. Du holst dir darin, was du brauchst, über den Namen, und die Reihenfolge ist egal.
Die beiden Summen werden diesmal mit einer List Comprehension ausgerechnet. Und {...} über mehrere
Zeilen geschrieben liest sich wie eine kleine Tabelle.
Eine feste Grenze gibt es nicht. Ein Dictionary lohnt sich, sobald man beim Auspacken überlegen muss, welcher Wert wohin gehört. Das Kleinste, das Größte und der Durchschnitt gehen als Tupel noch gut, weil man sie in dieser Reihenfolge auch sagt.
Was die Aufgabe will
Eine Wetterstation misst jeden Tag die Temperatur. Aus einer Liste solcher Messwerte soll eine Funktion den kleinsten, den größten und den Durchschnitt auf einmal zurückgeben. Und auch ein Tag ohne Messung darf sie nicht umwerfen.
Zum Mitnehmen
Stehen hinter return mehrere Werte mit Kommas dazwischen, kommt ein Tupel zurück, und beim Aufruf packst du es gleich in ebenso viele Namen aus. Auch bei einer leeren Liste kommen so viele Werte zurück, notfalls lauter None. Bei vielen Werten ist ein Dictionary oft die bessere Form.
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.