Question
Can someone give me an example of why the "send" function associated with Python generator function exists? I fully understand the yield function. However, the send function is confusing to me. The documentation on this method is convoluted:
generator.send(value)
What does that mean? I thought value was the input to the function? The phrase "The send() method returns the next value yielded by the generator" seems to be also the exact purpose of the yield function; yield returns the next value yielded by the generator... Can someone give me an example of a generator utilizing send that accomplishes something yield cannot?
How-To
It's used to send values into a generator that just yielded. Here is an artificial (non-useful) explanatory example. Consider a testing function:
- def double_inputs():
- while True:
- x = yield
- yield x * 2
As to why it's useful, one of the best use cases I've seen is Twisted's @defer.inlineCallbacks. Essentially it allows you to write a function like this:
- @defer.inlineCallbacks
- def doStuff():
- result = yield takesTwoSeconds()
- nextResult = yield takesTenSeconds(result * 10)
- defer.returnValue(nextResult / 10)
- def doStuff():
- returnDeferred = defer.Deferred()
- def gotNextResult(nextResult):
- returnDeferred.callback(nextResult / 10)
- def gotResult(result):
- takesTenSeconds(result * 10).addCallback(gotNextResult)
- takesTwoSeconds().addCallback(gotResult)
- return returnDeferred
- #!/usr/bin/env python
- import functools
- import sys
- import time
- # https://docs.python.org/2/library/functools.html
- def init_coroutine(func):
- functools.wraps(func)
- def init(*args, **kwargs):
- gen = func(*args, **kwargs)
- next(gen)
- return gen
- return init
- def dataSrc(alist, target):
- counter = 0
- for e in alist:
- target.send(e)
- time.sleep(1)
- @init_coroutine
- def plus2(target):
- while True:
- x = yield
- target.send( x + 2 )
- @init_coroutine
- def multi2(target):
- while True:
- x = yield
- target.send( x * 2 )
- @init_coroutine
- def output():
- while True:
- x = yield
- print("Output: {}".format(x))
- print('Output: (x + 2) * 2')
- dataSrc(range(5), plus2(multi2(output())))
- print('Output: (x * 2) + 2')
- dataSrc(range(5), multi2(plus2(output())))
Supplement
* Python generator.send with yield
沒有留言:
張貼留言