Enumerate in Python: iterate with index easily

Discover the enumerate function in Python: syntax, practical examples and best practices for iterating over sequences with an index counter.
8 min read
Believemy logo

When you loop through a sequence in Python, you often need to know not only the current element but also its position in the sequence.

This is exactly what the enumerate() function allows.

This built-in function is one of the most elegant and widely used tools by Python developers. If you want to master these essential features, our complete Python course will guide you step by step in your learning.

 

Definition of enumerate

The enumerate() function is a built-in Python function that takes an iterable object as input and returns an enumerate object. This object produces pairs consisting of a counter (index) and the values obtained by iterating over the original iterable.

The basic syntax is as follows:

PYTHON
enumerate(iterable, start=0)

The parameters are:

  • iterable: any iterable object (list, tuple, string, dict, etc.)
  • start (optional): the starting value of the counter, default is 0

The function returns an enumerate object which is itself an iterator. Each element produced is a tuple containing the index and the corresponding value.

Good to know

The enumerate() function does not create a new list in memory. It generates the (index, value) pairs on demand, making it very memory efficient.

 

Why use enumerate?

Before discovering enumerate(), many developers use a less elegant approach to get the index during iteration. Let's compare the different methods:

The traditional approach (to avoid)

PYTHON
# Method 1: using range and len
fruits = ['apple', 'banana', 'cherry', 'orange']

for i in range(len(fruits)):
    print(f"Index {i}: {fruits[i]}")

This approach works, but it is less readable and more error-prone. You must manually access the element via its index.

 

The approach with a manual counter (to avoid)

PYTHON
# Method 2: manual counter
fruits = ['apple', 'banana', 'cherry', 'orange']

index = 0
for fruit in fruits:
    print(f"Index {index}: {fruit}")
    index += 1

This method is slightly better because you access the element directly, but you must manage the counter manually.

 

PYTHON
# Method 3: enumerate (the best approach)
fruits = ['apple', 'banana', 'cherry', 'orange']

for index, fruit in enumerate(fruits):
    print(f"Index {index}: {fruit}")

With enumerate(), the code is more concise, more readable, and less error-prone. This is the idiomatic way to loop through a sequence with its index in Python.

 

Practical usage examples

Starting the counter at a value other than 0

By default, the counter starts at 0, but you can specify a different starting value with the start parameter:

PYTHON
# Numbering a list starting from 1
students = ['Alice', 'Bob', 'Charlie', 'Diana']

print("Student list:")
for number, student in enumerate(students, start=1):
    print(f"{number}. {student}")

# Result:
# 1. Alice
# 2. Bob
# 3. Charlie
# 4. Diana

This feature is particularly useful for displaying numbered lists in a natural way for the user.

 

Usage with strings

Strings are iterable in Python. You can therefore use enumerate() to loop through each character with its index:

PYTHON
# Finding the positions of a character in a string
word = "programming"
search_character = 'g'

positions = []
for index, character in enumerate(word):
    if character == search_character:
        positions.append(index)

print(f"The character '{search_character}' is found at positions: {positions}")
# Result: The character 'g' is found at positions: [3, 10]

 

Modifying list elements based on their position

When you need to modify elements of a list based on their position, enumerate() is essential:

PYTHON
# Double values at even positions
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

for index, value in enumerate(numbers):
    if index % 2 == 0:  # Even position (0, 2, 4, ...)
        numbers[index] = value * 2

print(numbers)
# Result: [2, 2, 6, 4, 10, 6, 14, 8, 18, 10]

 

Enumerate with list comprehensions

You can combine enumerate() with list comprehensions to write even more concise code:

PYTHON
# Create a list of tuples (index, squared_value)
numbers = [1, 2, 3, 4, 5]

result = [(i, n**2) for i, n in enumerate(numbers)]
print(result)
# Result: [(0, 1), (1, 4), (2, 9), (3, 16), (4, 25)]

# Filter and keep only elements at even indices
even_elements = [value for index, value in enumerate(numbers) if index % 2 == 0]
print(even_elements)
# Result: [1, 3, 5]

 

Enumerate with dictionaries

Although dict have their own key system, you can use enumerate() to number entries when displaying:

PYTHON
# Display a dictionary with numbers
people = {
    'alice': 25,
    'bob': 30,
    'charlie': 35
}

print("List of people and their ages:")
for number, (name, age) in enumerate(people.items(), start=1):
    print(f"{number}. {name.capitalize()} is {age} years old")

# Result:
# 1. Alice is 25 years old
# 2. Bob is 30 years old
# 3. Charlie is 35 years old

 

File processing with enumerate

When reading a file, enumerate() is very useful to know the line number:

PYTHON
# Display file content with line numbers
with open('my_file.txt', 'r') as file:
    for line_number, content in enumerate(file, start=1):
        print(f"Line {line_number}: {content.strip()}")

This technique is particularly useful for debugging or generating error reports.

 

