The Python Coding Stack

The Python Coding Stack

The Club

Parkruns, Python’s enumerate and zip, and Why Python Loops Are Different from Other Languages • [Club]

Don’t forget about enumerate() and zip() when coding in Python • A short post

Stephen Gruppetta's avatar
Stephen Gruppetta
Jan 09, 2026
∙ Paid

If you live in the UK, you’re probably familiar with the Parkrun tradition: a friendly 5k run held every Saturday morning in hundreds of parks across the UK. Runners range from Olympians to people trying to lose some weight. It’s a well-oiled format replicated across all 893 Parkrun locations.

And here’s how they deal with the finish line logistics. Runners don’t wear bibs with numbers. When they cross the finish line, they enter a “funnel” marked by plastic cones and are handed a token with their position number. They then proceed to another official, who scans their personal barcode, which runners carry in their pockets or on a wristband, and the position token they received a few seconds earlier. This process matches the runner with their finishing position.

What’s this got to do with Python loops? And how does it help us understand why Python does loops differently from other languages?

First step, let’s create the Parkrun funnel. I’ll just put the first five finishers in this example:

>>> funnel = [”Jonathan”, “Michael”, “Samantha”, “Jessica”, “Daniel”]

Now, here’s something you definitely know already because it’s always one of the first things you’re taught when learning Python: Don’t loop through this list like this:

# Avoid this when coding in Python
>>> i = 0
>>> while i < len(funnel):
...     name = funnel[i]
...     print(name)
...     i += 1
...    
Jonathan
Michael
Samantha
Jessica
Daniel

This style mimics how other languages may work: you manually define and increment the index. To be fair, most people who shift from other languages are more likely to write the following version at some point:

# Also best to avoid this in Python
>>> for i in range(len(funnel)):
...     name = funnel[i]
...     print(name)
...    
Jonathan
Michael
Samantha
Jessica
Daniel

This version may seem more Pythonic since it uses Python tools such as range(), but still fails to make the most of Python’s iteration protocol. The Pythonic way of looping through this list is the following:

>>> for name in funnel:
...     print(name)
...    
Jonathan
Michael
Samantha
Jessica
Daniel

A question that’s often asked but rarely answered is: Why is this version preferred over the other two? I’ll write another short post to answer this question soon as I want to keep these The Club posts short whenever possible. So, let me state just a few reasons (there are more) and then I’ll move on to my main topic for today.

  • It’s more readable

  • It’s more efficient (try timing the versions above using timeit—remove the print() calls first)

  • It’s less prone to errors and bugs

  • It works with a broader selection of data structures, not just sequences

While you wait for my follow-up post on this, you can read more about Python’s Iterator Protocol, iterables, and iterators here:

  • The Anatomy of a for Loop

  • Iterable: Python’s Stepping Stones

  • A One-Way Stream of Data • Iterators in Python

But let’s move on.

Let’s say you want to print out the names alongside each runner’s position. You’d like the following output:

1. Jonathan
2. Michael
3. Samantha
4. Jessica
5. Daniel

“Aha!” I’m often told by some learners, “This is when you need to use the for i in range(len(funnel)) idiom, since you need the index!”

Python’s for loop doesn’t explicitly use the index, so you don’t have access to the index within the for loop. Many revert to the non-Pythonic idioms for this.

But Python provides tools that let you stay within the pure Pythonic style. Python’s for loop needs an iterator—it will create one from the iterable you provide. All Python iteration needs iterators, not just for loops. Iterators are Python’s tool for any iteration.

And there are some bespoke iterators in Python that handle most of your iteration needs. I recently wrote a series about the itertools module. The itertools module contains many such tools. Here’s the series: The itertools Series.

But there are also two built-in tools that many forget, but are extremely useful. The first one is enumerate().

Here’s how you can use it to display the Parkrun results:

>>> for index, name in enumerate(funnel, start=1):
...     print(f”{index}. {name}”)
...    
1. Jonathan
2. Michael
3. Samantha
4. Jessica
5. Daniel
User's avatar

Continue reading this post for free, courtesy of Stephen Gruppetta.

Or purchase a paid subscription.
© 2026 Stephen Gruppetta · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture