2011-08-20 7 views
5

Voglio generare tutti i percorsi da ogni foglia a radice in un albero. Mi piacerebbe farlo con i generatori, per risparmiare memoria (l'albero può essere grande). Ecco il mio codice:Python (resa): tutti i percorsi da foglie a radice in un albero

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

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

Ma non funziona. Perché? Invocato alla radice, attraversa l'albero da cima a fondo, raccogliendo nodi in "acc". "acc" deve essere restituito in ogni foglia ...

is_leaf() è true se self.children è vuoto.

risposta

7

Questo codice cede solo foglie che sono (immediati) figli della radice. Gli altri vengono visitati, si arrendono alla funzione superiore, ma la funzione superiore non fa nulla con loro. Quello che ti serve è cederli dalla funzione inferiore a quella superiore:

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 

Questo dovrebbe fare il trucco.

+0

Mi sono sempre chiesto: c'è un rapido comando "produce tutto" o è il più breve ciclo di "for" che hai scritto? – Owen

+0

@Own nope, ma lo trovo OK in questo modo, sono solo due semplici righe ... –

+5

In Python 3.3 ci sarà un'istruzione 'yield from' che produrrà automaticamente elementi da un altro generatore, quindi qualsiasi ciclo' for' con un 'yield' in esso puoi scrivere come un'espressione di generatore può essere fatta in una riga. – agf

1

Al momento il ciclo for non corrisponde a yield. Si dovrebbe invece produrre tutti gli elementi che vengono generati dalla chiamata ricorsiva:

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