- If the compiler detects the
yield
keyword anywhere inside a function, that function no longer returns via thereturn
statement. Instead, it immediately returns a lazy "pending list" object called a generator - A generator is iterable. What is an iterable? It's anything like a
list
or,set
or,range
or dict-view, dictionary view, or any other object with a built-in protocol for visiting each element in a certain order.
Comparing the example to "just returning a list"
The above example can be thought of as merely creating a list whichthat you append to and return:
Please note: generators can actually be used for many more things, such as implementing coroutines or, non-deterministic programming or, and other elegant things. However, the "lazy lists" viewpoint I present here is the most common use you will find.
A coroutine (generators whichthat generally accept input via the yield
keyword e.g. nextInput = yield nextOutput
, as a form of two-way communication) is basically a computation whichthat is allowed to pause itself and request input (e.g. to what it should do next). When the coroutine pauses itself (when the running coroutine eventually hits a yield
keyword), the computation is paused and control is inverted (yielded) back to the 'calling' function (the frame which requested the next
value of the computation). The paused generator/coroutine remains paused until another invoking function (possibly a different function/context) requests the next value to unpause it (usually passing input data to direct the paused logic interior to the coroutine's code).
You can think of pythonPython coroutines as lazy incrementally-pending lists, where the next element doesn't just depend on the previous computation, but also on input that you may opt to inject during the generation process.