[Edu-sig] Another Iterator Example (2.2a)
Kirby Urner
pdx4d@teleport.com
Mon, 23 Jul 2001 09:40:19 -0700
In the example below, we approximate the 2nd root of
a number using Newton's method. Each call to the
.next() method of our generator function gives a next
approximation, until the next guess is no different
from the last one, at which point we return (warning:
this is *not* a good test on which to stop iteration,
as the guesses may oscillate between two values --
better is to stop when the difference is under some
threshold).
To return from a generator is to end its effective life
span, although it sticks around to remind you it's dead.
Further calls to it throw a StopIteration exception:
>>> from play import *
>>> s = sqrt(2)
>>> s.next()
1.0
>>> s.next()
1.5
>>> s.next()
1.4166666666666667
>>> s.next()
1.4142156862745099
>>> s.next()
1.4142135623746899
>>> s.next()
1.4142135623730949
>>> s.next()
Traceback (most recent call last):
File "<pyshell#32>", line 1, in ?
s.next()
StopIteration
On the other hand, as we learned about iterators in general
in the last example, the for-loop use simply ends, without
throwing an exception, when the terminal condition is reached
(in this case, a return).
>>> s = sqrt(2)
>>> for i in s: print "%r" % i
1.0
1.5
1.4166666666666667
1.4142156862745099
1.4142135623746899
1.4142135623730949
You can restart the generator simply by reinitializing it:
>>> s = sqrt(2)
>>> [i for i in s]
[1.0, 1.5, 1.4166666666666667, 1.4142156862745099,
1.4142135623746899, 1.4142135623730949]
Source:
from __future__ import generators
def sqrt(target):
guess = 1.0 # initialize to 1
while 1:
newguess = (guess**2 + target)/(2*guess)
yield guess
if newguess==guess:
return
guess = newguess