Notes on PEP 342 "Coroutines via Enhanced Generators"
I think I've worked my sparkly distraction out of my system, time to return to my Python study. This was motivated my CircuitPython experiments running on RP2040 microcontrollers. CircuitPython may be a reduced subset of Python, but it nevertheless incorporated many concepts that I have yet to grasp. Thus the study session, which dug through multiple PEP (Python Enhancement Proposal) design documents. Here are my notes after reading PEP 342 Coroutines via Enhanced Generators.
I was not familiar with coroutines, but I found a helpful explanation within Python glossary: "Coroutines are a more generalized form of subroutines. Subroutines are entered at one point and exited at another point. Coroutines can be entered, exited, and resumed at many different points." I was familiar with functions, which has a single entry point and multiple exit points. (Each return
is an exit.) When I read about "resume" in context, my first thought was of a function calling another. The parent caller function pauses execution waiting for the child callee function to run. Which is true, but Python coroutines have more points of interaction with each other. The caller can send
additional data to the callee, which receives that data via yield
. And they each maintain their internal state while this went on.
Why do we even want this? At surface I thought the same could be accomplished by standard nested loops, but example #2 in the PEP (JPEG contact sheet creator) helped me understand. Yes, maybe the pattern of execution could be replicated by nested loops, but that meant a single function has to track all variables involved in every nested loop. A coroutine, in contrast, can be written to encapsulate information for just one layer.
Here's my pseudocode to replicate example #2 with nested loops:
for each page of contact sheet
for each thumbnail on contact sheet
for each JPEG
generate thumbnail
add thumbnail to contact sheet
write page of contact sheet
If I want to process a bunch of JPEG differently, resulting in a different summary output JPEG, I would write a new function that has the different second loop but has the same innermost and outermost loops. With coroutines, I can get the same result by swapping out the thumbnail_pager
coroutine and continue using the rest without making any changes to them or duplicate code.
I think I see the advantage here for independent code modules, but it'll take a while for my brain to adapt and add this tool to my toolbox. During this transition period I'm likely to continue writing my code as nested loops. But at least this understanding helped me understand Python context managers. But before that, a complaint from grumpy Python student.