First, consider the following code (I'm going to discuss several versions of subgen()
next):
>>> def maingen(i):
... print("maingen started")
... yield from subgen(i)
... print("maingen finished")
...
>>> for i in maingen(5):
... print(i)
...
I want to write several subgen
generator functions.
A normal one is:
>>> def subgen_1(i):
... yield i + 1
... yield i + 2
... yield i + 3
No prob, output is as expected:
maingen started
6
7
8
maingen finished
Now, I want an other version of subgen
which yields nothing...
If I try that:
>>> def subgen_2(i):
... i * 3
I've an exception:
maingen started
Traceback (most recent call last):
...
TypeError: 'NoneType' object is not iterable
It's expected: subgen_2
isn't a generator function.
OK, next. I can read somewhere (like the first answer here)
that I've to raise a StopIteration
. (Note that, as a newbie, I can't comment this answer.)
>>> def subgen_3(i):
... i * 3
... raise StopIteration()
...
As identified in PEP 479, "Finally, the proposal also clears up the confusion about how to terminate a generator: the proper way is return
, not raise StopIteration
.", I only get:
maingen started
(no maingen finished
...)
And the only way I've found to get things OK is:
>>> def subgen_4(i):
... i * 3
... return
... yield
...
With this, I get:
maingen started
maingen finished
Hourrah! But this solution isn't beautiful...
Does anyone have a better or a more pythonic idea?
Is it possible to write a decorator to secretly add the ugly yield statement?