python3 yield from skills up
#python#coroutinepython3 yield from skills up
The explanation that yield from g is equivalent to for v in g: yield v does not even begin to do justice to what yield from is all about. Because, let's face it, if all yield from does is expand the for loop, then it does not warrant adding yield from to the language and preclude a whole bunch of new features from being implemented in Python 2.x. Think of yield from as providing a transparent two-way channel from the caller to the sub-generator.
sending data to a generator using yield from
def generator():
"""
A generator(coroutine) that writes data *sent* to it to fd, socket, etc.
"""
while True:
w = (yield)
print('>> %s' % w)
def gen_wrapper(c): # c for coroutine
yield from c
if __name__ == '__main__':
gen = generator()
wrap = gen_wrapper(gen)
wrap.send(None) # initialize the coroutine
for i in range(4):
gen.send(i)
exception handling for yield from
class TransactionException(Exception):
pass
def generator():
while True:
try:
w = (yield)
except TransactionException:
print('******')
else:
print('>> ', w)
def gen_wrapper(c): # c for coroutine
yield from c
if __name__ == '__main__':
gen = generator()
wrap = gen_wrapper(gen)
wrap.send(None)
for i in [0, 1, 2, 3, 'exc', 4]:
if i == 'exc':
wrap.throw(TransactionException)
else:
wrap.send(i)
close outside of block
def generator():
while True:
w = (yield)
print('>> ', w)
def gen_wrapper(c): # c for coroutine
yield from c
if __name__ == '__main__':
gen = generator()
wrap = gen_wrapper(gen)
wrap.send(None)
for i in [0, 1, 2, 3, 'close', 4]:
if i == 'close':
wrap.close()
else:
wrap.send(i)
benefits of yield
- Using a generalization of the StopIteration exception makes it easy for other kinds of iterators to participate in the protocol without having to grow an extra attribute or a close() method.
- It simplifies the implementation, because the point at which the return value from the subgenerator becomes available is the same point at which the exception is raised. Delaying until any later time would require storing the return value somewhere.
- the primary benefits of yield from come when you've written a generator that uses these techniques and when it needs to be refactored.
and especially this part: https://www.python.org/dev/peps/pep-0380/#generators-as-threads
coroutine
is not a callback
(which is yield
is not a function
)
The difference is that whenever the generator "yields" a value the execution of the generator is paused and the code continues where the generator was called.
reference
http://legacy.python.org/dev/peps/pep-0380/ http://legacy.python.org/dev/peps/pep-0342/ http://stackoverflows.com
- speacial great thanks to @Fantix King