A backport of the `yield from` semantic from Python 3.x to Python 2.7
Project description
A backport of the yield from
semantic from Python 3.x to Python 2.7
If you want to nest generators in Python 3.x, you can use the yield from
keywords. This allows you to automatically iterate over sub-generators and
transparently pass exceptions and return values from the top level caller
to the lowest generator.
def subgen(): yield 2 yield 3 def gen(): yield 1 yield from subgen() # Python 3.x only yield 4 def main(): for i in gen(): print i, >>> main() ... 1 2 3 4
This functionality is not available in Python 2.x, and we emulate it using the
yieldfrom
decorator and the helper From
class:
from yieldfrom import yieldfrom, From def subgen(): yield 2 yield 3 @yieldfrom def gen(): yield 1 yield From(subgen()) yield 4 def main(): for i in gen(): print i, >>> main() ... 1 2 3 4
Advanced usage allows returning a value from the subgenerator using
StopIteration
. Using Return
does this conveniently:
from yieldfrom import yieldfrom, From, Return def subgen(): yield 2 yield 3 Return(100) # Raises `StopIteration(100)` @yieldfrom def gen(): yield 1 ret = (yield From(subgen())) yield 4 yield ret def main(): for i in gen(): print i, >>> main() ... 1 2 3 4 100
Subgenerators can be nested on multiple levels, each one requiring additional
decoration by yieldfrom
:
def subsubgen(): yield 2 @yieldfrom def subgen(): yield From(subsubgen()) yield 3 @yieldfrom def gen(): yield 1 yield From(subgen()) yield 4 def main(): for i in gen(): print i, >>> main() ... 1 2 3 4
Exceptions thrown into the top-level generator can be handled in relevant subgenerators:
def subsubgen(): try: yield 2 except ValueError: yield 200 @yieldfrom def subgen(): yield From(subsubgen()) yield 3 @yieldfrom def gen(): yield 1 yield From(subgen()) yield 4 def main(): try: g = gen() while True: i = g.next() if i == 2: i = g.throw(ValueError()) print i, except StopIteration: pass >>> main() ... 1 200 3 4
Note that if you use yield From()
on a simple iterable (list
,
tuple
, etc) then the individual members of the iterator will be yielded on
each iteration (perhaps in that case you need the usual yield
).
@yieldfrom def gen(): yield From([1, 2, 3]) yield [1, 2, 3] def main(): for i in gen(): print i >>> main() ... 1 ... 2 ... 3 ... [1, 2, 3]
Passing non-iterable objects to From
will result in an empty
generator that does nothing.
@yieldfrom def gen(): yield From(None) yield 1 def main(): for i in gen(): print i >>> main() ... 1
This module is an adaptation of the following Python recipe:
http://code.activestate.com/recipes/576727
Modifications include bug fixes in exception handling, naming, documentation,
handling of empty generators, etc.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size yieldfrom-1.0.4-py2-none-any.whl (6.1 kB) | File type Wheel | Python version py2 | Upload date | Hashes View hashes |
Filename, size yieldfrom-1.0.4.tar.gz (5.0 kB) | File type Source | Python version None | Upload date | Hashes View hashes |
Hashes for yieldfrom-1.0.4-py2-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ab62daf50776de62b7ea98f5264f372c1cb33ca8af1a244bd5c42405381edf8e |
|
MD5 | c94df2ec41cee7e89dc23f3549ec3026 |
|
BLAKE2-256 | a7a968ac74ef7b1b8950a8aa40493f99b8756e69cbcbccdd020a523d532697c6 |