@Kahnbein.Kai: Hättest Du die Frage „Warum kann ich mit einer Funktion multiplizieren“ auch bei ``x = sin(0.5) * 3``? Es wird ja nicht die *Funktion* mit einer Zahl multipliziert, sondern die Funktion wird aufgerufen und das *Ergebnis* wird mit einer Zahl multipliziert. Und genau das gleiche passiert auch mit dem `z()` — da wird eine Funktion, hier halt wieder die Funktion in der das als Teilausdruck steht → Rekursion, aufgerufen, aber ansonsten ist das nicht anderes als das Beispiel mit dem `sin()`-Aufruf.
Da das eine reine Funktion ist, also Eingabewerte hat, einen Rückgabewert, und keine Seiteneffekte, kann man das einfach durch ersetzen visualisieren:
Nehmen wir mal den konkreten Fall ``z(5, 2)``:
Code: Alles auswählen
z(5, 2)
# Die Werte eingesetzt:
5 if 2 == 0 else z(5, 2-1) ** 2 + 5
# Da 2≠0 ist, bleibt der ``else``-Teil:
z(5, 1) ** 2 + 5
# Für `z` wieder die Werte eingesetzt:
(5 if 1 == 0 else z(5, 1-1) ** 2 + 5) ** 2 + 5
# Da 1≠0 ist, bleibt auch hier wieder der ``else``-Teil:
(z(5, 0) ** 1 + 5) ** 2 + 5
# Für `z` wieder die Werte eingesetzt:
((5 if 0 == 0 else z(5, 0-1) ** 2 + 5) ** 2 + 5) ** 2 + 5
# Dieses mal wird der ``if``-Teil genommen:
((5) ** 2 + 5) ** 2 + 5
# Und das kann man jetzt einfach ausrechnen:
905
Würde man real tatsächlich mit einer Schleife lösen, weil das mit Rekursion zu machen in Programmiersprachen, die keine Optimierung für endrekursive Aufrufe garantieren, („tail call optimisation“) ein Stackoverflow ist, der nur darauf wartet das Programm abstürzen zu lassen. Beziehungsweise in Python der `RecursionError`, den Du bereits kennengelernt hast.
In der Mathematik gibt man so etwas gerne rekursiv an, weil man dann nicht so etwas wie „Schleifen“ erfinden muss, sondern eine normale, halt rekursiv definierte, Formel angeben kann. Und es gibt funktionale Programmiersprachen, beispielsweise Haskell, die keine prozeduralen Schleifenkonstrukte haben, wo man so etwas dann auch rekursiv angeben kann.