mitmario.dev

Parameter, Standardwerte, Namen

Python Sandbox 4 Min Lesezeit 5 BeispieleLektion 3 von 9

Ein Preis mit Rabatt hängt an zwei Zahlen, dem Preis und dem Prozentsatz. Bisher hatte jede Funktion in diesem Abschnitt einen Parameter. Eine Funktion darf aber so viele haben, wie sie braucht. Sie stehen beim def nebeneinander, mit Kommas getrennt, und beim Aufruf stehen die Argumente genauso da.

Zwei Parameter, eine Reihenfolge
def rabattiert(preis, prozent):
    return preis * (100 - prozent) / 100


print(rabattiert(80, 25))
print(rabattiert(25, 80))

Welches Argument in welchem Parameter landet, entscheidet allein die Reihenfolge. Das erste kommt in den ersten Parameter, das zweite in den zweiten. rabattiert(80, 25) rechnet also 80 Euro mit 25 Prozent Rabatt, und das sind 60 Euro.

Schreibst du es andersherum, rechnet Python ohne zu zögern 25 Euro mit 80 Prozent Rabatt aus, und heraus kommen 5 Euro. Eine Fehlermeldung gibt es nicht, denn für Python sind beides einfach zwei Zahlen. Woher soll es wissen, was davon der Preis ist?

So ein Fehler fällt erst auf, wenn jemand das Ergebnis ansieht. Manchmal nicht mal dann. Mit den beiden Werkzeugen aus dieser Lektion passiert er seltener.

Standardwerte

Ein Standardwert für die Steuer
def brutto(netto, mwst=19):
    return round(netto * (1 + mwst / 100), 2)


print(brutto(100))
print(brutto(100, 7))
print(brutto(4.20, 7))

In Deutschland gelten fast überall 19 Prozent Mehrwertsteuer, für Lebensmittel und Bücher aber 7. Ein Parameter für die Steuer ist deshalb sinnvoll. Nur müsstest du dann bei jedem Aufruf 19 hinschreiben, obwohl es fast immer 19 sind.

Dafür gibt es den Standardwert (default). mwst=19 in der Zeile mit def heißt, dass Python 19 nimmt, wenn dieses Argument beim Aufruf fehlt. Mit brutto(100) wird also mit 19 Prozent gerechnet, mit brutto(100, 7) mit 7. Ein Parameter mit Standardwert ist freiwillig, einer ohne ist Pflicht. Fehlt so einer, kommt der TypeError mit missing 1 required positional argument aus Lektion 8.1.

Den Standardwert kennst du übrigens schon von der anderen Seite. get bei den Dictionaries hat einen freiwilligen zweiten Wert. Und round(wert) rundet ohne zweites Argument auf ganze Zahlen, round(wert, 2) auf zwei Stellen.

Parameter mit Standardwert stehen hinten. def brutto(mwst=19, netto): lehnt Python ab, mit SyntaxError: parameter without a default follows parameter with a default. Der Grund ist einfach. Bei brutto(100) wüsste Python sonst nicht, ob die 100 die Steuer ist, die man ändern wollte, oder der Preis, der fehlt.

Benannte Argumente

Mit Namen aufrufen
def kaffee(groesse, milch=False, extra_shot=False):
    preis = 2.20
    if groesse == "groß":
        preis = 2.90
    if milch:
        preis += 0.40
    if extra_shot:
        preis += 0.60
    return round(preis, 2)


print(kaffee("klein"))
print(kaffee("groß", True))
print(kaffee("klein", False, True))
print(kaffee("klein", extra_shot=True))
print(kaffee(extra_shot=True, groesse="groß", milch=True))

Beim Kaffee gibt es drei Fragen. Welche Größe, mit Milch, mit einem zusätzlichen Schuss Espresso? Die beiden letzten sind Ja-oder-nein-Fragen, und dafür gibt es True und False.

Beim dritten Aufruf siehst du das Problem. kaffee("klein", False, True) stimmt, aber wer die Zeile liest, muss erst nachsehen, welches True und False was bedeutet. Im vierten Aufruf steht es mit extra_shot=True gleich dabei. Das ist ein benanntes Argument (keyword argument). Es besteht aus dem Namen des Parameters, einem Gleichheitszeichen und dem Wert, üblicherweise ohne Leerzeichen dazwischen. Damit landet der Wert in genau diesem Parameter, egal an welcher Stelle er steht. milch wird übersprungen und behält seinen Standardwert.

