Python’s enumerate() function demystified

Hey there,

Python’s enumerate function is a mythical beast—

It’s hard to summarize its purpose and usefulness in a single sentence.

And yet, it’s a super useful feature that many beginners and even intermediate Pythonistas are blissfully unaware of.

Basically, enumerate() allows you to loop over a collection of items while keeping track of the current item’s index in a counter variable.

Let’s take a look at a quick example:

names = ['Bob', 'Alice', 'Guido']
for index, value in enumerate(names):
    print(f'{index}: {value}')


This produces the following output:
 

0: Bob
1: Alice
2: Guido


As you can see, this iterated over the names list and generated an index for each element by increasing a counter variable starting at zero.

Now why is keeping a running index with the enumerate function useful?

I noticed that new Python developers coming from a C or Java background sometimes use the following range(len(...)) antipattern to keep a running index while iterating over a list with a for-loop:
 

# HARMFUL: Don't do this
for i in range(len(my_items)):
    print(i, my_items[i])


By using the enumerate function skillfully, like I showed you in the “names” example above, you can make this looping construct much more “Pythonic” and idiomatic.

You see, there’s usually no need to generate element indexes manually in Python—you simply leave all of this work to the enumerate function.

And as a result your code will be easier to read and less vulnerable to typos.

Another useful feature is the ability to choose the starting index for the enumeration. 

The enumerate() function accepts an optional argument which allows you to set the initial value for its counter variable:

names = ['Bob', 'Alice', 'Guido']
for index, value in enumerate(names, 1):
    print(f'{index}: {value}')


In the above example I changed the function call to enumerate(names, 1) and the extra 1 argument now starts the index at one instead of zero:

1: Bob
2: Alice
3: Guido


And voilà, this is how you switch from zero-based indexing to starting with index 1 (or any other int, for that matter) using Python’s enumerate() function.

You might be wondering how the enumerate function works behind the scenes—so let's talk about that for a bit: 

Part of it’s magic lies in the fact that enumerate is implemented as a Python iterator.

This means that element indexes are generated lazily (one by one, just-in-time), which keeps memory use low and keeps this construct so fast.

Let’s play with some more code to demonstrate what I mean:
 

>>> names = ['Bob', 'Alice', 'Guido']
>>> enumerate(names)
<enumerate object at 0x1057f4120>


In the above code snippet I set up the same enumeration you’ve already seen in the previous examples.

But instead of immediately looping over the result of the  enumerate call I’m just displaying the returned object on the Python console.

As you can see, it’s an “enumerate object.”

This is the actual iterator.

And like I said, it generates its output elements lazily and one by one when they’re requested.

In order to retrieve those “on demand” elements so we can inspect them, I’m going to call the built-in list() function on the iterator:
 

>>> list(enumerate(names))
[(0, 'Bob'), (1, 'Alice'), (2, 'Guido')]


For each element in the input list (names) the iterator returned by enumerate() produces a tuple of the form (index, element).

In your typical for-in loop you’ll use this to your advantage by leveraging Python’s data structure unpacking feature:
 

for index, element in enumerate(iterable):
    # ...

And there you have it—enumerate() is awesome!

Let's do a quick recap:

    1. "enumerate()" is a built-in function of Python. You use it to loop over an iterable with an automatic running index generated by a counter variable.

    2. The counter starts at 0 by default, but you can set it to any integer.

    3. enumerate was added to Python starting at version 2.3 with the implementation of PEP 279.

    4. Python’s enumerate function helps you write more Pythonic and idiomatic looping constructs that avoid the use of clunky and error-prone manual indexing.


Happy Pythoning!

— Dan Bader

Older messages

[Python Dependency Pitfalls] "Re-inventing the wheel" disease

Wednesday, February 17, 2021

Hey there, PyPI, the Python packaging repository, now contains more than 100000 third-party packages in total. That's an *overwhelming* number of packages to choose from... And this feeling of

[Python Dependency Pitfalls] What dev managers expect from Python candidates

Monday, February 15, 2021

Hey there, My friend Og is a senior manager at Red Hat and works with a large team of developers and quality engineers using Python. I got to pick his brain on what he thought were the most important

[Python Dependency Pitfalls] How to set the world on fire

Sunday, February 14, 2021

Hey there, #1 on my list of dependency management pitfalls is there for a good reason: It lead to a single developer causing mayhem and breaking thousands of open-source projects around the world in

[PythonistaCafe] Q&A

Saturday, February 13, 2021

Hey there, At this point you should have a pretty good idea of what PythonistaCafe is about and what makes it special. In this email I want to answer some common questions that I get asked about the

A story about crushed coding dreams

Saturday, February 13, 2021

Hey there, The other day I read this story of a fledgling Python coder named Seth on Reddit: Seth's been learning Python for 5 months, and things have been "hit and miss" for a while now.

You Might Also Like

Import AI 399: 1,000 samples to make a reasoning model; DeepSeek proliferation; Apple's self-driving car simulator

Friday, February 14, 2025

What came before the golem? ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏

Defining Your Paranoia Level: Navigating Change Without the Overkill

Friday, February 14, 2025

We've all been there: trying to learn something new, only to find our old habits holding us back. We discussed today how our gut feelings about solving problems can sometimes be our own worst enemy

5 ways AI can help with taxes 🪄

Friday, February 14, 2025

Remotely control an iPhone; 💸 50+ early Presidents' Day deals -- ZDNET ZDNET Tech Today - US February 10, 2025 5 ways AI can help you with your taxes (and what not to use it for) 5 ways AI can help

Recurring Automations + Secret Updates

Friday, February 14, 2025

Smarter automations, better templates, and hidden updates to explore 👀 ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏ ͏

The First Provable AI-Proof Game: Introducing Butterfly Wings 4

Friday, February 14, 2025

Top Tech Content sent at Noon! Boost Your Article on HackerNoon for $159.99! Read this email in your browser How are you, @newsletterest1? undefined The Market Today #01 Instagram (Meta) 714.52 -0.32%

GCP Newsletter #437

Friday, February 14, 2025

Welcome to issue #437 February 10th, 2025 News BigQuery Cloud Marketplace Official Blog Partners BigQuery datasets now available on Google Cloud Marketplace - Google Cloud Marketplace now offers

Charted | The 1%'s Share of U.S. Wealth Over Time (1989-2024) 💰

Friday, February 14, 2025

Discover how the share of US wealth held by the top 1% has evolved from 1989 to 2024 in this infographic. View Online | Subscribe | Download Our App Download our app to see thousands of new charts from

The Great Social Media Diaspora & Tapestry is here

Friday, February 14, 2025

Apple introduces new app called 'Apple Invites', The Iconfactory launches Tapestry, beyond the traditional portfolio, and more in this week's issue of Creativerly. Creativerly The Great

Daily Coding Problem: Problem #1689 [Medium]

Friday, February 14, 2025

Daily Coding Problem Good morning! Here's your coding interview problem for today. This problem was asked by Google. Given a linked list, sort it in O(n log n) time and constant space. For example,

📧 Stop Conflating CQRS and MediatR

Friday, February 14, 2025

​ Stop Conflating CQRS and MediatR Read on: m​y website / Read time: 4 minutes The .NET Weekly is brought to you by: Step right up to the Generative AI Use Cases Repository! See how MongoDB powers your