Iterating over a dict
In the previous lesson we read the price board one row at a time: we found pear and read 70. Sometimes you need the whole board at once. For example, in the morning the seller copies the prices into a notebook. They go from top to bottom and write down the name and the price of each row.
A for loop over a dict does the same. On its own, it goes through the keys, that is, the names in the rows. You can read each value by its key inside the loop, but a dict can hand out whole pairs. The items method gives "key—value" pairs, and unpacking in the for header splits each one into two variables:
prices = {"pear": 70, "plum": 40, "kiwi": 90}
for name in prices:
print(name, end=" ") # pear plum kiwi
print()
for name, price in prices.items():
print(f"{name}={price}", end=" ") # pear=70 plum=40 kiwi=90Let's see what the program prints:
- The first loop,
for name in prices, gets only the keys and printspear plum kiwi. print()with no arguments ends the line, so the second loop starts printing on a new one.- The second loop,
for name, price in prices.items(), gets the pairs and splits each one intonameandprice. - The f-string joins them with
=, which givespear=70 plum=40 kiwi=90.
keys, values and items
A dict has three methods for looping. Each hands out its own part of the board.
items
Each pair from items is a tuple of a key and a value. The loop unpacks it, like the tuples from enumerate. This is the most common way to loop over a dict when you need both the names and the prices.
keys
The keys method hands out the keys. The loop for name in prices.keys() goes through the same as for name in prices, so keys is usually left out in a loop.
values
The values method hands out the values without the keys. So sum(prices.values()) adds up the prices and gives 200, the total price of the products. The check "pear" in prices looks among the keys, and 70 in prices.values() among the values.
Special objects, not lists
These three methods return not lists but special objects that read the data straight from the dict. What you can do with them:
- loop over them with
for; - pass them to
sum,sortedandlist; - check for an element in them with
in.
They have no indices: prices.keys()[0] raises a TypeError. If you need a list, wrap the result in list: list(prices.keys()) gives ['pear', 'plum', 'kiwi']. The function sorted(prices) returns a list of the keys in alphabetical order: ['kiwi', 'pear', 'plum'].
Key order
A dict remembers insertion order, the way the board remembers the order in which the seller wrote the rows. A loop goes in the order in which the keys appeared. Two rules apply here:
- writing to an existing key changes the value but not the key's place;
- a key that is deleted and added again goes to the end.
d = {"b": 1, "a": 2}
d["c"] = 3
d["b"] = 10
print(list(d)) # ['b', 'a', 'c']
del d["b"]
d["b"] = 4
print(list(d)) # ['a', 'c', 'b']Let's go through it step by step:
- The dict starts with the keys
"b"and"a", then"c"goes to the end. d["b"] = 10changes the value, and"b"stays first:['b', 'a', 'c'].del d["b"]erases the whole row.d["b"] = 4writes it again, and it goes to the end:['a', 'c', 'b'].
list(d) gives the same as list(d.keys()): a list of the keys in order. Insertion order has nothing to do with the alphabet or the size of the values: only sorted returns the list in alphabetical order. In return, the loop order is predictable: on every run, the program prints the pairs in the same order.
Interviewers like to ask this: "Does a dict keep its order?" The answer: yes, the language has guaranteed insertion order since Python 3.7. In older versions the loop order was not promised, so older articles may say the opposite.
Common mistake
Pairs are deleted right inside a loop over the dict:
stock = {"apple": 3, "pear": 0, "plum": 0}
for name in stock:
if stock[name] == 0:
del stock[name] # ✗RuntimeError: dictionary changed size during iterationAfter deleting "pear", the loop tries to take the next key and stops with the error. While a loop runs over a dict, its number of pairs must not change: no deleting keys and no adding new ones.
Loop over a copy of the keys—for name in list(stock):—and then deleting from the dict itself does not break the loop. Changing the value of an existing key during the loop is allowed: the size of the dict does not change.
Key points
for k in dgoes through the keys, andfor k, v in d.items()through the "key—value" pairs.keys,valuesanditemsreturn objects with no indices, andlistmakes a list of them.- A dict keeps insertion order, and only
sortedputs the keys in alphabetical order. - Do not delete or add keys in a loop over the dict itself; loop over
list(d).
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.