recursionlimit verwenden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
nuhakan
User
Beiträge: 51
Registriert: Donnerstag 11. August 2016, 11:42

Hallo,

ich wollte recursionlimit verwenden. Ich weiß nicht, ob es Sinn macht oder ob überhaupt recursionlimit hier korrekt ist. Der Code soll 3 Tippfehler akzeptieren und dann zu else springen und etwas tun.

Code: Alles auswählen

def start():

#    sys.setrecursionlitmi(3)
    choice =  input("> ")

    if choice == "1":
        print("1")
    elif choice == "2":
        print("2")
    elif choice == "3":
        print("3")
    else:
        print("1  2 3")
        # Tut etwas

start()
Danke!!
Benutzeravatar
noisefloor
User
Beiträge: 4183
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

nee, das macht keinen Sinn - zumal du keine Rekursion verwendest im gezeigten Code.

Deine Problemstellung löst man über `while` und einen Zähler, der feststellt, wie oft die Schleife durchlaufen wurde.

Das Rekursionslimit auf einen so niedrigen Wert wie 3 zu setzen ist auch fragwürdig, weil wenn du irgendwo in der Instanz des laufenden Python-Interpreters ein Modul hast, was Rekursion benutzt, bist du direkt an der MaxRecursionDepth und das Prog / Modul beendet sich. Weil drei Rekursonsschritte quasi nichts ist.

Python besitzt - im Gegensatz zu anderen Sprachen - auch null Optimierung für Rekursion, weswegen Rekursion bei Python fast nie verwendet wird. Iteration ist der bessere Weg, da ist Python auch viel stärker.

Gruß, noisefloor
Benutzeravatar
__blackjack__
User
Beiträge: 14013
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@nuhakan: Das macht keinen Sinn. Du möchtest eine ``for``-Schleife mit einem ``break`` und einem ``else``-Zweig.

@noisefloor: Deine Beschreibung klingt so als würde das Rekursionslimit tatsächlich nur bei rekursiven Aufrufen greifen: Das sind die maximal verschachtelbaren Aufrufe, egal ob nun rekursiv oder nicht. Da ist 3 also wirklich unbenutzbar und nicht nur fragwürdig. :-)
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Sirius3
User
Beiträge: 18255
Registriert: Sonntag 21. Oktober 2012, 17:20

Python ist sogar so schlau, das gar nicht zuzulassen:

Code: Alles auswählen

>>> import sys
>>> def start():
...   sys.setrecursionlimit(3)
... 
>>> start()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in start
RecursionError: cannot set the recursion limit to 3 at the recursion depth 2: the limit is too low
@nuhakan: Da Du gar nicht weißt, wie tief verschachtelt Deine Funktion aufgerufen wird, kannst Du gar kein passendes Rekursionslimit setzen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

nuhakan hat geschrieben: Donnerstag 1. November 2018, 11:42 ich wollte recursionlimit verwenden. Ich weiß nicht, ob es Sinn macht oder ob überhaupt recursionlimit hier korrekt ist. Der Code soll 3 Tippfehler akzeptieren und dann zu else springen und etwas tun.
Das ist alleine schon deshalb nicht richtig, weil du eine globale Einstellung des Interpreters lokal zur Flusskontrolle ausnutzt. Selbst wenn dein Code funktionieren wuerde, handelst du dir damit massiv Probleme ein. Starte mal einen Thread im Hintegrund, der dann ploetzlich stirbt, weil er das Limit ueberschreitet. Oder das einfuegen eines Bibliotheksaufrufs, dessen tiefe du gar nicht kennst, oder die sich in einer anderen Pythonversion anders gestaltet, und die Nummer kracht.
Benutzeravatar
__blackjack__
User
Beiträge: 14013
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Sirius3: Naja, man könnte das ja mit ``len(inspect.stack())`` ermitteln und drei drauf addieren. Das Problem ist eher in der anderen Richtung, nicht das man nicht weiss auf welcher Ebene man bereits steht, sondern wie viele Ebenen benutzte Funktionen wie `input()` und `print()` da vielleicht noch tiefer gehen wollen/müssen.

@__deets__: Threads müssten da doch eigentlich ihre eigenen Stacks haben‽
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@__blackjack__: aber setrecursionlimit ist global.

Code: Alles auswählen

Traceback (most recent call last):
  File "/tmp/test.py", line 15, in <module>
    t = threading.Thread(target=test)
  File "/usr/lib/python3.6/threading.py", line 793, in __init__
    self._started = Event()
  File "/usr/lib/python3.6/threading.py", line 499, in __init__
    self._cond = Condition(Lock())
RecursionError: maximum recursion depth exceeded while calling a Python object
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 53, in apport_excepthook
    if not enabled():
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 28, in enabled
    return re.search(r'^\s*enabled\s*=\s*0\s*$', conf, re.M) is None
  File "/usr/lib/python3.6/re.py", line 182, in search
    return _compile(pattern, flags).search(string)
  File "/usr/lib/python3.6/re.py", line 301, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/usr/lib/python3.6/sre_compile.py", line 562, in compile
    p = sre_parse.parse(p, flags)
  File "/usr/lib/python3.6/sre_parse.py", line 847, in parse
    source = Tokenizer(str)
RecursionError: maximum recursion depth exceeded

Original exception was:
Traceback (most recent call last):
  File "/tmp/test.py", line 15, in <module>
    t = threading.Thread(target=test)
  File "/usr/lib/python3.6/threading.py", line 793, in __init__
    self._started = Event()
  File "/usr/lib/python3.6/threading.py", line 499, in __init__
    self._cond = Condition(Lock())
RecursionError: maximum recursion depth exceeded while calling a Python object
Produziert von

Code: Alles auswählen

import sys
import threading
import time
sys.setrecursionlimit(100)

def recursive(count):
    if count:
        recursive(count-1)


def test():
    time.sleep(3)
    recursive(200)

t = threading.Thread(target=test)
t.daemon = True
t.start()

while True:
    recursive(8)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nachtrag: ich musste das Rekursionslimit hochsetzen, weil man mit nur 10 noch nicht mal den Thread hochgezogen bekommt (mein anderer Punkt). Aber bei 100 schlaegt der Thread fehl. Das hat ja nix mit dessen Stack, sondern nur der globalen Einstellung fuer desset tiefe zu tun.
nuhakan
User
Beiträge: 51
Registriert: Donnerstag 11. August 2016, 11:42

Vielen Dank für die Antworten. Ich weiß, besser mit 'for' oder 'while'. Es war nur ein Gedanke zum Üben. Und jetzt lese ich euch, um 'recursionlimit' besser zu verstehen. :P

Grüße.
Antworten