Python-Rekursion RuntimeError

8
%Vor%

Wir alle wissen, dass das Aufrufen dieser Funktion in Python RuntimeError: maximum recursion depth exceeded

ergibt

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?

    
Piotr Dabkowski 09.04.2014, 19:39
quelle

2 Antworten

4

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

übernommen wird

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

    
mhlester 09.04.2014, 19:45
quelle
4

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:

%Vor%     
Martijn Pieters 09.04.2014 19:45
quelle

Tags und Links