On Fri, May 1, 2015 at 12:24 PM, Ethan Furman <ethan@stoneleaf.us> wrote:
On 05/01, Guido van Rossum wrote:
> On Fri, May 1, 2015 at 11:26 AM, Jim J. Jewett <jimjjewett@gmail.com> wrote:

>> So does this mean that yield should NOT be used just to yield control
>> if a task isn't blocked?  (e.g., if its next step is likely to be
>> long, or low priority.)  Or even that it wouldn't be considered a
>> co-routine in the python sense?
>>
>
> I'm not sure what you're talking about. Does "next step" refer to something
> in the current stack frame or something that you're calling? None of the
> current uses of "yield" (the keyword) in Python are good for lowering
> priority of something. It's not just the GIL, it's that coroutines (by
> whatever name) are still single-threaded. If you have something
> long-running CPU-intensive you should probably run it in a background
> thread (or process) e.g. using an executor.

So when a generator is used as an iterator, yield and yield from are used
to produce the actual working values...

But when a generator is used as a coroutine, yield (and yield from?) are
used to provide context about when they should be run again?

The common thing is that the *argument* to yield provides info to whoever/whatever is on the other end, and the *return value* from yield [from] is whatever they returned in response.

When using yield to implement an iterator, there is no return value from yield -- the other end is the for-loop that calls __next__, and it just says "give me the next value", and the value passed to yield is that next value.

When using yield [from] to implement a coroutine the other end is probably a trampoline or scheduler or multiplexer. The argument to yield [from] tells the scheduler what you are waiting for. The scheduler resumes the coroutine when that value is avaiable.

At this point please go read Greg Ewing's tutorial. Seriously. http://www.cosc.canterbury.ac.nz/greg.ewing/python/yield-from/yield_from.html

Note that when using yield from, there is a third player: the coroutine that contains the "yield from". This is neither the scheduler nor the other thing; the communication between the scheduler and the other thing passes transparently *through* this coroutine. When the other thing has a value for this coroutine, it uses *return* to send it a value. The "other thing" here is a lower-level coroutine -- it could either itself also use yield-from and return, or it could be an "I/O primitive" that actually gives the scheduler a specific instruction (e.g. wait until this socket becomes readable).

Please do read Greg's tutorial.

--
--Guido van Rossum (python.org/~guido)