Ich bin mir nicht sicher, ob ich jemanden wiederhole, aber vor einiger Zeit hat jemand Gutes die Y-Operator für rekursiv aufgerufene Funktionen geschrieben, wie:
def tail_recursive(func):
y_operator = (lambda f: (lambda y: y(y))(lambda x: f(lambda *args: lambda: x(x)(*args))))(func)
def wrap_func_tail(*args):
out = y_operator(*args)
while callable(out): out = out()
return out
return wrap_func_tail
und dann braucht die rekursive Funktion die Form:
def my_recursive_func(g):
def wrapped(some_arg, acc):
if : return acc
return g(some_arg, acc)
return wrapped
# und schließlich rufen Sie es im Code auf
(tail_recursive(my_recursive_func))(some_arg, acc)
für Fibonaccizahlen sieht Ihre Funktion so aus:
def fib(g):
def wrapped(n_1, n_2, n):
if n == 0: return n_1
return g(n_2, n_1 + n_2, n-1)
return wrapped
print((tail_recursive(fib))(0, 1, 1000000))
Ausgabe:
..684684301719893411568996526838242546875
(eigentlich eine Menge Ziffern)
4 Stimmen
Siehe auch stackoverflow.com/questions/5061582/…
21 Stimmen
Memoisierung könnte die Geschwindigkeit Ihrer Funktion steigern und ihre effektive rekursive Tiefe erhöhen, indem zuvor berechnete Werte beendet werden, anstatt die Stapelgröße zu erhöhen.
6 Stimmen
Die Rekursionsobergrenze beträgt in der Regel 1000.
1 Stimmen
@Boris Warum bleibt es dann bei
997
stecken? Liegt es daran, dass der Python-Interpreter die ersten 3 Ebenen des Stapels einnimmt?6 Stimmen
@tonix der Interpreter fügt einen Stapelrahmen hinzu (die
Zeile , in
in Stapelverfolgungen) und dieser Code nimmt 2 Stapelrahmen fürn=1
(weil der Basisfalln < 1
ist, also fürn=1
rekursiert es trotzdem). Und ich nehme an, dass das Rekursionslimit nicht inklusiv ist, wie in "Fehler, wenn Sie 1000 erreichen" und nicht "Fehler, wenn Sie 1000 überschreiten (1001)".997 + 2
ist weniger als 1000, also funktioniert es,998 + 2
nicht, weil es das Limit erreicht.0 Stimmen
@Boris Also sind
997
Stapelrahmen vonrecursive_function
belegt und die letzten2
sind vom Interpreter selbst besetzt (eingebaute Zuweisung)? Habe ich das richtig verstanden?6 Stimmen
@tonix nein.
recursive_function(997)
funktioniert, bricht bei998
ab. Wenn Sierecursive_function(998)
aufrufen, werden 999 Stapelrahmen verwendet und 1 Rahmen wird vom Interpreter hinzugefügt (weil Ihr Code immer so ausgeführt wird, als ob er Teil des obersten Moduls wäre), was dazu führt, dass er das 1000er-Limit erreicht.0 Stimmen
Der Weg, wie diese Funktion geschrieben ist, führt dazu, dass es
n+1
Frames dauert, um das Ergebnis fürn
zu berechnen.0 Stimmen
@tonix, ich habe deine Frage hier gestellt stackoverflow.com/questions/59347491/…
0 Stimmen
@Boris Ich habe noch einmal nachgeschaut und in meinem Fall funktioniert
recursive_function(995, 0)
mitRekursionsgrenze = 1000
, währendrecursive_function(996, 0)
nicht funktioniert... Also denke ich, dass zusätzliche Stapelrahmen verwendet werden (Ich benutze Python 3.6).0 Stimmen
@tonix Ich habe es gerade auf Python 3.6.9 durch die REPL ausprobiert und erhalte immer noch das gleiche Verhalten, 997 funktioniert, 998 nicht. Wie führst du diese Funktion aus? Du musst es auf eine Weise machen, die 2 Stapelrahmen hinzufügt. Führst du es aus einer
main()
-Funktion oder importierst du eine Datei, in der du die Funktion definierst? Wenn du es mit IPython ausführst, wäre es nicht überraschend, wenn das auch ein paar Rahmen hinzufügt.0 Stimmen
Ich verwende direkt die Python-Befehlszeilenschnittstelle. Ich starte
python
und schreibe dann den Code auf der Eingabeaufforderung des Interpreters>>>
und führe ihn aus.0 Stimmen
@tonix verwendest du Python 2 oder 3. Wenn du nur "
python
" eingibst und nicht "python3
", ist es wahrscheinlich 2.0 Stimmen
@Boris Ich kann bestätigen, dass ich Python 3 verwende, weil ich diese Ausgabe sehe, wenn ich im CLI
python
eingebe:Python 3.6.5 (Standard, 30. März 2018, 06:42:10) [GCC 4.2.1 kompatibel Apple LLVM 9.0.0 (clang-900.0.39.2)] auf Darwin Geben Sie "help", "copyright", "credits" oder "license" für weitere Informationen ein. >>>