Internal workings of enumerate

To better understand enumerate(), let's see how you could implement this function yourself:

PYTHON
def my_enumerate(iterable, start=0):
    """Simplified implementation of enumerate"""
    counter = start
    for element in iterable:
        yield counter, element
        counter += 1

# Usage
fruits = ['apple', 'banana', 'cherry']

for index, fruit in my_enumerate(fruits):
    print(f"{index}: {fruit}")

This implementation uses the yield keyword to create a generator, which makes the function memory efficient, just like the real enumerate() function.

Good to know

The object returned by enumerate() is an iterator. This means it can only be traversed once. If you need to traverse it multiple times, convert it to a list first.

 

Converting the enumerate object

You can convert the enumerate object to different data structures:

PYTHON
colors = ['red', 'green', 'blue']

# Convert to list of tuples
enumerate_list = list(enumerate(colors))
print(enumerate_list)
# Result: [(0, 'red'), (1, 'green'), (2, 'blue')]

# Convert to dictionary
enumerate_dict = dict(enumerate(colors))
print(enumerate_dict)
# Result: {0: 'red', 1: 'green', 2: 'blue'}

# Convert to tuple of tuples
enumerate_tuple = tuple(enumerate(colors))
print(enumerate_tuple)
# Result: ((0, 'red'), (1, 'green'), (2, 'blue'))

 

Enumerate with zip

You can combine enumerate() with zip() to loop through multiple sequences simultaneously while keeping an index:

PYTHON
names = ['Alice', 'Bob', 'Charlie']
scores = [95, 87, 92]

print("Student rankings:")
for position, (name, score) in enumerate(zip(names, scores), start=1):
    print(f"Position {position}: {name} with {score} points")

This combination is extremely powerful for processing tabular data or pairs of values.

 

Best practices with enumerate

Name your variables explicitly

Use descriptive variable names rather than i and v:

PYTHON
# Less readable
for i, v in enumerate(users):
    print(f"{i}: {v}")

# More readable
for index, user in enumerate(users):
    print(f"{index}: {user}")

 

Use start=1 for user displays

End users typically expect numbering to start at 1:

PYTHON
# For user display
for number, option in enumerate(options, start=1):
    print(f"{number}. {option}")

 

Don't use enumerate if you don't need the index

If you don't use the index, a simple for loop is preferable:

PYTHON
# Unnecessary
for _, fruit in enumerate(fruits):
    print(fruit)

# Preferable
for fruit in fruits:
    print(fruit)

 

Prefer enumerate over range(len())

Systematically replace the range(len()) pattern with enumerate():

PYTHON
# To avoid
for i in range(len(my_list)):
    print(i, my_list[i])

# To prefer
for i, element in enumerate(my_list):
    print(i, element)
Warning

Don't forget that the enumerate object is a single-use iterator. If you convert it to a list for reuse, you lose the memory efficiency advantage.

 

Advanced use cases

Creating interactive menus

PYTHON
def display_menu(options):
    """Display a numbered menu and return the user's choice"""
    print("\n=== MENU ===")
    for number, option in enumerate(options, start=1):
        print(f"{number}. {option}")
    
    while True:
        try:
            choice = int(input("\nYour choice: "))
            if 1 <= choice <= len(options):
                return options[choice - 1]
            print("Invalid choice, please try again.")
        except ValueError:
            print("Please enter a valid number.")

# Usage
menu_options = ['New file', 'Open', 'Save', 'Quit']
user_choice = display_menu(menu_options)

 

Finding an element and returning its index

PYTHON
def find_first_index(lst, condition):
    """Find the index of the first element satisfying the condition"""
    for index, element in enumerate(lst):
        if condition(element):
            return index
    return -1

# Usage
numbers = [1, 3, 5, 8, 10, 12]
even_index = find_first_index(numbers, lambda x: x % 2 == 0)
print(f"First even number at index: {even_index}")  # Result: 3

 

Frequently asked questions

Question

What is the difference between enumerate() and range(len())?

enumerate() is more Pythonic and more readable than range(len()). With enumerate, you get both the index and the element directly in the loop, without having to manually access the element via its index. It is also less error-prone because you don't have to manage index access yourself.

 

Question

Can enumerate be used with any iterable?

Yes, enumerate() works with all iterable objects in Python: lists, tuples, strings, dictionaries, sets (set), files, generators, and any object implementing the iteration protocol. It is a very versatile function.

 

Question

Is the enumerate object reusable?

No, the object returned by enumerate() is an iterator that can only be traversed once. If you need to traverse the data multiple times, you must either call enumerate() again on the original iterable, or convert the result to a list with list(enumerate(...)) during the first iteration.

 

Question

How can I learn to master enumerate and other Python functions?

To master enumerate() and all Python features, regular practice is essential. You can deepen your knowledge with our Python course on Believemy which covers in detail built-in functions, best practices, and advanced techniques to become an effective Python developer.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.