Ich probier das mal "grafisch" darzustellen:
Wenn Du eine Rekursion hast, wird jede "Instanz" der aufgerufenen Funktion separat im Speicher gehalten. (Für Sprach-Puristen gilt die Formulierung vermutlich nicht)
D.h. wenn die Abbruchbedingung (wert < 2) erreicht ist, wird die zuletzt aufgerufene Funktion beendet. Das Verlassen der Funktion geht aber dorthin, von wo Du sie aufgerufen hast, und das ist die Funktion mit dem Wert, der doppelt so groß war.
Als Beispiele fange ich mit dem Wert 8 an. Dieses Beispiel soll die Verschachtelungen der Funktionen verdeutlichen und wurden der Übersicht halber mit eigenen Namen versehen:
Code: Alles auswählen
rechne_8:
print 8 # in Fkt. "rechne_8"
rechne_4:
print 4 # in Fkt. "rechne_4"
rechne_2:
print 2 # in Fkt. "rechne_2"
rechne_1:
return # von rechne_1 nach rechne_2
print 2 # und schliesse Fkt "rechne_2", gehe nach "rechne_4"
(soweit alles klar. Jetzt springt der Programmfluss dorthin zurück, von wo rechne_2 aufgerufen wurde, und das ist rechne_4, und dort steht als nächste Anweisung, dass der aktuelle Wert ausgegeben werden soll, und der ist 4.
Also geht es folgendermassen weiter:
Code: Alles auswählen
print 4 # und schliesse Fkt "rechne_4", gehe nach "rechne_8"
print 8 # in Fkt. "rechne_2 und schliesse Fkt "rechne_2"
Ich hoffe ich konnte das gut verständlich darstellen. Meiner Meinung nach, ist es wichtig, sich bei Rekursionen zu verdeutlichen, dass "jede" Funktion für sich allein im Speicher steht und natrülich auf die lokalen Variablen mit ihr. Deshalb sind Rekursionen aus ziemlich speicherfressend, aber für ähnliche Strukturen einfach genial. (Bäume etc.)
Wenn Du gar zuviel Zeit hast, empfehle ich Dir dazu das Buch "Gödel, Escher, Bach" von Douglas Hofstatter. Er hat es leider grad ein paar Jahre vor der "Entdeckung" der Mandelmenge geschrieben, aber obwohl es jettz schon 25 Jahre alt ist, ist es nach wie vor ein Hammer...