1

Consider the following (non-working) example code:

class MyGenerator: def test_gen(self): for i in range(1,5): if i % 2: self.foo(i) else: self.bar(i) def foo(self, i): yield i def bar(self, i): yield i**2 g = MyGenerator() for i in g.test_gen(): print i 

This will not work, because test_gen has no yield and is no longer a generator function. In this small example I could just return the values from foo and bar and put the yield into test_gen, however I have a case where that's not possible. How can I turn test_gen into a generator function again?

2 Answers 2

5

You need to loop over the results of the delegated generators and yield those:

def test_gen(self): for i in range(1,5): if i % 2: for res in self.foo(i): yield res else: for res in self.bar(i): yield res 

If you are using Python 3.3 or up, you'd use the yield from expression to do proper generator delegation:

def test_gen(self): for i in range(1,5): if i % 2: yield from self.foo(i) else: yield from self.bar(i) 

Both re-introduce yield into the function, once again making it a generator function.

Sign up to request clarification or add additional context in comments.

2 Comments

Ha, the Python 3 way is exactly what I was looking for! Sweet and concise. Unfortunately I'm on Python 2.7 :-(
In this special example, the subgenerator will just yield a simple item before exhausting, so the yield from examples are fine. But people using it have to attempt they do yield up to exhaustion of the sub-generators, not a single item - and only after that the controls comes back to the primary generator. (otherwise they would not be distinguishable from a plain yield)
0

why not just:

class MyGenerator: def test_gen(self): for i in range(1,5): if i % 2: yield next(self.foo(i)) else: yield next(self.bar(i)) def foo(self, i): yield i def bar(self, i): yield i**2 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.