Lässt es sich mit cremefarbenem Papier, einer Tönung, mehr Kontrast oder größerer Schrift besser lesen? Wählen Sie Ihre Farben und Ihre Schrift, einmalig für alle Seiten.

Kostenlose Lektion

Rekursion verstehen: Basisfall und Aufrufstapel

Nach dieser Lektion: Ich kann eine rekursive Funktion mit Basisfall schreiben und ihre Aufrufe nachvollziehen.

Lektion, 60 Min.3 BefehleLab „Linux im Alltag“: die dreißig Befehle, die Entwickelnde auswendig tippen

Wie sich eine Funktion selbst aufruft

Rekursion bedeutet, dass eine Funktion ein Problem löst, indem sie sich mit einem kleineren Problem selbst aufruft. Sie brauchen dafür nur zwei Dinge: einen Fall, der sich direkt lösen lässt, und einen Schritt, der das Problem kleiner macht.

Die Größe eines Ordners auf der Festplatte ist die Summe seiner Dateien plus die Größe jedes Unterordners. Für den Unterordner gilt derselbe Satz.

Am Ende dieser Lektion

Notiz

Ich kann eine rekursive Funktion mit Basisfall schreiben und ihre Aufrufe nachvollziehen.

Schlüsselwörter

BegriffWas er bedeutetBeispiel
Rekursioneine Funktion ruft sich selbst auf
Basisfallder Fall, den die Funktion ohne Selbstaufruf löstn <= 1
Rekursiver Fallder Fall, der ein kleineres Problem selbst aufruft
Aufrufstapeldie Liste der Aufrufe, die noch auf ein Ergebnis warten
Rekursionstiefewie viele Aufrufe gleichzeitig offen sind

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Ohne Basisfall hört die Rekursion nie auf

Die Fakultät von 4 ist 4 mal 3 mal 2 mal 1. Das ist 4 mal die Fakultät von 3. So erhalten Sie die Regel: n Fakultät ist n mal (n minus 1) Fakultät.

Der Basisfall ist die Fakultät von 1, und sie ist 1. Der rekursive Fall ruft die Funktion mit n minus 1 auf. Jeder Aufruf macht die Zahl kleiner, bis der Basisfall kommt.

Die Fakultät mit Ausgabe jedes Aufrufs

Code: python
# Die Fakultaet: 4! = 4 * 3 * 2 * 1.
def fakultaet(n):
    print("Aufruf mit n =", n)
    if n <= 1:
        return 1  # Basisfall: hier hoert die Rekursion auf
    ergebnis = n * fakultaet(n - 1)  # rekursiver Fall: ein kleineres Problem
    print("Rueckgabe", ergebnis, "fuer n =", n)
    return ergebnis

print(fakultaet(4))
# Aendern Sie 4 auf 6. Wie viele Aufrufe sehen Sie?

Der Aufrufstapel merkt sich die offenen Aufrufe

Ruft eine Funktion sich selbst auf, muss der erste Aufruf warten. Python merkt sich das auf dem Aufrufstapel: Oben liegt der neueste Aufruf, und nur der oberste arbeitet.

Hat der Basisfall ein Ergebnis, wird der Stapel von oben nach unten abgebaut. Jeder Aufruf rechnet mit dem Ergebnis des Aufrufs über ihm weiter.

Der Stapel bei fakultaet(3)

SchrittWas geschiehtStapel (oben zuerst)
1fakultaet(3) startetfakultaet(3)
2fakultaet(3) ruft fakultaet(2) auffakultaet(2), fakultaet(3)
3fakultaet(2) ruft fakultaet(1) auffakultaet(1), fakultaet(2), fakultaet(3)
4fakultaet(1) gibt 1 zurückfakultaet(2), fakultaet(3)
5fakultaet(2) gibt 2 mal 1 = 2 zurückfakultaet(3)
6fakultaet(3) gibt 3 mal 2 = 6 zurückleer

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Im Lab: die Grenze der Rekursionstiefe

Der Stapel ist nicht unendlich groß. Python erlaubt nur eine feste Zahl offener Aufrufe und meldet danach einen Fehler. Der erste Befehl zeigt diese Grenze.

Der zweite und dritte rechnen mit der Fakultät aus der Standardbibliothek. Sie sehen, dass 6 Fakultät genau 6 mal 5 Fakultät ist.

Die Grenze der offenen Aufrufe

Befehl
python3 -c "import sys; print(sys.getrecursionlimit())"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Zehn Fakultät

Befehl
python3 -c "import math; print(math.factorial(10))"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Fünf Fakultät und der Faktor zur sechsten

Befehl
python3 -c "import math; print(math.factorial(5), math.factorial(6) // math.factorial(5))"

Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.

Zwei Aufrufe pro Ebene wachsen sehr schnell

Eine Fibonacci-Zahl ist die Summe der beiden davor: 0, 1, 1, 2, 3, 5, 8. Die Funktion fib ruft sich deshalb zweimal auf, mit n minus 1 und mit n minus 2.

Der Basisfall sind die Zahlen unter 2. Ein Aufruf erzeugt zwei neue, jeder von ihnen wieder zwei. Die Zahl der Aufrufe wächst darum rasant.

Die Aufrufe von fib zählen

Code: python
# Die Fibonacci-Zahlen: jede ist die Summe der beiden davor.
aufrufe = [0]

def fib(n):
    aufrufe[0] = aufrufe[0] + 1
    if n < 2:
        return n
    return fib(n - 1) + fib(n - 2)

for n in [5, 10, 20]:
    aufrufe[0] = 0
    print("fib(", n, ") =", fib(n), "Aufrufe:", aufrufe[0])
# Probieren Sie 25. Warten Sie auf die Ausgabe und lesen Sie die Zahl der Aufrufe.

Wie viele Aufrufe macht fib(n)?

nfib(n)Zahl der Aufrufe
5515
1055177
20676521.891
30832.0402.692.537

Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.

Ein häufiger Fehler

Warnung

Viele denken, der Basisfall sei nur eine Zusatzprüfung. Er ist der Grund, warum die Rekursion endet. Ohne ihn ruft sich die Funktion immer weiter auf, bis Python bei der Grenze der Tiefe mit einem Fehler abbricht. Der rekursive Aufruf muss außerdem zum Basisfall hinführen.

Weiterführend

Schreiben Sie potenz(basis, exponent) rekursiv. Der Basisfall ist der Exponent 0 mit dem Ergebnis 1. Sonst gilt: basis mal potenz(basis, exponent - 1).

Wie viele Aufrufe macht potenz(2, 10)? Vergleichen Sie mit python3 -c "print(2 ** 10)" im Lab.

Über dieses Lab und seinen Quellcode: Lab „Linux im Alltag“: die dreißig Befehle, die Entwickelnde auswendig tippen

Sie unterrichten eine Gruppe? Weisen Sie dieses Modul Ihren Studierenden zu, mit Handbuch für Lehrende, automatisch geprüften Aufgaben und einem Lab für jede Person.