Sammy’s Generators in Python

Skyler Lewis
Aug 20, 2018 · 3 min read

Python generators are pretty rad and less scary than the slender man image you have in your mind.

It is lunch time and Sammy Sandwiches food truck pulls in to the parking lot next to your office. A line of people queue up next to the truck. Sammy begins taking orders. The workflow Sammy has been accustomed to has always been to take all the orders first, prepare all the orders, and finally deliver them to the customer.

Sammy’s workflow v1: Take all the orders. Then make all the sandwiches.

His customers have always been happy, and never complained about the time it takes to get food. But recently his food truck has become quite popular. He now has a pretty sizable line, and by the time he takes all the orders and prepares all the sandwiches, people are getting hungry!

Sammy had an idea. Take all the orders and then deliver each sandwich as he finishes them. That way at least some people don’t have to wait.

That is great, but that only makes a small difference. Customers who ordered first have to wait for everyone else to order before getting their food. Not bad when there are only a few people in line, but it is not scalable!

Rather than taking everyone’s order first, he decides to take one order, prepare the sandwich and then deliver it — all before taking the next order.

Tada! Sammy has done it. He has become successful by understanding and optimizing his operation.

Great story, but no real food truck would work like Sammy did in the beginning, but this happens in code all the time. Generators save us from being forced into a terrible workflows and opens up the bottlenecks. Just yield to the tasks and your function will put a pin in the loop, work on an item and move on to the next.

Now that you understand the broad strokes, let’s take a look at some ancillary details.

Generators are also iterators! By adding yield to your function, Python automatically adds the __iter__ and __next__ functions.

So you can do next()? Yup!

When you yield a generator, you aren’t just pausing execution to extract a value. You can also use that time to send a value to what is yielding.

This will return No Customer followed by 13 . This can get confusing, especially if you are just reading the code, and not running it. So try running it!

When you need to send data to your generator function, you can’t have the generator function be part of a loop. Instead assign it to a variable so you can manually handle next/send. (In the above example, I assign the generator to the action variable)

Once you have the action variable, you need to step over to the next yield. This is done with the next() function. Warning: executing send() before next(), you will get a TypeError: can't send non-None value to a just-started generator error.

If you did run the above example, you will notice a StopIteration exception being thrown. This happens because you have exhausted your generator, and it can’t continue. You can silence this with a try/except or you could also tell next() to default to none with next(action, None). Just be aware that if you are using send() there is no default option, and you will need to use a try/except.

The last thing I wanted to mention was pipelining generators. Let’s take a look at the following example:

This iterates and yields all users, first by employees and then by customers. This works fine to drain our generators, but Python has given us some syntactic sugar. yield from does the same thing, but in a cleaner, more readable format.

Voila! That is generators! Generators are the basis of many optimizations, including Asyncio! I will cover that at another time, but for now, I hope generators are a little less scary for you.

Skyler Lewis makes no claims to expertise or exactness of the information presented and may not reflect the opinions of the owners or advertisers. Parental guidance isn’t recommended. Any rebroadcast, retransmission, or account of this article, without the express written consent of Major League Baseball, is not prohibited. Use as directed. May cause sleepiness, headaches, backaches, or thoughts of bacon wrapped shrimp.

While you are at it, check out my company: Canopy and our dev events.

Development at Canopy Tax

Our amazing software is made possible because of our…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store