Alles, was Sie bisher geschrieben haben, war ein Skript: ein Rezept, das einmal von oben nach unten durchläuft. Diese Lektion macht Sie zum Werkzeugbauer. Eine Funktion ist ein benannter Codeblock, der Eingaben entgegennimmt, eine Aufgabe erledigt und ein Ergebnis zurückgibt: und sie verändert Ihre Art zu programmieren mehr als jedes andere einzelne Sprachelement. Funktionen befreien Sie vom Kopieren und Einfügen, erlauben isolierte Tests, lassen ein Programm wie ein Inhaltsverzeichnis lesen statt wie eine Wand aus Zeilen und ermöglichen ab Teil 6 den Bau von Klassen und Modulen, aus denen echte Software besteht.
Es gibt noch einen leiseren Vorteil, der genannt werden sollte. Funktionen zwingen Sie zu entscheiden, was ein Stück Code tatsächlich tut, denn Sie müssen es benennen und festlegen, was hineingeht und was herauskommt. Programmierer entdecken die Hälfte ihrer Entwurfsfehler im Moment der Namensgebung. Wenn Sie eine Funktion nicht ehrlich benennen können, ohne das Wort „und“ zu verwenden, sind es wahrscheinlich zwei Funktionen: und diese Ein-Satz-Regel wird Ihren Code für das nächste Jahrzehnt verbessern.
Was Sie in Teil 4 lernen
- Funktionen mit def definieren, aufrufen und Werte zurückgeben
- Parameter, Argumente, Standardwerte und Schlüsselwortargumente
- Vorzeitige Rückgaben, mehrere Rückgabewerte und was None wirklich bedeutet
- Lokaler versus globaler Gültigkeitsbereich und warum Globale Schmerzen verursachen
- Flexible Signaturen mit *args und **kwargs
- Docstrings und kleine anonyme Funktionen mit lambda
Hinweis
Bevor Sie beginnen
Sie benötigen Bedingungen aus Teil 2 und Schleifen aus Teil 3, denn die Beispielfunktionen verpacken genau diese Art von Logik. Wenn Sie FizzBuzz auswendig schreiben können, sind Sie bereit.
1. Eine Funktion definieren und aufrufen
Eine Funktionsdefinition beginnt mit def, dann dem Namen, dann einer in Klammern gesetzten Parameterliste, dann einem Doppelpunkt und einem eingerückten Rumpf: dieselbe Blockregel, die Sie in Teil 2 gemeistert haben. Die Ausführung der def-Anweisung führt den Rumpf nicht aus; sie erzeugt die Funktion und bindet den Namen. Der Rumpf läuft nur, wenn Sie die Funktion mit Klammern aufrufen, und jeder Aufruf ist eine frische Ausführung mit frischen Variablen. Die return-Anweisung beendet den Aufruf sofort und sendet einen Wert an den Aufrufer zurück.
def grade_for(score):
"""Return the letter grade for a 0-100 score."""
if score >= 75:
return "A"
elif score >= 65:
return "B"
elif score >= 50:
return "C"
elif score >= 35:
return "S"
return "F"
print(grade_for(73)) # B
print(grade_for(91)) # A
result = grade_for(40) # the returned value can be stored, printed, compared
print(result) # S
Das ist die Notenleiter aus Teil 2, aber beachten Sie, wie die Funktionsversion sie verbessert. Die Logik hat jetzt einen Namen, sie kann für tausend Schüler wiederverwendet werden, ohne eine Zeile zu kopieren, und die vorzeitigen Rückgaben machen die elif-Leiter flacher: Sobald ein return ausgeführt wird, ist der Aufruf beendet, also kann jeder Zweig einfach seine Antwort nennen. Die Zeichenkette zwischen dreifachen Anführungszeichen in der ersten Zeile ist ein Docstring, die übliche Art zu dokumentieren, was eine Funktion tut; Editoren zeigen ihn beim Darüberfahren an, und help(grade_for) gibt ihn aus. Ein ehrlicher Satz pro Funktion ist eine professionelle Angewohnheit, die fünf Sekunden kostet.
2. Parameter, Standardwerte und Schlüsselwortargumente
Die Namen in der def-Zeile sind Parameter; die Werte, die Sie beim Aufruf übergeben, sind Argumente. Python ordnet sie standardmäßig nach Position zu, aber Sie können jedes Argument auch beim Namen übergeben, was Aufrufe selbstdokumentierend macht, und Sie können Parametern Standardwerte geben, was sie optional macht. Standardwerte müssen in der Signatur nach den nicht-optionalen stehen, und die Kombination beider Merkmale deckt die meiste Flexibilität ab, die Sie in der Praxis jemals brauchen werden.
def make_greeting(name, punctuation="!", lang="en"):
if lang == "si":
return f"Ayubowan, {name}{punctuation}"
return f"Hello, {name}{punctuation}"
print(make_greeting("Amina")) # Hello, Amina!
print(make_greeting("Amina", "?")) # Hello, Amina?
print(make_greeting("Amina", lang="si")) # Ayubowan, Amina!
print(make_greeting(punctuation=".", name="Zane")) # keyword order is free
Eine Warnung verdient einen eigenen Kasten, denn sie erwischt jeden genau einmal: Verwenden Sie niemals einen veränderlichen Wert wie eine Liste als Standardwert. Standardwerte werden einmal ausgewertet, wenn die Funktion definiert wird, daher wird eine Standardliste von jedem Aufruf geteilt, der sich darauf verlässt, und Elemente sammeln sich auf mysteriöse Weise an. Die übliche Redewendung ist, auf None vorzubelegen und die Liste innerhalb der Funktion zu erzeugen. Sie werden die Mechanik nach Teil 5 vollständig verstehen; übernehmen Sie vorerst die Regel.
# Wrong: the default list is created ONCE and shared
def add_item_bad(item, basket=[]):
basket.append(item)
return basket
# Right: make a fresh list per call
def add_item(item, basket=None):
if basket is None:
basket = []
basket.append(item)
return basket
print(add_item_bad("apple")) # ['apple']
print(add_item_bad("mango")) # ['apple', 'mango'] <- surprise!
print(add_item("apple")) # ['apple']
print(add_item("mango")) # ['mango'] <- correct
Kontrollpunkt
Eine Funktion hat die Signatur def f(a, b=2, c=3). Welcher Aufruf ist ungültig?
3. Rückgaben, None und mehrere Dinge zurückgeben
Jeder Funktionsaufruf erzeugt einen Wert. Wenn der Rumpf niemals ein return ausführt oder ein nacktes return ohne etwas dahinter ausführt, ist der Wert None, der Abwesenheitsmarker, den Sie in Teil 1 kennengelernt haben. Das erklärt eine klassische Verwirrung: print gibt None zurück, also gibt x = print("hi") den Text aus und lässt x mit None zurück. Drucken ist etwas, das eine Funktion tut; Zurückgeben ist das, was sie aushändigt. Halten Sie diese beiden im Kopf auseinander, und eine ganze Kategorie von Anfängerfehlern verschwindet.
Python-Funktionen können auch mehrere Werte auf einmal zurückgeben, indem sie sie nach return durch Kommas getrennt auflisten. Technisch gibt das ein Tupel zurück, das Sie in Teil 5 formal kennenlernen werden, aber die Aufrufseite liest sich so oder so schön: Sie entpacken die Ergebnisse in einer Zeile in Namen. Funktionen, die zwei verwandte Dinge berechnen, wie ein Minimum und ein Maximum oder einen Quotienten und einen Rest, verwenden dies überall in echtem Code.
def min_max(numbers):
lowest = highest = numbers[0]
for n in numbers:
if n < lowest:
lowest = n
if n > highest:
highest = n
return lowest, highest
low, high = min_max([13, 4, 27, 9, 18])
print(f"range: {low} to {high}") # range: 4 to 27
4. Gültigkeitsbereich: wo Namen leben
Variablen, die innerhalb einer Funktion zugewiesen werden, sind lokal: Sie entstehen beim Aufruf und verschwinden, wenn die Funktion endet. Die Funktion kann nicht versehentlich Variablen Ihres Skripts überschreiben, und zwei Funktionen können beide einen Namen wie total verwenden, ohne sich in die Quere zu kommen. Das Lesen einer äußeren Variablen aus einer Funktion heraus funktioniert, aber eine Zuweisung erzeugt stattdessen eine neue lokale Variable: genau dieses Verhalten schützt Sie. Python bietet zwar das Schlüsselwort global, um Zuweisungen auf Modulebene zu erzwingen, doch der professionelle Rat ist unmissverständlich: Lassen Sie es. Funktionen, die über Parameter und Rückgabewerte kommunizieren, lassen sich isoliert verstehen und testen; Funktionen, die nach außen greifen und gemeinsamen Zustand verändern, nicht.
tax_rate = 0.12 # module level, "global" to this file
def price_with_tax(price):
total = price * (1 + tax_rate) # reading a global: fine
return round(total, 2)
print(price_with_tax(1000)) # 1120.0
# print(total) # NameError: 'total' lives only inside the call
Das Lesen globaler Variablen hat eine legitime, alltägliche Form: Konstanten. Werte, die Ihr Programm konfigurieren und sich nie ändern: ein Steuersatz, ein Dateipfad, eine Wiederholungsgrenze: stehen üblicherweise am Anfang der Datei in GROSSBUCHSTABEN_MIT_UNTERSTRICHEN, etwa STEUERSATZ = 0,12, und Funktionen lesen sie ungehindert. Die Großschreibung ist ein Versprechen an jeden Leser, dass dieser Name niemals neu zugewiesen wird. Deshalb ist das Lesen aus Funktionen heraus ehrlich, während das Zuweisen die Sünde ist. Die meisten gepflegten Python-Dateien beginnen mit Importen, dann Konstanten, dann Funktionen: eine Struktur, die Ihre zukünftigen Projekte übernehmen sollten.
5. Flexible Signaturen: *args und **kwargs
Manchmal soll eine Funktion eine beliebige Anzahl von Argumenten akzeptieren; print selbst ist das offensichtliche Beispiel. Ein Parameter, der als *args geschrieben wird, sammelt alle zusätzlichen Positionsargumente in einem Tupel, und **kwargs sammelt zusätzliche Schlüsselwortargumente in einem Wörterbuch. Sie werden diese gelegentlich selbst schreiben und ständig lesen, denn Bibliotheken nutzen sie, um Optionen an tiefere Schichten durchzureichen. Für den Moment genügt ein ehrliches Beispiel, um die Sternchen für immer zu entmystifizieren.
def average(*numbers):
if not numbers: # truthiness, Part 2
return 0.0
return sum(numbers) / len(numbers)
print(average(4, 8)) # 6.0
print(average(1, 2, 3, 4, 5)) # 3.0
print(average()) # 0.0
Das Spiegelbild von *args ist das Entpacken an der Aufrufstelle, und es vervollständigt das Bild: Wenn Ihre Werte bereits in einer Liste oder einem Wörterbuch leben, verteilt ein Stern sie in einen Aufruf. zahlen = [4, 8, 15] und dann durchschnitt(*zahlen) übergibt drei separate Argumente, und optionen = {"interpunktion": "!", "sprache": "si"} mit erstelle_gruss("Amina", **optionen) füllt Schlüsselwortparameter aus dem Dict. Das begegnet Ihnen ständig in Bibliothekscode, wo Funktionen alles, was sie empfangen haben, mit einem einzigen *args, **kwargs-Paar an eine andere Funktion weiterleiten.
Eine weitere Idee gehört in Ihr Modell von Funktionen, bevor Lambdas sinnvoll werden: In Python sind Funktionen Werte. Ein def erzeugt ein Objekt, der Name ist eine gewöhnliche Variable, die darauf zeigt, und Sie können Funktionen in Listen speichern, als Argumente übergeben und von anderen Funktionen zurückgeben. Das ist kein exotischer Trick; so erlaubt sorted die Anpassung der Sortierreihenfolge, und so akzeptiert die halbe Standardbibliothek Verhalten als Parameter. Die Lambda-Syntax unten existiert einzig, um das Übergeben einer kleinen Funktion weniger umständlich zu machen.
6. Lambdas: kleine anonyme Funktionen
Ein Lambda ist eine Funktion ohne Namen und mit einem einzigen Ausdruck als Körper: lambda x: x * 2 ist das Wegwerf-Äquivalent eines zweizeiligen def. Lambdas existieren hauptsächlich, um als Argumente an Funktionen übergeben zu werden, die ein Stück Logik erwarten, und das kanonische Beispiel ist das Sortieren nach einem Schlüssel. sorted akzeptiert eine key-Funktion, die es für jedes Element aufruft, um die Reihenfolge zu bestimmen, und ein Lambda ist die natürliche Art, inline an der Aufrufstelle zu sagen: sortiere nach dem zweiten Element oder sortiere nach Länge. Wenn ein Lambda über einen kurzen Ausdruck hinauswächst, befördern Sie es zu einem def mit Namen; Lesbarkeit gewinnt immer.
students = [("Amina", 87), ("Zane", 91), ("Ruwan", 78)]
by_score = sorted(students, key=lambda s: s[1], reverse=True)
print(by_score)
# [('Zane', 91), ('Amina', 87), ('Ruwan', 78)]
words = ["banana", "fig", "apple"]
print(sorted(words, key=len)) # ['fig', 'apple', 'banana']
Kontrollpunkt
Was hinterlässt x = print("hallo") in x?
7. Praxis: Ein Skript in Funktionen umgestalten
Der Spielplatz unten enthält den Steuerrechner aus Teil 2, umgeschrieben als Funktionen, sowie einen Trinkgeldrechner mit einem absichtlichen Fehler. Ihre Aufgaben: Beheben Sie den Fehler, indem Sie den Traceback lesen, fügen Sie ein Standardargument hinzu und extrahieren Sie eine weitere Funktion. Arbeitsfähigen Code in eine sauberere Form umzugestalten, ist die Hälfte der professionellen Programmierung, und es ist eine Fähigkeit, die Sie nur durch genau dieses Tun aufbauen können.
Beachten Sie die Architektur selbst in diesem vereinfachten Beispiel: tax_rate_for behandelt die Steuerregel, tax_due die Berechnung, und jede Funktion kann geändert werden, ohne die andere zu beeinflussen. Wenn Teil 13 automatisiertes Testen einführt, sind solche Funktionen mühelos testbar, gerade weil sie Eingaben entgegennehmen und Ergebnisse zurückgeben, ohne Seiteneffekte. Gute Struktur heute bedeutet kostenloses Testen später.
! Häufige Fehler, die Sie vermeiden sollten
-
✕Eine Funktion aufrufen, bevor sie definiert wurde, und einen NameError erhalten.
✓Python liest Dateien von oben nach unten; def muss vor dem Aufruf ausgeführt werden. Üblicher Aufbau: zuerst alle Definitionen, dann der Code, der sie verwendet.
-
✕Die Klammern vergessen: result = my_func schreiben statt my_func().
✓Ohne Klammern erhalten Sie das Funktionsobjekt selbst, nicht sein Ergebnis. Wenn Sie etwas wie <function my_func at 0x...> sehen, haben Sie den Aufruf vergessen.
-
✕Eine Liste oder ein Dictionary als Standardwert für einen Parameter verwenden.
✓Standardwerte werden einmal bei der Definition ausgewertet und über alle Aufrufe hinweg geteilt. Setzen Sie den Standard auf None und erzeugen Sie das neue Objekt innerhalb des Funktionskörpers.
-
✕Sich innerhalb von Funktionen auf print verlassen statt auf return und dann das Ergebnis nicht weiterverwenden können.
✓Berechnen Sie das Ergebnis in der Funktion und geben Sie es mit return zurück; print verwenden Sie an der Aufrufstelle. Funktionen, die Werte zurückgeben, sind wiederverwendbar und testbar; Funktionen, die nur ausgeben, sind Sackgassen.
? Häufig gestellte Fragen
Wie lang sollte eine Funktion sein? +
Kurz genug, um sie ehrlich benennen zu können. Viele Profis streben eine Bildschirmseite oder weniger an, aber der eigentliche Test ist, ob der Name alles beschreibt, was der Körper tut. Sobald eine Funktion ein „und“ im Namen braucht, teilen Sie sie auf.
Was ist der Unterschied zwischen Parametern und Argumenten? +
Parameter sind die Namen in der def-Zeile; Argumente sind die tatsächlichen Werte, die beim Aufruf übergeben werden. Die Unterscheidung ist wichtig, wenn Sie Fehlermeldungen lesen, die beide Begriffe präzise verwenden.
Wann sollte ich lambda anstelle von def verwenden? +
Nur wenn Sie eine Funktion mit einem einzigen Ausdruck als Argument übergeben, typischerweise als Sortierschlüssel oder Filter. Alles, was Sie mehr als einmal aufrufen würden oder was eine zweite Zeile benötigt, verdient ein def und einen Namen.
Können Funktionen sich selbst aufrufen? +
Ja, das ist Rekursion, und Python unterstützt sie mit einer standardmäßigen Tiefenbegrenzung von etwa tausend Aufrufen. Sie ist elegant für baumartige Probleme, und Sie werden ihr ganz natürlich begegnen, wenn wir in Teil 8 Ordnerstrukturen durchlaufen.
8. Zusammenfassung und Ausblick
Sie können jetzt Funktionen definieren, Argumente nach Position und Schlüsselwort übergeben, sichere Standardwerte setzen, einen oder mehrere Werte zurückgeben, den lokalen Gültigkeitsbereich verstehen, variable Argumente annehmen, mit Docstrings dokumentieren und Lambdas dort einsetzen, wo sie hingehören. Von diesem Punkt an wird jedes Beispiel in Funktionen organisiert sein, denn so wird echtes Python geschrieben, und Ihre Skripte sind offiziell zu Programmen geworden.
Als Nächstes kommt die Lektion, von der viele Lernende sagen, dass dabei der Groschen fällt: Teil 5, Python-Datenstrukturen, behandelt Listen, Tupel, Sets, Dictionaries und die Comprehensions, die Python berühmt gemacht haben. Die Lektion und das Quiz zu Funktionen in der App „Learn Python“ unten geben Ihnen zusätzliche Übungsmöglichkeiten zum heutigen Stoff, und das gesamte Curriculum finden Sie auf der Serienübersicht.
Profitipp
Rufen Sie nach dem Schreiben einer Funktion diese sofort zweimal mit unterschiedlichen Argumenten auf, darunter einen Grenzfall wie null oder einen leeren String. Dreißig Sekunden Herumstochern finden die Fehler, die eine Stunde erneutes Lesen übersieht, und genau diese Denkweise wird in Teil 13 zu automatisiertem Testen.
Üben für unterwegs
Learn Python, die kostenlose Android-App
Jedes Thema dieser Serie gibt es auch in der App: mundgerechte Lektionen, ausführbare Beispiele, Quizze, Miniprojekte und einen Offline-Python-Spielplatz, der auf Ihrem Handy läuft.
Kommentare
0Noch keine Kommentare. Teile als Erste oder Erster deine Gedanken.