[Edu-sig] Some design patterns with iterators
Kirby Urner
urnerk@qwest.net
Wed, 02 Apr 2003 17:22:11 -0800
So, based on the foregoing, I'm playing around with the Seq class
below as a kind of template iterator. It's designed to accept a
passed-in test, or to let the user override the default test method
-- or to not supply a test at all.
The idea is: you want to generate this sequence, based on some rule.
By subclassing Seq, you inherit the iterator qualities you need, so
you can just focus on the __init__ and update methods, which define
the variables you'll be using, the the rule for going from one term
to the next in sequence (hence the name Seq).
The other wrinkle is the reset() method, which restores the iterator
to its initial state. I'm not sure if this is a good idea, but it
seems like it might be useful.
Example use:
>>> def t(self): return self.t1>1000
>>> fibs = iters.Fibseq(0,1,t)
>>> for i in fibs: print i,
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
>>> fibs.reset()
>>> fibs.next()
1
#---------- iters.py
from __future__ import division
class Seq(object):
"""
Subclass and override update() to do the next iteration and
to return a next value.
Your subclass's __init__ should define whatever instance
variables you need, including one named 'test' if you want
to pass in a test for the purpose of limiting iteration.
Or you may choose to override test in the source code.
Iteration stops when the passed in test returns True.
The test function, if written externally, should have self
as an argument, and refer to your instance variables as if
in a class, e.g. as self.variable.
"""
def next(self):
if not self.__dict__.has_key("_savedict"):
self._savedict = self.__dict__.copy()
if self.test(self):
raise StopIteration
else:
return self.update()
def update(self):
pass
def test(self):
return False
def __iter__(self):
return self
def reset(self):
if self.__dict__.has_key("_savedict"):
self.__dict__ = self._savedict.copy()
class Fibseq(Seq):
"""
Demonstrates how to subclass Seq. In this case, a test will
be supplied upon initialization. The user need define only
__init__ and update.
"""
def __init__(self,t1,t2,test):
self.t1 = t1
self.t2 = t2
self.test = test
def update(self):
self.t1, self.t2 = self.t2, self.t1 + self.t2
return self.t1