Mixing generators and recursion

Francis Avila francisgavila at yahoo.com
Tue Nov 4 17:01:44 EST 2003


"Gerson Kurz" <gerson.kurz at t-online.de> wrote in message
news:3fa80eaa.22505703 at news.t-online.de...
> No, it has nothing to do with the pathname. Try this:
>
> def f(nested):
>     if not nested:
>         f(True)
>     else:
>         yield 42
>
> for k in f(False): print k
>
> Step through it in the mind:
> - f(False) gets called
> - it is not nested, so f(True) gets called
> - it is nested, so should yield 42 - but it doesn't!
> - instead, you get an empty list.

Computer's can't read our minds, though....

> def f(nested):
>     if not nested:

F is false so...

>         f(True)

...call function f(True), which returns a *generator*...
...which is never bound to anything, so the refcount goes to 0.

>     else:
>         yield 42

Above never gets executed by anything at all.

Look:
>>> def g():
...     yield 'Hello there!'
...
>>> type(g)
<type 'function'>
>>> g.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
    g.next()
AttributeError: 'function' object has no attribute 'next'
>>> G = g()
>>> type(G)
<type 'generator'>
>>> G.next()
'Hello there!'
>>>

See the difference?

What you want something like:

def f(nested):
    if not nested:
        for v in f(True): yield v
    else:
        yield 42

for k in f(False): print k     # 42

I.e., you must explicitly iterate the generator.  No 'yield' ever yields
without a next() asking first.  (That next() call can be implicit or
explicit, but it's still always there.)
--
Francis Avila





More information about the Python-list mailing list