Guten Morgen liebe Community,
folgendes Problem: Ich habe eine Funktion, die sich je nach den übergebenen/bearbeiteten Parametern möglicherweise rekursiv aufruft.
Aber ich möchte, dass, unabhängig vom Zustand der Parameter, dieses rekursive Aufrufen nicht öfter als fünfmal passiert. Daher, sollte die Rekursionstiefe fünf erreichen/überschreiten, soll die Funktion einfach False zurückgeben - oder so.
Bisher mache ich das einfach mit einem Funktionsattribut, das halt mitzählt. Dafür muss ich aber zuerst testen ob dieses Attribut existiert etc... Da wird der Code schnell mal für meine Begriffe chaotisch.
Gibt es da eine einfachere Lösung? Also einfach den Test "Rekursionstiefe > 5" - oder so?
Danke für die Hilfe!
Liebe Grüße, Christoph
Aktuelle Rekursionstiefe feststellen
Gemeint ist vielleicht etwas in der Richtung:__deets__ hat geschrieben:Ich Verstehe den Begriff Funktionsattribut nicht.
Code: Alles auswählen
In [1]: def test():
...: calls = getattr(test, "calls", 0)
...: print('Calls:', calls)
...: if calls < 5:
...: setattr(test, "calls", calls + 1)
...: test()
...: else:
...: print('Exceeded.')
...: return
In [2]: test()
Calls: 0
Calls: 1
Calls: 2
Calls: 3
Calls: 4
Calls: 5
Exceeded.
In [3]: test()
Calls: 5
Exceeded.
@snafu: Das habe ich bisher nicht anders verstanden. Nach meinem bisherigen Verständnis bedeutet Rekursionstiefe, wie oft "def test()" sich rekursiv in der Zeile 6 mit "test()" selbst aufruft. Beruht diese Annahme auf ein Missverständnis?
Wie verstehst du denn Rekursionstiefe? Mein Beispiel zählt die Anzahl der inneinander verschachtelten Aufrufe. Ist das nicht die Rekursionstiefe?snafu hat geschrieben:Wobei ich unter Rekursionstiefe nicht die Anzahl der Funktionsaufrufe verstehe. Da bringst du wohl was durcheinander.
Lasse ich mein Beispiel leicht abgewandelt als eigenständiges Skript laufen, komme ich jedenfalls an das Rekursionslimit (abzüglich des Frames, das inital schon auf dem Stack liegt).
Code: Alles auswählen
#!/usr/bin/env python3
import sys
import inspect
def test():
calls = getattr(test, "calls", 0)
setattr(test, "calls", calls + 1)
try:
test()
except RecursionError:
print('calls ', calls)
print('Stack', len(inspect.stack()))
return
if __name__ == '__main__':
print('Stack', len(inspect.stack()))
print('Recursion Depth:', sys.getrecursionlimit())
test()
Code: Alles auswählen
% ./recursion_test.py
Stack 1
Recursion Depth: 1000
calls 998
Stack 1000
Zuletzt geändert von nezzcarth am Sonntag 24. September 2017, 14:00, insgesamt 2-mal geändert.
Na kommt drauf an. Für baumartige rekursionen ist dein erster Ansatz zu simpel. Prinzipiell würde ich sowas auch per Dekoration umsetzten. Dann kannst du auch wieder ‚poppen‘ wenn du austrittst.
Und der zweite impliziert das du immer nur die Funktion selbst aufrufst. Das ist oft, aber nicht immer so.
So oder so würde ich das nicht so machen. Ist globaler Zustand. Aber für eine bessere Beurteilung fehlen Informationen.
Und der zweite impliziert das du immer nur die Funktion selbst aufrufst. Das ist oft, aber nicht immer so.
So oder so würde ich das nicht so machen. Ist globaler Zustand. Aber für eine bessere Beurteilung fehlen Informationen.
Schlepp die Rekursionstiefe doch einfach als Parameter mit:
Hilft bei baumartigen Strukturen sicherlich nicht. Ich halte es allerdings auch für fraglich, ob bei solchen Strukturen die "Rekursionstiefe" alleine eine sinnvolle Abbruchbedingung darstellt.
Code: Alles auswählen
def recursive_function(arg='LA ', max_depth=5, current_depth=1):
if current_depth >= max_depth:
return arg
return arg + recursive_function(arg, max_depth, current_depth+1)
@nezzcarth: Du verwendest bei Deinem Beispiel eine globale Variable und kannst insgesamt `test` nur 5 mal aufrufen, wie Du in Deinem Beispiel schön zeigst, das versteht man normalerweise nicht unter Rekursion. kbr's Methode ist der empfohlene Weg.
Rekursionstiefe meint über wieviele Ebenen "nach unten" die Funktionsaufrufe gehen. Dabei kann es sich aber durchaus um mehr als nur eine Funktion handeln. Zudem ist es nicht sinnvoll, die Funktion selbst einfach mit der Anzahl ihrer Aufrufe zu bestücken. Was passiert wohl, wenn sich die Funktion z.B. nur dreimal aufgerufen hat und später nochmals verwendet werden soll...?
Aah! Das schaut doch schon weitaus aufgeräumter auskbr hat geschrieben:Schlepp die Rekursionstiefe doch einfach als Parameter mit:
Hilft bei baumartigen Strukturen sicherlich nicht. Ich halte es allerdings auch für fraglich, ob bei solchen Strukturen die "Rekursionstiefe" alleine eine sinnvolle Abbruchbedingung darstellt.Code: Alles auswählen
def recursive_function(arg='LA ', max_depth=5, current_depth=1): if current_depth >= max_depth: return arg return arg + recursive_function(arg, max_depth, current_depth+1)
Ich glaub, damit kann ich mich anfreunden...
Meine Methode war ein Attribut im Sinne von test.current_depth. Das geht zwar, aber dann muss man es irgendwann mal wieder zurücksetzen und/oder so - und da wirds dann chaotisch...
Nur zur Klarstellung - die Rekursionstiefe ist nur ein Abbruchkriterium, das ich im besten Fall garnicht brauche...