Перебор словарей с использованием циклов for
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
...
Как Python распознает, что ему нужно только прочитать ключ из словаря? Является ли ключ специальным словом в Python? Или это просто переменная?
Это не просто forпетли. Важное слово здесь - «повторение».
Словарь - это отображение ключей на значения:
d = {'x': 1, 'y': 2, 'z': 3}
Каждый раз, когда мы перебираем его, мы перебираем ключи. Имя переменной keyпредназначено только для описания, и оно вполне подходит для этой цели.
Это происходит в понимании списка:
>>> [k for k in d]
['x', 'y', 'z']
Это происходит, когда мы передаем словарь в список (или любой другой объект типа коллекции):
>>> list(d)
['x', 'y', 'z']
Итерация Python заключается в том, что в контексте, где это необходимо, он вызывает __iter__метод объекта (в данном случае словарь), который возвращает итератор (в данном случае, объект keyiterator):
>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>
Мы не должны сами использовать эти специальные методы, вместо этого использовать соответствующую встроенную функцию для вызова iter:
>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>
У итераторов есть __next__метод, но мы вызываем его с помощью встроенной функции next:
>>> next(key_iterator)
'x'
>>> next(key_iterator)
'y'
>>> next(key_iterator)
'z'
>>> next(key_iterator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Когда итератор исчерпан, он повышается StopIteration. Это то, как Python знает, как выйти из forцикла, или из списка, или из выражения генератора, или из любого другого итеративного контекста. Когда итератор поднимается, StopIterationон всегда поднимает его - если вы хотите повторить снова, вам нужен новый.
>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']
Возвращаясь к диктату
Мы видели повторения диктов во многих контекстах. Что мы видели, так это то, что каждый раз, когда мы перебираем слова, мы получаем ключи. Вернуться к исходному примеру:
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
Если мы изменим имя переменной, мы все равно получим ключи. Давай попробуем:
>>> for each_key in d:
... print(each_key, '=>', d[each_key])
...
x => 1
y => 2
z => 3
Если мы хотим перебрать значения, нам нужно использовать .valuesметод dicts или для обоих вместе .items:
>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]
В приведенном примере было бы более эффективно перебирать элементы вроде этого:
for a_key, corresponding_value in d.items():
print(a_key, corresponding_value)
Но для академических целей пример вопроса просто отлично.