Welcome, guest | Sign In | My Account | Store | Cart

With Python 2.2+, you can make generators that return unbounded output. By creating a "wrapper" generator that runs the first generator, you can restrict its output to some defined subset.

Python, 23 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def genWhile(g, condition):
    """
    run generator g while 'condition' is true.
    Condition is a partial expression such as "< 10"
    to be evaluated with g.next() as the left side
    """
    while 1:
        next = g.next()
        if eval("next " + condition):
            yield next
        else:
            return


def genEven():
    x = 0
    while 1:
        x += 2
        yield x


def main():
    print [x for x in genWhile(genEven(), "< 12")]

The generator "genEven" above, generates all positive even numbers. To see the positive even numbers < 12, it would be tempting to write something like:

[x for x in genEven() if x < 12]

But this does not work. Instead, we can use the wrapper "genWhile" to get a similar effect:

[x for x in genWhile(genEven(), "< 12")]

2 comments

Tom Good (author) 20 years, 11 months ago  # | flag

fix. The "return" statement in the code above should be indented so as to be inside the else:

Steve Alexander 20 years, 5 months ago  # | flag

Use the two argument form of iter. You can use the two-argument form of iter() to get some of the same effect.

So, this:

[x for x in iter(genEven().next, 12)]

gives the same result as this:

[x for x in genWhile(genEven(), "&lt; 12")]

Of course, genWhile is more flexible, as it understands predicates rather than just a simple sentinel.

Created by Tom Good on Wed, 25 Jul 2001 (PSF)
Python recipes (4591)
Tom Good's recipes (4)
Python Cookbook Edition 1 (103)

Required Modules

  • (none specified)

Other Information and Tasks