2011-08-20 25 views
5

Quiero generar todas las rutas desde cada hoja hasta la raíz en un árbol. Me gustaría hacer eso con generadores, para ahorrar memoria (el árbol puede ser grande). Aquí está mi código:Python (rendimiento): todas las rutas desde las hojas hasta la raíz en un árbol

def paths(self, acc=[]): 
    if self.is_leaf(): 
     yield [self.node]+acc 

    for child in self.children: 
     child.paths([self.node]+acc) 

Pero no funciona. ¿Por qué? Invocado en la raíz, atraviesa el árbol de arriba a abajo, recogiendo nodos en "acc". "acc" debe devolverse en cada hoja ...

is_leaf() es verdadero si self.children está vacío.

Respuesta

7

Este código sólo produce hojas que son (inmediatos) hijos de la raíz. Los otros son visitados, ceden a la función superior, pero la función superior no hace nada con ellos. Lo que necesita es cederlos desde la función inferior a la superior:

def paths(self, acc=[]): 
    if self.is_leaf(): 
     yield [self.node]+acc 

    for child in self.children: 
     for leaf_path in child.paths([self.node]+acc): # these two 
      yield leaf_path       # lines do that 

Esto debería hacer el truco.

+0

Siempre me he preguntado: ¿hay un comando rápido "ceder todo", o es el más corto el bucle 'for' que ha escrito? – Owen

+0

@Own no, pero me parece bien así, son solo dos líneas simples ... –

+5

En Python 3.3 habrá una declaración 'yield from' que automáticamente producirá elementos de otro generador, por lo que cualquier' for' loop con un "rendimiento" en él puede escribir como una expresión del generador se puede hacer en una línea. – agf

1

En este momento, el for no hace yield nada. En su lugar, debe ceder todos los elementos que son generados por la llamada recursiva:

for child in self.children: 
    for path in child.paths([self.node]+acc): 
     yield path 
Cuestiones relacionadas