torres recursivos recursividad recursiva programacion problemas pilas informatica hanoi funcion fractal ejemplos arbol algoritmo python python-2.7 recursion yield

recursivos - recursividad python ejemplos



RecursiĆ³n usando rendimiento (3)

¿Hay alguna manera de mezclar la recursividad y la declaración de yield ? Por ejemplo, un generador de números infinitos (usando recursividad) sería algo así como:

def infinity(start): yield start # recursion here ... >>> it = infinity(1) >>> next(it) 1 >>> next(it) 2

Lo intenté:

def infinity(start): yield start infinity(start + 1)

y

def infinity(start): yield start yield infinity(start + 1)

Pero ninguno de ellos hizo lo que yo quería, el primero se detuvo después de que cedió el start y el segundo dio start , luego el generador y luego se detuvo.

NOTA: Por favor, sé que puedes hacer esto usando un ciclo while:

def infinity(start): while True: yield start start += 1

Solo quiero saber si esto puede hacerse recursivamente.


En algunos casos, puede ser preferible utilizar una pila en lugar de recurrencia para generadores. Debería ser posible reescribir un método recursivo utilizando una pila y un ciclo while.

Aquí hay un ejemplo de un método recursivo que usa una devolución de llamada y se puede reescribir utilizando la lógica de la pila:

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)

El método anterior atraviesa un árbol de nodos donde cada nodo tiene una matriz de elementos secundarios que puede contener nodos secundarios. A medida que se encuentra cada nodo, se emite la devolución de llamada y se le pasa el nodo actual.

El método podría usarse de esta manera, imprimiendo alguna propiedad en cada nodo.

def callback(node): print(node[''id'']) traverse_tree(callback)

Use una pila en su lugar y escriba el método transversal como generador

# 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)

(Tenga en cuenta que si desea el mismo orden transversal que originalmente, debe invertir el orden de los niños porque el primer niño agregado a la pila será el último que se haya reventado).

Ahora puedes obtener el mismo comportamiento que el de traverse_tree anterior, pero con un generador:

for node in iternodes(): print(node[''id''])

Esta no es una solución única para todos, pero para algunos generadores puede obtener un buen resultado sustituyendo el procesamiento de pila por recursividad.


Entonces, básicamente, solo necesita agregar un bucle for en donde necesita llamar a su función recursivamente . Esto aplica para Python 2.7.


Sí, usted puede hacer esto:

def infinity(start): yield start for x in infinity(start + 1): yield x

Sin embargo, esto producirá un error una vez que se alcance la profundidad máxima de recursión.

A partir de Python 3.3, podrás usar

def infinity(start): yield start yield from infinity(start + 1)

Si solo llama a su función de generador de forma recursiva sin pasar por encima de ella o yield from , todo lo que hace es construir un generador nuevo, sin ejecutar realmente el cuerpo de la función ni ceder nada.

Ver PEP 380 para más detalles.