Wir alle wissen, dass das Aufrufen dieser Funktion in Python RuntimeError: maximum recursion depth exceeded
Ich habe seine leicht modifizierte Version geschrieben:
%Vor% Die zweite Funktion läuft für immer, ohne RuntimeError
zu werfen. Außerdem konnte ich es nicht mit der Kombination Strg C stoppen.
Ich verstehe nicht, warum Aufruf von f2 () RuntimeError
nicht wirft. Kannst du es bitte erklären?
Wenn der Stapel voll ist, ruft er f2
in try
auf, bis die maximale Rekursionstiefe erreicht ist.
Sobald es erreicht ist, wird ein RuntimeError
ausgelöst, was von finally
Das wiederum erhöht das gleiche RuntimeError
, aber jetzt zu dem früheren Stapel, der an den finally
-Aufruf weitergeleitet wird.
In diesem Bereich wird die maximale Tiefe erneut überschritten.
Wenn ein KeyboardInterrupt
ausgelöst wird, geht das Programm trotzdem zum finally
und wird nicht beendet.
Es wird technisch nicht für immer laufen, weil es nur ein finally
gibt. Das heißt, (dank der Kommentare), es erlaubt exponentiell mehr Anrufe, die ziemlich nah an der Unendlichkeit ist. Eine Rekursionstiefe von 100 würde sich in 2 100 == 1267650600228229401496703205376 verwandeln.
Wenn es pro Aufruf 1 ms dauert, würde 465 Milliarden Jahre dauern. Und das ist nur eine Tiefe von 100
Die Ausnahme wird immer noch geworfen, aber bevor Python es zeigen kann rufen Sie f2()
wieder auf.
Jedes Mal, wenn die Ausnahme ausgelöst wird, schleichen Sie sich in einen anderen Anruf ein. Dieser rekursive Aufruf ist zulässig (weil wir einen Schritt unterhalb des Limits sind), wir überschreiten das Limit, die Ausnahme wird erneut ausgelöst, der finally
-Handler schleicht sich in einem weiteren Aufruf fast ad infinitum.
CTRL-C
beendet das Programm nicht aus den gleichen Gründen; eine Ausnahme wird ausgelöst ( KeyboardInterrupt
), aber der finally:
-Handler sendet Sie erneut in die Rekursion zurück.
Sie fallen jetzt mit einer solchen Geschwindigkeit, dass Sie den Orbit um den Interpreter betreten haben.
Alles endet , aber die finally
-Handler fügen eine exponentiell wachsende Anzahl zusätzlicher Aufrufe hinzu, bevor der Stapel vollständig abwickeln kann: