Gibt es eine Möglichkeit, Rekursion und yield
Anweisung zu mischen ? Zum Beispiel wäre ein Generator für unendliche Zahlen (unter Verwendung von Rekursion) ungefähr so:
def infinity(start):
yield start
# recursion here ...
>>> it = infinity(1)
>>> next(it)
1
>>> next(it)
2
Ich habe es versucht:
def infinity(start):
yield start
infinity(start + 1)
und
def infinity(start):
yield start
yield infinity(start + 1)
Aber keiner von ihnen hat getan, was ich will, der erste hat angehalten, nachdem er nachgegeben hat, start
und der zweite hat nachgegeben start
, dann der Generator und dann angehalten.
HINWEIS: Bitte, ich weiß, dass Sie dies mit einer while-Schleife tun können:
def infinity(start):
while True:
yield start
start += 1
Ich möchte nur wissen, ob dies rekursiv möglich ist.
python
python-2.7
recursion
yield
juliomalegria
quelle
quelle
itertools.count
Ihre eigene Lösung zu verwenden, anstatt sie zu rollen, schleifenbasiert oder anderweitig.Antworten:
Ja, das können Sie tun:
def infinity(start): yield start for x in infinity(start + 1): yield x
Dies tritt jedoch auf, sobald die maximale Rekursionstiefe erreicht ist.
Ab Python 3.3 können Sie verwenden
def infinity(start): yield start yield from infinity(start + 1)
Wenn Sie Ihre Generatorfunktion nur rekursiv aufrufen
yield from
, ohne sie zu durchlaufen oder zu durchlaufen, müssen Sie lediglich einen neuen Generator erstellen, ohne den Funktionskörper tatsächlich auszuführen oder etwas zu liefern.Siehe PEP 380 für weitere Details.
quelle
yield from
es immer noch ein Rekursionslimit gibt :(In einigen Fällen ist es möglicherweise vorzuziehen, einen Stapel anstelle einer Rekursion für Generatoren zu verwenden. Es sollte möglich sein, eine rekursive Methode mit einem Stapel und einer while-Schleife neu zu schreiben.
Hier ist ein Beispiel für eine rekursive Methode, die einen Rückruf verwendet und mithilfe der Stapellogik neu geschrieben werden kann:
def traverse_tree(callback): # Get the root node from somewhere. root = get_root_node() def recurse(node): callback(node) for child in node.get('children', []): recurse(child) recurse(root)
Die obige Methode durchläuft einen Knotenbaum, in dem jeder Knoten ein
children
Array hat, das untergeordnete Knoten enthalten kann. Wenn jeder Knoten angetroffen wird, wird der Rückruf ausgegeben und der aktuelle Knoten an ihn übergeben.Die Methode könnte auf diese Weise verwendet werden, indem einige Eigenschaften auf jedem Knoten ausgedruckt werden.
def callback(node): print(node['id']) traverse_tree(callback)
Verwenden Sie stattdessen einen Stapel und schreiben Sie die Traversal-Methode als Generator
# A stack-based alternative to the traverse_tree method above. def iternodes(): stack = [get_root_node()] while stack: node = stack.pop() yield node for child in reversed(node.get('children', [])): stack.append(child)
(Beachten Sie, dass Sie die Reihenfolge der untergeordneten Elemente umkehren müssen, wenn Sie dieselbe Durchlaufreihenfolge wie ursprünglich wünschen, da das erste an den Stapel angehängte untergeordnete Element das letzte ist, das angezeigt wird.)
Jetzt können Sie das gleiche Verhalten wie
traverse_tree
oben erzielen, jedoch mit einem Generator:for node in iternodes(): print(node['id'])
Dies ist keine Einheitslösung, aber für einige Generatoren erhalten Sie möglicherweise ein gutes Ergebnis, wenn Sie die Rekursion durch die Stapelverarbeitung ersetzen.
quelle
def lprint(a): if isinstance(a, list): for i in a: yield from lprint(i) else: yield a b = [[1, [2, 3], 4], [5, 6, [7, 8, [9]]]] for i in lprint(b): print(i)
quelle
b
? Versuchen Sie, keine Nur-Code-Antworten zu hinterlassen ... Eine kleine Klarstellung und Erklärung hilft, die Dinge in einen Kontext zu bringen und Ihre Antwort besser zu verstehenedit
Tag unter Ihrer Antwort klicken oder hier klicken . Versuchen Sie auch, wie gesagt, eine kleine Erklärung hinzuzufügen, wie und warum dies das Problem löstIm Grunde müssen Sie nur eine for-Schleife hinzufügen, an der Sie Ihre Funktion rekursiv aufrufen müssen . Dies gilt für Python 2.7.
quelle