ricardomol
  • Ricardomol Notes
  • Frontend
    • Javascript Toolchain
    • Javascript
      • Quirks
      • Articles
        • Function caching
        • 12 JS Tricks
      • Closures
      • Assorted
      • ES6
      • this
      • OOP
      • Async Programming
      • Functional Programming
      • Typescript
    • React
      • Patterns
        • Render props
      • React Router
    • Webpack
    • CSS
      • Resources
  • Backend
    • Python
      • Shallow copy vs deep copy
      • Classes
      • Resources
      • Python C Extensions
      • Coroutines
      • Exceptions
      • Context managers
      • One-Liners
      • Open function
      • Object introspection
      • Targeting Python 2 + 3
      • For - else
      • Comprehensions
      • Lambdas
      • __slots__ magic
      • Collections
      • Enumerate
      • Mutation
      • Map, Filter and Reduce
      • Decorators
      • Sets
      • Fluent Python summary
      • Quizes / Tips
      • Generators
    • Django
      • Generic Relations
      • FBV's vs CBV's
      • ORM
      • DRF
    • RESTful Architecture
    • Resources
  • Databases
    • Joins
    • Normalization
    • PostgreSQL
  • DevOps
    • Docker
      • 0. Resources
      • 2. Services
      • 3. Swarms
      • 5. Stacks
      • 6. Deploy your app
    • CI
      • CI with Django
    • CD
    • PaaS
    • WSGI servers
    • Django
      • Django Deployment
    • Modern DevOps with Django
  • Git
    • Git
  • Comp Sci
    • Big O Notation
    • Patterns
    • Programming paradigms
  • Assorted
    • TCP vs UDP
    • Tests
    • MongoDB
    • Node
      • Resources
    • Go
    • HTTP vs HTTP2
    • GraphQL
    • Books
    • Vim
    • IPv4 vs IPv6
    • Regex
    • Redis
    • Celery
      • Brokers
    • Caching
  • SECURITY
    • Security
Powered by GitBook
On this page
  1. Backend
  2. Python

Coroutines

Similar to generators with a few differences:

  • generators are data producers

  • coroutines are data consumers

Generator blueprint:

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a+b

We then commonly use it in a for loop like this:

for i in fib():
    print(i)

It is fast and does not put a lot of pressure on memory because it generates the values on the fly rather than storing them in a list.

If we use yield in the above example, we get a coroutine.

Coroutines consume values which are sent to it.

Example: a grep alternative in Python:

def grep(pattern):
    print("Searching for", pattern)
    while True:
        line = (yield)
        if pattern in line:
            print(line)

We have turned it into a coroutine. yield does not contain any value initially, instead we supply it values externally. We supply values by using the .send()method. Example:

search = grep('coroutine')
next(search)
# Output: Searching for coroutine
search.send("I love you")
search.send("Don't you love me?")
search.send("I love coroutines instead!")
# Output: I love coroutines instead!

The sent values are accessed by yield.

next()is required to start the coroutine. Just like generators, coroutines do not start the function immediately. Instead they run it in response to the __next__() and .send() methods. Therefore, you have to run next() so that the execution advances to the yield expression.

Close a coroutine by calling the .close() method:

search = grep('coroutine')
# ...
search.close()

Further reading

PreviousPython C ExtensionsNextExceptions

Last updated 6 years ago

There is a lot more to coroutines. I suggest you check out by David Beazley.

this awesome presentation