switch recipe?

Mark McEahern marklists at mceahern.com
Sat Jul 13 10:08:55 EDT 2002


[Christian Tanzer]
> Not so. As long as one of the iterators is finite, zip will work:
>
> >>> from __future__ import generators
> >>> def repeat(*args):
> ...     """Return a repeating alternator for args."""
> ...     while args:
> ...         for a in args:
> ...             yield a
> ...
> >>> for i, j in zip(range(5), repeat("a","b","c")):
> ...   print i, j
> ...
> 0 a
> 1 b
> 2 c
> 3 a
> 4 b

I just saw Office Space for the first time last night.  One of the
characters in the movie develops a prototype for a Jumping To Conclusions
mat.  That's certainly what I did about zip, assuming that it had similar
behavior to map when it came to unbounded iterators.  As you point out,
that's not true.

Because I want to do something to the zipped items, it doesn't seem like zip
solves all my problems, though.  map would, if it had the same behavior as
zip--namely that it stopped once one of the iterators ran out of items.
Below is a version that shows the use of zip.  Here are the key lines:

        weaved = zip(iterator, alternator)
        generated = [color_item(x, y) for x, y in weaved]

Perhaps what I'm still looking for is a way to
weave-two-iterators-with-a-function all at once.  One solution would be to
modify or wrap repeating_alternator() so that it was finite--then I could
just use map.

Thanks!

// mark

#! /usr/bin/env python

from __future__ import generators
import unittest

def repeating_alternator(*args):
    """Return a repeating alternator for args."""
    while args:
        for a in args:
            yield a

def weave_items(iterator, alternator, weave_item):
    """Iterate over iterator, applying weave_item to each item with its
    pair in alternator.
    """
    for item in iterator:
        yield weave_item(item, alternator.next())

def color_item(item, color):
    template = "<%(color)s>%(item)s</%(color)s>"
    return template % locals()

class test(unittest.TestCase):

    def test(self):
        iterator = range(10)
        colors = ("red", "organge", "yellow", "green", "blue", "indigo",
                  "violet")
        alternator = repeating_alternator(*colors)
        expected = ['<red>0</red>',
                    '<organge>1</organge>',
                    '<yellow>2</yellow>',
                    '<green>3</green>',
                    '<blue>4</blue>',
                    '<indigo>5</indigo>',
                    '<violet>6</violet>',
                    '<red>7</red>',
                    '<organge>8</organge>',
                    '<yellow>9</yellow>']
        weaved = zip(iterator, alternator)
        generated = [color_item(x, y) for x, y in weaved]
        self.assertEquals(expected, generated)

    def test_empty(self):
        r = repeating_alternator()
        self.assertRaises(StopIteration, r.next)

if __name__ == "__main__":
    unittest.main()

-






More information about the Python-list mailing list