generator functions: why won't this work?

George Sakkis george.sakkis at gmail.com
Wed Apr 2 05:24:01 CEST 2008


On Apr 1, 11:17 pm, George Sakkis <george.sak... at gmail.com> wrote:
> On Apr 1, 10:56 pm, zillo... at googlemail.com wrote:
>
>
>
> > Hi all,
>
> > I'm trying to understand generator functions and the yield keyword.
> > I'd like to understand why the following code isn't supposed to work.
> > (What I would have expected it to do is, for a variable number of
> > arguments composed of numbers, tuples of numbers, tuples of tuples,
> > etc., the function would give me the next number "in sequence")
> > ####################################
> > def getNextScalar(*args):
> >    for arg in args:
> >       if ( isinstance(arg, tuple)):
> >          getNextScalar(arg)
> >       else:
> >          yield arg
> > ####################################
>
> > # here's an example that uses this function:
> > # creating a generator object:
> > g = getNextScalar(1, 2, (3,4))
> > g.next() # OK: returns 1
> > g.next() # OK: returns 2
> > g.next() # not OK: throws StopIteration error
>
> > ####################################
>
> > I'm sure I'm making some unwarranted assumption somewhere, but I
> > haven't been able to figure it out yet (just started learning Python a
> > couple of days ago).
>
> > Any help will be appreciated :)
>
> You're pretty close, there's just one more thing left. The return
> value of a generator function is an iterable, something you're
> supposed to iterate over. In the 'if' clause you call recursively the
> generator on arg but you don't use the result, you discard it as soon
> as it is returned. What you have to do is iterate over the returned
> iterable and yield its values:
>
>        # don't need parentheses around the if expression
>        if isinstance(arg, tuple):
>           for scalar in getNextScalar(arg):
>               yield scalar
>
> Hope this helps,
> George

Just after hitting send I noticed a second unrelated issue that has to
do with the generator's signature. Since you define it to take any
positional arguments instead of a single argument (as I mistakenly
assumed), the right way to call it recursively is expand the tuple arg
into positional arguments: getNextScalar(*arg) instead of
getNextScalar(arg):

        # don't need parentheses around the if expression
        if isinstance(arg, tuple):
           for scalar in getNextScalar(*arg):
               yield scalar

George



More information about the Python-list mailing list