[Tutor] Workaround for limitation in xrange()?

Kent Johnson kent37 at tds.net
Tue Oct 10 22:27:09 CEST 2006


Dick Moores wrote:
> At 11:34 AM 10/10/2006, Kent Johnson wrote:
>> Dick Moores wrote:
>>> Here are the suggestions I've received:
>> <snipped>
>>
>>> All 3 are essentially the same, aren't they. 
>>> Which makes me feel even dumber, because I 
>>> don't understand any of them. I've consulted 3 
>>> books, and still don't understand the use of yield.
>> Yes, they are pretty much the same. Mine is 
>> bare-bones, just doing what you specifically 
>> asked for. Danny's is a full replacement for xrange(); Andrei's is in between.
>>
>> Here is a good introduction to generators:
>> http://www.python.org/doc/2.2.3/whatsnew/node5.html
> 
> While I'm studying that, could you modify my 
> while loop so that it incorporates your 
> suggestion in a way that improves it? That would 
> be a big help to me in understanding generators 
> and the use of yield, I believe.

I'm not certain I would call it an improvement, but it would look just 
like your loop with xrange(). If the generator function is called 
count(), your loop would be
for i in count(2**100):  # ;)
   # process i

The big advantage of generators is they let you encapsulate the logic 
that generates a sequence. This makes it easy to reuse a sequence 
without having to duplicate the sequence generation logic in multiple 
loops. Sometimes this can make your loop clearer because it can focus on 
processing the sequence rather than generating it. Sometimes it can 
greatly simplify your logic. This happens when both the generation of a 
sequence and the processing of it involve maintaining state.

Here's a very artificial and possibly helpful example. Consider the sequence
1, 1, 2, 1, 2, 3, 1, 2, 3, 4, ...

Imagine you want to do something with every third element of that 
sequence, for example sum them. Maybe it's not so hard to do this in a 
simple loop but my head starts to hurt thinking about it.

OK, so let's encapsulate the sequence into a generator:
In [13]: def multicount(limit):
    ....:     for i in range(1, limit+1):
    ....:         for j in range(1, i+1):
    ....:             yield j
    ....:
    ....:

In [14]: list(multicount(5))
Out[14]: [1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5]

Now summing every third element is easy:
In [16]: sum(list(multicount(5))[::3])
Out[16]: 10

Does that help?

Kent



More information about the Tutor mailing list