[Tutor] generators?

Kirby Urner urnerk@qwest.net
Thu, 29 Nov 2001 21:51:34 -0800


If you don't like the idea of preallocating
memory to hold a list of a million consecutive
integers, as in range(int(1E6)), you could
write lazyrange(a,b,c), which gives the next
integer as needed, but doesn't preallocate.

  >>> def lazyrange(start,stop,inc):
	if (start<stop and inc<0) or \
	   (start>stop and inc>0):
	   raise ValueError,"Illegal parameters"
	while start<stop:
	   yield start
	   start += inc
	return

Because it's a generator, a kind of iterator,
you can iterate over lazyrange() just as you
would range(), meaning you have the benefit
of already familiar syntax:

  >>> for i in lazyrange(0,10,1):
        print i,

  0 1 2 3 4 5 6 7 8 9

You could even get fancy and call yours 'range'
for the duration of your program.  Just store the
builtin range to a variable and restore it when
done:

  >> sr = __builtins__.range

  [define range as above, lazyrange...]

  >>> for i in range(0,1,.1): print i,

  0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0

Works for non-integer increment! -- except I don't
get why it doesn't stop with 0.9, as the previous
example stopped at 9.  Anyone?

OK, we want our regular range() builtin back:

  >>> range = sr  # -- setting range back to default
  >>> range(0,1,.1)
  Traceback (most recent call last):
    File "<pyshell#37>", line 1, in ?
      range(0,1,.1)
  ValueError: range() arg 3 must not be zero

OK, now we get an error message, cuz builtin range
doesn't like .1 as the increment.

Kirby