If you've used another programming language before, you've probably used indexes while looping. Often when you're trying to loop with indexes in Python, you'll find that you actually care about counting upward as you're looping, not actual indexes.
Let’s say we have a variable, favorite_fruit
that points to a list of strings:
>>> favorite_fruits = ["jujube", "pear", "watermelon", "apple", "blueberry"]
We're looping over favorite_fruits
list here:
>>> n = 1
>>> for fruit in favorite_fruits:
... print(n, fruit)
... n += 1
...
1 jujube
2 pear
3 watermelon
4 apple
5 blueberry
We're printing out n
and fruit
(which represents each of our fruits).
The n
variable is a counter that we're keeping track of ourselves.
We start n
at 1
and we're incrementing it by 1
in each iteration of our loop.
range
of len
(not recommended)Instead of keeping track of counter ourselves, how about thinking in terms of indices and using range(len(favorite_fruits))
to grab each of the indexes of all the items in this list:
>>> favorite_fruits = ["jujube", "pear", "watermelon", "apple", "blueberry"]
>>>
>>> for i in range(len(favorite_fruits)):
... print(i+1, favorite_fruits[i])
...
1 jujube
2 pear
3 watermelon
4 apple
5 blueberry
We’re using i
to index the list manually and add one to each of these indices. This gives us the same result as before.
I wouldn't recommend doing this because the official Python style guide, PEP 8, recommends against it and instead of using range
of len
, there is usually one of two techniques you'll want to use.
We can entirely get rid of this and instead say for fruit in favorite_fruits
:
>>> favorite_fruits = ["jujube", "pear", "watermelon", "apple", "blueberry"]
>>>
>>> for fruit in favorite_fruits:
... print(fruit)
...
jujube
pear
watermelon
apple
blueberry
Here we've decided we don't need any counter in our loop at all.
If you do decide you actually need some kind of counting as you're looping, you'll want to use the built-in enumerate
function.
enumerate
returns both index and valuePython's enumerate
function is for counting upward as you loop over an iterable.
If we give enumerate
our iterable (our favorite_fruits
list in this case) and an optional start
value (which defaults to 0
):
>>> favorite_fruits = ["jujube", "pear", "watermelon", "apple", "blueberry"]
>>>
>>> for fruit in enumerate(favorite_fruits):
... print(fruit)
...
(0, 'jujube')
(1, 'pear')
(2, 'watermelon')
(3, 'apple')
(4, 'blueberry')
We'll get an iterable back that can be looped over to get tuples containing numbers counting upward along with each item in the iterable that we passed to enumerate
.
If we want to start counting at a different number, we can set the start
keyword argument when calling enumerate
:
>>> favorite_fruits = ["jujube", "pear", "watermelon", "apple", "blueberry"]
>>>
>>> for fruit in enumerate(favorite_fruits, start=1):
... print(fruit)
...
(1, 'jujube')
(2, 'pear')
(3, 'watermelon')
(4, 'apple')
(5, 'blueberry')
As we loop over enumerate
, it's gives us back two-item tuples that have two things inside them:
>>> favorite_fruits = ["jujube", "pear", "watermelon", "apple", "blueberry"]
>>>
>>> for item in enumerate(favorite_fruits, start=1):
... print(item)
...
(1, 'jujube')
(2, 'pear')
(3, 'watermelon')
(4, 'apple')
(5, 'blueberry')
It has a number that keeps track of counting upward and the actual item that it's grabbing from our favorite_fruits
list as it's looping over it .
We could index this tuple, using item[0]
and item[1]
, to grab these two values:
>>> favorite_fruits = ["jujube", "pear", "watermelon", "apple", "blueberry"]
>>>
>>> for item in enumerate(favorite_list, start=1):
... print(item[0], item[1])
...
1 jujube
2 pear
3 watermelon
4 apple
5 blueberry
But a better way is to use tuple unpacking to give each of these two values a name:
>>> favorite_fruits = ["jujube", "pear", "watermelon", "apple", "blueberry"]
>>>
>>> for item in enumerate(favorite_fruits, start=1):
... n, fruit = item
... print(n, item)
...
1 (1, 'jujube')
2 (2, 'pear')
3 (3, 'watermelon')
4 (4, 'apple')
5 (5, 'blueberry')
The number (n
) and that actual item (fruit
) are both important here. If something is important, it deserves a name.
Tuple unpacking is allowed anywhere an assignment happens, and that for
line has an assignment happening within it, so we can unpack at the same time as we loop:
>>> favorite_fruits = ["jujube", "pear", "watermelon", "apple", "blueberry"]
>>>
>>> for n, fruit in enumerate(favorite_fruits, start=1):
... print(n, fruit)
...
1 jujube
2 pear
3 watermelon
4 apple
5 blueberry
This is the most common way you'll see enumerate
used: you'll almost always see tuple unpacking used whenever enumerate
is used.
enumerate
to count upward while loopingIf you think you need to loop with indices, first, ask yourself a question: do I even need some kind of counter as I'm looping?
If you don't need a counter, just use a for
loop without any frills.
But if you do need to count upward while looping, you can use Python's built-in enumerate
function to help you do that counting.
Intro to Python courses often skip over some fundamental Python concepts.
Sign up below and I'll explain concepts that new Python programmers often overlook.
Unlike, JavaScript, C, Java, and many other programming languages we don't have traditional C-style for
loops.
Our for
loops in Python don't have indexes.
This small distinction makes for some big differences in the way we loop in Python.
To track your progress on this Python Morsels topic trail, sign in or sign up.
Intro to Python courses often skip over some fundamental Python concepts.
Sign up below and I'll share ideas new Pythonistas often overlook.