Im letzten Aufruf hat jedes Argument einen Namen, und die Reihenfolge ist durcheinander. Auch das geht, denn mit Namen spielt die Reihenfolge keine Rolle mehr. Lesbarer wird so ein Aufruf trotzdem, wenn sie stimmt.

Ob man Namen dazuschreibt, hängt davon ab, wer den Aufruf später liest. Bei brutto(100) ist klar, was gemeint ist. Bei einer Zahl oder einem True, dessen Bedeutung man nicht sieht, lohnt sich der Name. brutto(100, mwst=7) erklärt sich selbst, und ein True allein erklärt gar nichts.

Auch print hat Standardwerte

Auch print hat Standardwerte
print("Brot", "Milch", "Eier")
print("Brot", "Milch", "Eier", sep=", ")
print("Brot", end=" und ")
print("Milch")

In Lektion 4.5 stand end=" " in einem print, mit dem Versprechen, dass sich die Schreibweise hier klärt. end ist ein Parameter von print, und sein Standardwert ist ein Zeilenumbruch. Darum endet jede Ausgabe mit einem neuen Zeilenanfang, solange man nichts anderes sagt.

Daneben gibt es sep (von separator, Trenner), der zwischen mehrere Werte gesetzt wird. Sein Standardwert ist ein Leerzeichen. Mit sep=", " wird aus drei Wörtern eine Aufzählung, und end=" und " lässt die Zeile offen, damit die Milch hinten dranhängt. Beides geht nur mit Namen, denn print nimmt beliebig viele Werte, und ohne Namen wäre das ", " einfach ein vierter.

Erst ohne Namen, dann mit

Erst ohne Namen, dann mit
def brutto(netto, mwst=19):
    return round(netto * (1 + mwst / 100), 2)


print(brutto(netto=100, mwst=7))
print(brutto(mwst=7, 100))

Argumente ohne und mit Namen darfst du mischen, aber nur in einer Reihenfolge. Erst kommen die ohne Namen, dann die mit. Hier läuft nicht einmal der erste Aufruf, obwohl der in Ordnung ist. Python liest die ganze Datei, bevor es irgendetwas ausführt, stößt auf brutto(mwst=7, 100) und lehnt ab, mit SyntaxError: positional argument follows keyword argument.

Gemeint ist, dass ein Argument nach seiner Stelle (positional) auf eins mit Namen (keyword) folgt, und welche Stelle sollte die 100 dann haben? Ein SyntaxError hält das Programm schon vor der ersten Zeile an, wie eine fehlende Klammer.

Ein Tippfehler im Namen gibt dagegen erst beim Aufruf einen Fehler. brutto(100, steuer=7) endet mit TypeError: brutto() got an unexpected keyword argument 'steuer', weil es einen Parameter mit diesem Namen nicht gibt. Die Namen der Parameter gehören damit zur Funktion wie ihr eigener Name. Wenn du einen davon umbenennst, musst du jeden Aufruf mitändern, der diesen Namen benutzt.

Was die Aufgabe will

Ein Laden rechnet Preise aus. Vom Nettopreis geht ein Rabatt in Prozent ab, und darauf kommt die Mehrwertsteuer. Der Rabatt ist meistens null, die Steuer meistens 19 Prozent. Gebraucht wird dafür eine Funktion mit drei Parametern, zwei davon mit Standardwert, und pruefen.py ruft sie mit und ohne Namen auf.

Zum Mitnehmen

Hat eine Funktion mehrere Parameter, entscheidet beim Aufruf die Reihenfolge, welches Argument wohin kommt. Ein Parameter mit Standardwert wie mwst=19 darf beim Aufruf fehlen. Schreibst du beim Aufruf den Namen dazu, etwa mwst=7, musst du dir die Reihenfolge nicht merken, und man sieht gleich, was gemeint ist.

Jetzt du

Basis Konto, kostenlos

Zu 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.