[Python-Dev] Re: Graph exploration with generators
David Abrahams
dave at boost-consulting.com
Thu Aug 21 19:35:21 EDT 2003
"Shane Holloway (IEEE)" <shane.holloway at ieee.org> writes:
> Well, I've been holding this generators idea for after the Python 2.3
> release since it would be a Python 2. or later feature. That and I
> didn't want to delay the release by even a the time to read an email.
> ;)
>
> Over the last few months, I've been using generators more and more to
> do lazy graph exploration. As a concrete example, take the following
> binary tree type structure:
>
> class Tree(object):
> def __init__(self, left=(), right=()):
> self.left = left
> self.right = right
>
> def __iter__(self):
> for each in self.left:
> yield each
> yield self
> for each in self.right:
> yield each
>
> This works great for iterating over ad-hoc graphs, and since "left"
> and "right" simply have to be iterable, you can chain trees to graphs,
> lists, or anything iterable. However, for each "chained" generator
> quite a bit of speed is lost. I assume this loss is due to restoring
> each context in the chain. (I would need help verifying this
> assumption.)
> What I would like to propose is a "yield *" type statement, where
> "yield *collection" would have the equivalent functionality of "for
> item in collection: yield item". The above example would then appear
> as follows:
I wonder if this is improves the speed and is expressive enough:
class YieldSeq(object):
__slots__ = [ 'outer', 'inner' ]
def __init__(self, *seq):
self.outer = iter(seq)
self.inner = iter(()) # start with something empty
def __iter__(self):
return self
def next(self):
while 1:
try:
return self.inner.next()
except StopIteration:
self.inner = iter(self.outer.next())
class Tree(object):
def __init__(self, name, left=(), right=()):
self.name = name
self.left = left
self.right = right
def __iter__(self):
return YieldSeq(self.left, (self,), self.right)
def __repr__(self):
return self.name
t = Tree('a',
Tree('b',
Tree('c'),
Tree('d')),
Tree('e',
Tree('f'),
Tree('g')
)
)
print [ c for c in t ]
Of course I realize it's not as beautiful as using generators...
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
More information about the Python-Dev
mailing list