Start learning free

LESSON 271 OF 673 · TUPLES, SORTING & BUILT-INS

Enumerate and Zip in Python: Loop with a Count

Lesson Read the full explanation

TL ; DR:

enumerate counts the items while you loop. zip walks two lists side by side.


fruits = ["apple", "kiwi", "plum"]
prices = [3, 1, 2]

for number, fruit in enumerate(fruits, start=1):
    print(number, fruit)     # 1 apple, then 2 kiwi, then 3 plum

for fruit, price in zip(fruits, prices):
    print(fruit, price)      # apple 3, then kiwi 1, then plum 2


Full lesson:

You have looped over indexes with range(len(meals)). Then meals[i] gave the item. Python has a shorter way to get both.

enumerate(lst) gives each item of lst together with a count. The loop unpacks each pair into two names, as you did with tuples.

for i, meal in enumerate(meals):
    print(i, meal)

The count starts at 0. To start at 1, write enumerate(meals, start=1). People read numbered lists from 1.

zip(a, b) walks two lists side by side. It pairs the first item of a with the first item of b. Then it pairs the second items, and so on. Each pair is a tuple.

for fruit, price in zip(fruits, prices):
    print(fruit, price)

zip stops at the end of the shorter list. The extra items are skipped, with no error.

The two work together. enumerate(zip(fruits, prices), start=1) gives a count and a pair each time. Put parentheses around the pair's two names.

for number, (fruit, price) in enumerate(zip(fruits, prices), start=1):
    print(f"{number}. {fruit} costs {price}")

Without the parentheses, Python stops with a ValueError. Each item has two parts, not three.


Your task

A quiz show keeps its players in the list players. Their points are in scores, in the same order.

First, print the players as a numbered list from 1, like 1. Ana. Use enumerate.

Then print each player with their points, like Ana has 12 points. Use zip.

Expected output:

1. Ana
2. Ben
3. Cleo
Ana has 12 points
Ben has 9 points
Cleo has 15 points
STEP 1 OF 4
    Ctrl + Enter to check

    PYTHON · TUPLES, SORTING & BUILT-INS

    Enumerate And Zip in Python, explained

    The problem with range(len(...))

    To get both the position and the item, you can loop over indexes: for i in range(len(meals)) and then read meals[i]. It works, but Python has a shorter way to get both.

    enumerate: items with a count

    enumerate(lst) gives each item of lst together with a count. Each step produces a pair, and the loop unpacks it into two names, as you do with tuples.

    meals = ["soup", "pasta"]
    for i, meal in enumerate(meals):
        print(i, meal)
    
    0 soup
    1 pasta
    

    The count starts at 0. To start at 1, write enumerate(meals, start=1), which is how people read numbered lists.

    You can use enumerate on any sequence, strings included: for i, ch in enumerate("hi") gives 0 h, then 1 i. It is also the usual way to find where something is. For example, a loop with for i, s in enumerate(scores) and an if s == 15 can print the index 2 of the score 15 in [12, 9, 15], with no range(len(...)) in sight.

    zip: two lists side by side

    zip(a, b) pairs the first item of a with the first item of b, then the second items, and so on. Each pair is a tuple.

    fruits = ["apple", "kiwi", "plum"]
    prices = [3, 1, 2]
    
    for fruit, price in zip(fruits, prices):
        print(fruit, price)
    
    apple 3
    kiwi 1
    plum 2
    

    zip stops at the end of the shorter list. The extra items are skipped without an error: list(zip([1, 2, 3], "ab")) is [(1, 'a'), (2, 'b')].

    The two lists should match in length. When they don't, zip doesn't warn you: list(zip(["x", "y", "z"], [1, 2])) is [('x', 1), ('y', 2)], and the third name quietly vanishes. If you meet a result that is shorter than you expected, check the lengths first.

    Zipped pairs are useful outside loops too: dict(zip(["a", "b"], [1, 2])) builds the dictionary {'a': 1, 'b': 2}, with the first list as the keys.

    Using both together

    enumerate(zip(fruits, prices), start=1) gives a count and a pair on every step, such as (1, ('apple', 3)). Put parentheses around the pair's two names when you unpack it:

    for number, (fruit, price) in enumerate(zip(fruits, prices), start=1):
        print(f"{number}. {fruit} costs {price}")
    
    1. apple costs 3
    2. kiwi costs 1
    3. plum costs 2
    

    Without the parentheses, for number, fruit, price in ... stops with ValueError: not enough values to unpack (expected 3, got 2). Each item has two parts, a number and a pair, not three.

    Reading the loop header

    The names in a for line must match the shape of what the iterator produces. enumerate(players) produces a pair, so two names fit. zip(a, b) produces a pair, so two names fit. enumerate(zip(a, b)) produces a number and a pair, so you write two names, with the second one a pair in parentheses. When a loop fails with a "values to unpack" error, count the parts the iterator gives and compare them with the names you wrote.

    The exercise, step by step

    A quiz show keeps its players in players and their points in scores, in the same order.

    1. Loop over enumerate(players, start=1) with the names number and player.
    2. Inside, print number, a dot, a space and player, like 1. Ana, with an f-string. Without start=1 the first line would be 0. Ana.
    3. Loop over zip(players, scores) with the names player and points.
    4. Inside, print a line like Ana has 12 points. Each pass sees one player and that player's points, so no index is needed.
    players = ["Ana", "Ben", "Cleo"]
    scores = [12, 9, 15]
    
    for number, player in enumerate(players, start=1):
        print(f"{number}. {player}")
    
    for player, points in zip(players, scores):
        print(f"{player} has {points} points")
    
    1. Ana
    2. Ben
    3. Cleo
    Ana has 12 points
    Ben has 9 points
    Cleo has 15 points
    

    Key takeaways

    • enumerate(lst, start=1) gives a count and an item; the count starts at 0 unless you set start.
    • zip(a, b) gives pairs, one item from each list, and stops at the shorter list.
    • To use both, write for number, (x, y) in enumerate(zip(a, b), start=1), keeping the parentheses.
    Keep going with Python500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free