[Tutor] Generator function question?

Karl Pflästerer sigurd at 12move.de
Sat May 7 16:04:44 CEST 2005


On  7 Mai 2005, clajo04 at mac.com wrote:

> It's clear that your code is a more elegant implementation of
> neverEndingStatus() but I am still having to initialize a global variable
> and call .next() when I want to get the next value... So the generator
> function has been cleaned up, but the client code interaction with the
> function is still pretty much the same.
>
> (Either that, or I am not following what you mean when you say:
>
>>      As for how to access it, use a for loop (for i in
>> neverEndingStatus()). xrange, for example, is a generator function.
>
> Can you please provide an example of how my Test1() function changes based
> on your suggestion?  (sorry to be dense)


The for loop does all the work for you: generating an iterator from the
generator function and calling its `next' method until the iterator is
exhausted (raises StopIteration).

So you first should write a generator function which produces the values
you need (perhaps with some way to stop it after a defined number of
characters) and then you u8se a for loop to get the values from the
iterator (which is what you get when you call a generator function).

So here is an example.

First the generator function:

def status (chars=r'|\-/', num_of_chars=None):
    if num_of_chars <= 0: return
    elif num_of_chars:
        while True:
            for c in chars:
                yield c
                num_of_chars -= 1
                if num_of_chars <= 0: return
    else:
        while True:
            for c in chars: yield c


Now to print the characters from the function you could write:

for c in status(num_of_chars=10): sys.stdout.write(c)

and it would print 10 characters (starting with '|' and ending with '\'.
So far so good but that looks a bit ugly.  Python has a great library if
you want to work with iterators: the itertools.  There you find alot of
functions which help you to write the above code much shorter and nicer.

import itertools as it

def status2 (chars=r'|\-/', num_of_chars=None):
    for c in it.islice(it.cycle(chars), num_of_chars): yield c

The best is you look in the documentation of itertools to understand
what's happening here, but a short explanation might help.

'itertools.cycle' takes an iterator and if it's exhausted it starts to
emit the same values again and again and again ...  If you want to stop
the ietrator somewhere there are several possibilities but one is to use
another function from itertools `itertools.islice'.  It works a bit like
a normal slice (with which you can take some values from e.g. a list or
a string) but generates an iterator.  So the above
          it.islice(it.cycle(chars), num_of_chars)
returns an iterator which yields num_of_chars characters from the
iterator which was returned from 
          it.cycle(chars)
If num_of_chars is None then it yields an unlimited numkber of chars.

The above may be a bit to advanced for you if you just start with Python
but maybe also not (if you know programming at all).  Look in the
documentation, try it ot and then ask again.



   Karl
-- 
Please do *not* send copies of replies to me.
I read the list


More information about the Tutor mailing list