[Tutor] Workaround for limitation in xrange()?

Kent Johnson kent37 at tds.net
Thu Oct 12 02:49:31 CEST 2006


Alan Gauld wrote:
> "Dick Moores" <rdm at rcblue.com> wrote in message 
> news:7.0.1.0.2.20061010102836.06be3ae0 at rcblue.com...
>> Encapsulate the while loop in a generator:
>> def count(limit):
>>   n=0
>>   while n<limit:
>>     yield n
>>     n += 1
>>
>> 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.
> 
> Think of yield as being the same as return except that next time
> you "call the function" all the state is preserved and it picks up 
> processing
> after the yield.

A small correction - in normal use you only call the generator function 
once. The value it returns is a generator, an object with a next() 
method. It is the next() method that is called repeatedly to re-enter 
the function and return the next value. When there are no more values to 
return, the next() method raises StopIteration.

For example:
In [1]: def f(): yield 1
    ...:

In [2]: f
Out[2]: <function f at 0x00F15C70>

f is a generator function. The result of calling it is a generator:
In [3]: p=f()

In [4]: p
Out[4]: <generator object at 0x00F23670>

The generator p is not callable:
In [5]: p()
---------------------------------------------------------------------------
<type 'exceptions.TypeError'>             Traceback (most recent call last)

D:\Projects\e3po\<ipython console> in <module>()

<type 'exceptions.TypeError'>: 'generator' object is not callable

p.next() yields values, then raises StopIteration:
In [6]: p.next()
Out[6]: 1

In [7]: p.next()
---------------------------------------------------------------------------
<type 'exceptions.StopIteration'>         Traceback (most recent call last)

D:\Projects\e3po\<ipython console> in <module>()

<type 'exceptions.StopIteration'>:

The generator also has an __iter__() method that returns the generator 
itself:

In [9]: p.__iter__() is p
Out[9]: True

In other words, a generator satisfies the iterator protocol
http://docs.python.org/lib/typeiter.html
and it can be used any where an iterator can be used, such as in a for 
statement.

Kent

> 
> So first time you call count above it returns 0
> next time you call it it executes the n+= 1 and goes round the loop
> again until it hits yield when it returns 1.
> next time you call it executes y+=1 again, but because the state has
> been remembered n goes to 2 and yield returns that
> and so on until you reach n = limit at which point it just
> exits with StopIteration.  Here is a short example:
> 
>>>> def y(n):
> ...   j = 0
> ...   while j < n:
> ...     yield j
> ...     j += 1
> ...
>>>> try:
> ...    x = y(7)
> ...    for n in range(20):
> ...      print x.next()
> ... except StopIteration:
> ...   print 'Reached the end'
> ...
> 0
> 1
> 2
> 3
> 4
> 5
> 6
> Reached the end
> 
> Does that help?
> 
> 




More information about the Tutor mailing list