[Tutor] recursive generator

Hugo Arts hugo.yoshi at gmail.com
Sun Mar 7 17:21:11 CET 2010

sorry, forgot to forward this to the list.

On Sun, Mar 7, 2010 at 1:58 PM, spir <denis.spir at gmail.com> wrote:
> Hello,
> Is it possible at all to have a recursive generator? I think at a iterator for a recursive data structure (here, a trie). The following code does not work: it only yields a single value. Like if child.__iter__() were never called.
>    def __iter__(self):
>        ''' Iteration on (key,value) pairs. '''
>        print '*',
>        if self.holdsEntry:
>            yield (self.key,self.value)
>        for child in self.children:
>            print "<",
>            child.__iter__()
>            print ">",
>        raise StopIteration
> With the debug prints in code above, "for e in t: print e" outputs:
> * ('', 0)
> < > < > < > < > < > < > < > < >
> print len(t.children) # --> 9
> Why is no child.__iter__() executed at all? I imagine this can be caused by the special feature of a generator recording current execution point. (But then, is it at all possible to have a call in a generator? Or does the issue only appear whan the callee is a generator itself?) Else, the must be an obvious error in my code.
> Denis

remember that child.__iter__ returns a generator object. Merely
calling the function won't do anything. To actually get elements from
a generator object, you need to call next() on the returned iterator,
or iterate over it in another way (e.g. a for loop). I would write
this method more or less like so:

from itertools import chain

def __iter__(self):
   this_entry = [(self.key, self.value)] is self.holds_entry else []
   return chain(this_entry, *[iter(c) for c in self.children])

(Warning! untested! I'm pretty sure chain will work like this, but you
might have to do a little tweaking)

More information about the Tutor mailing list