David Beazley's tutorials on these topics are also excellent:
* Generator Tricks for Systems Programmers (PyCon 2008: http://www.dabeaz.com/generators/) * A Curious Course on Coroutines and Concurrency (PyCon 2009: http://www.dabeaz.com/coroutines/) * Generators: The Final Frontier (PyCon 2014: http://www.dabeaz.com/finalgenerator/)
The first one focuses on iteration, the second expands to cover PEP 342 and sending values into coroutines, while the last expands to cover *all* the different ways we use generator suspension points these days (including in context managers and asynchronous I/O).
The async I/O section is particularly interesting because David initially uses threads in order to delay getting into the complexities of event loops, while still illustrating the concept of "waiting for other things to happen".
(Note: once you get to Part 5 of the last tutorial, you're getting to stuff that really pushes the boundaries of what generators can do, using examples from domains that are complex in their own right. The very last section also contains some wise words around the fact that we're genuinely pushing out the boundaries of the language's expressive capabilities, which does carry some non-trivial risks)
I do believe that last tutorial also does a good job of illustrating a lot of the complexity that PEP 492 is intended to *hide* from (future!) end users by simplifying the story to "use async & await for cooperative multitasking, threads & processes for preemptive multitasking, and yield & yield from for iteration", rather than having the "cooperative multitasking" case continue to be a particular way of using yield & yield from as it is in Python 3.4 (and a way of use "yield" in earlier releases).