- Iterate dictionary (key and value) with for loop in Python
- Iterate dictionary keys: keys()
- Iterate dictionary values: values()
- Iterate dictionary key-value pairs: items()
- Related Categories
- Related Articles
- Эффективный обход словарей в цикле в Python
- Что будет если просто попытаться обойти словарь в цикле?
- Как обойти в цикле ключи словаря?
- Как обойти в цикле значения словаря?
- Как обойти в цикле и ключи, и значения словаря?
- Заключение
- Ссылки
Iterate dictionary (key and value) with for loop in Python
In Python, to iterate through a dictionary ( dict ) with a for loop, use the keys() , values() , and items() methods. You can also get a list of all keys and values in the dictionary with those methods and list() .
Consider the following dictionary as an example:
You can iterate keys by directly using the dictionary object in a for loop.
for k in d: print(k) # key1 # key2 # key3
See the following article for the basics of for loops in Python.
Iterate dictionary keys: keys()
As mentioned above, you can iterate dictionary keys by directly using the dictionary object, but you can also use keys() . The result is the same, but keys() may clarify the intent to the reader of the code.
for k in d.keys(): print(k) # key1 # key2 # key3
The keys() method returns dict_keys , which can be converted to a list with list() .
keys = d.keys() print(keys) print(type(keys)) # dict_keys(['key1', 'key2', 'key3']) # k_list = list(d.keys()) print(k_list) print(type(k_list)) # ['key1', 'key2', 'key3'] #
You can use dict_keys to perform set operations. See the following article for details.
Iterate dictionary values: values()
To iterate dictionary values, use the values() method.
for v in d.values(): print(v) # 1 # 2 # 3
The values() method returns dict_values , which can be converted to a list with list() .
values = d.values() print(values) print(type(values)) # dict_values([1, 2, 3]) # v_list = list(d.values()) print(v_list) print(type(v_list)) # [1, 2, 3] #
Iterate dictionary key-value pairs: items()
To iterate dictionary key-value pairs, use the items() method.
for k, v in d.items(): print(k, v) # key1 1 # key2 2 # key3 3
You can also receive the key-value pairs as a tuple of (key, value) :
for t in d.items(): print(t) print(type(t)) print(t[0]) print(t[1]) print('---') # ('key1', 1) # # key1 # 1 # --- # ('key2', 2) # # key2 # 2 # --- # ('key3', 3) # # key3 # 3 # ---
The items() method returns dict_items , which can be converted to a list with list() .
items = d.items() print(items) print(type(items)) # dict_items([('key1', 1), ('key2', 2), ('key3', 3)]) # i_list = list(d.items()) print(i_list) print(type(i_list)) # [('key1', 1), ('key2', 2), ('key3', 3)] # print(i_list[0]) print(type(i_list[0])) # ('key1', 1) #
You can also use dict_items to perform set operations. See the following article for details.
Related Categories
Related Articles
- Unpack and pass list, tuple, dict to function arguments in Python
- Merge multiple dictionaries and add items to a dictionary in Python
- Swap dictionary keys and values in Python
- Get value from dictionary by key with get() in Python
- Get maximum/minimum values and keys in Python dictionaries
- Add an item if the key does not exist in dict with setdefault in Python
- Create a dictionary in Python (<>, dict(), dict comprehensions)
- Sort a list of dictionaries by the value of the specific key in Python
- Change dictionary key in Python
- Get key from value in dictionary in Python
- Remove an item from a dictionary in Python (clear, pop, popitem, del)
- Pretty-print with pprint in Python
- Check if key/value exists in dictionary in Python
- Set operations on multiple dictionary keys in Python
- Extract specific key values from a list of dictionaries in Python
Эффективный обход словарей в цикле в Python
Словарь (dictionary, dict) — это ассоциативный массив, который позволяет сохранять значения по ключам.
Это очень важная, даже можно сказать основополагающая структура данных, которая используется в Python под капотом буквально повсюду: модули, классы, объекты, locals() , globals() — все это так или иначе работает лишь благодаря словарям.
Кроме того, словарь отлично подходит для решения множества прикладных задач, обладает хорошей вычислительной сложностью операций, так что и в вашем коде, наверняка, словари будут встречаться достаточно часто.
В Python большое внимание уделяется циклам. Правильно написанный заголовок цикла содержит много ценной информации: по чему итерируемся и какие данные будут использоваться в теле цикла. Это помогает читателю понять (или хотя бы предположить), что именно будет производиться в теле цикла, даже не смотря в него. Неправильно написанный цикл, который не выражает напрямую задумку автора, наоборот, сбивает читателя с толку и заставляет читать код целиком, возможно, даже не один раз.
Есть несколько способов обойти словарь в цикле. Очень важно научиться выбирать наиболее подходящий.
Что будет если просто попытаться обойти словарь в цикле?
Объявим словарь с отношением различных валют к российскому рублю, который нам по какой-то причине нужно обойти:
currencies = "rub": 1, "usd": 69.78, "eur": 78.28>
Самый очевидный вариант обхода словаря — это попытаться напрямую запустить цикл for по объекту словаря, так же как мы делаем это со списками, кортежами, строками и любыми другими итерируемыми объектами.
for something in currencies: print(something)
Словарь и правда поддерживает протокол итераций, но словарь не так прост, как другие объекты, которые мы упомянули выше. Словарь состоит из нескольких частей, ведь словарь — это отношение между ключами и значениями. Получается, что теоретически цикл по словарю может получать либо ключи, либо значения, либо пары (ключ, значение). Попробуете угадать, что же именно выведет код выше?
То есть обход словаря в цикле будет возвращать только ключи этого словаря.
Пожалуй, задать такое поведение по умолчанию — это очень логичное решение со стороны разработчиков Python. Было бы намного внезапнее, если бы цикл по словарю получал значения. Вариант с кортежами (ключ, значение) в качестве поведения по умолчанию мне кажется не таким уж плохим, но имеем то, что имеем.
Есть куча задач, в которых нужно обойти лишь ключи словаря, и это отличное решение для таких задач. У этого способа есть один крупный недостаток: нужно знать как работают словари. По коду совершенно неясно, что будет обходиться в цикле — ключи, значения или пары, а читатель может либо этого не знать, либо забыть, и в итоге неправильно интерпретировать код. Поэтому во избежание неоднозначности даже для обхода ключей словаря я рекомендую использовать следующий способ.
Как обойти в цикле ключи словаря?
Давайте представим, что нам нужно нарисовать какую-нибудь таблицу с валютами, и для создания шапки этой таблицы нужно получить список всех валют. Значения словаря нас не интересуют, только ключи.
У словаря есть метод .keys() , который возвращает представление словаря (dict view), возвращающее ключи.
Что такое представление словаря? Это некий объект, который предоставляет доступ к данным в словаре, либо к части этих данных, и работает по следующим принципам:
- не копирует содержимое словаря, а обращается к нему динамически, на больших словарях это здорово экономит память и улучшает скорость работы программы;
- если словарь изменяется, то эти изменения автоматически становятся доступными и через представление словаря;
- не является списком, не поддерживает извлечение элементов по индексам;
- является итерируемым объектом, можно использовать в циклах сколько угодно раз.
Создадим такое представление словаря по ключам:
dict_keys = currencies.keys() print(dict_keys) # dict_keys(['rub', 'usd', 'eur'])
Давайте добавим новый ключ в словарь:
currencies["jpy"] = 0.65 print(dict_keys) # dict_keys(['rub', 'usd', 'eur', 'jpy'])
Как видите, созданное ранее представление словаря обновилось автоматически, когда обновился его словарь.
Обратите внимание, что представление словаря — это не список, а совершенно другой объект. Представление словаря не поддерживает извлечение значений по индексам:
dict_keys[0] # Traceback (most recent call last): # File "", line 1, in # TypeError: 'dict_keys' object is not subscriptable
Зато представление словаря является итерируемым объектом и его без проблем можно обходить при помощи цикла:
for key in currencies.keys(): print(key) # rub # usd # eur # jpy
Результат тот же самый, что и в предыдущем способе обхода словаря, но в этот раз явно видно, что в цикле будут обрабатываться только ключи словаря.
Обратите внимание, что если в цикле вам нужны не только ключи словаря, но и значения, то обходить словарь таким образом — не самое эффективное решение. Смотрите дальше, как можно обойти словарь, чтобы получать и ключи, и значения.
Как обойти в цикле значения словаря?
По аналогии с ключами, из словаря можно извлечь только значения, без ключей. Это делается через метод словарей .values() , который возвращает представление словаря, содержащее только значения.
Это представление работает по тем же правилам, что и возвращаемое методом .keys() .
Вот как можно обойти в цикле только значения словаря, без ключей:
for value in currencies.values(): print(value) # 1 # 69.78 # 78.28 # 0.65
По значениям словаря уже невозможно получить ключи (ну, вообще можно попытаться, но для этого потребуется полный перебор словаря, и не факт, что ключи будут восстановлены правильно). Этот способ подойдёт только если в цикле используются исключительно значения словаря, а ключи не нужны.
Как обойти в цикле и ключи, и значения словаря?
Пожалуй, это самый распространённый случай. Во многих задачах, где выполняется обход словаря, в цикле используются и ключи, и соответствующие им значения.
Специально для этого у словарей есть метод .items() , который возвращает представление словаря, содержащее кортежи из двух элементов, вида (ключ, значение).
Это представление работает по точно таким же правилам, как .keys() и .values() . Единственное отличие этого представления от предыдущих состоит в том, что оно возвращает не единичные значения, а кортежи из двух значений.
for item in currencies.items(): # item — это кортеж (ключ, значение) print(item[0], item[1]) # rub 1 # usd 69.78 # eur 78.28 # jpy 0.65
В Python есть возможность распаковывать итерируемые объекты, такие как кортежи, в различные переменные. Давайте на примере посмотрим как это работает:
point = (1, 2, 3) x, y, z = point print(x) # 1 print(y) # 2 print(z) # 3
Таким образом можно распаковывать последовательности любого размера. Это намного проще, чем извлекать значения по индексам и присваивать в отдельные переменные. Этот приём можно использовать практически в любом месте программы, в том числе и в заголовке цикла.
Вот так можно обойти ключи и значения словаря, сохраняя ключ и значение в разные переменные прямо в заголовке цикла при помощи распаковки кортежа:
for key, value in currencies.items(): print(key, value) # rub 1 # usd 69.78 # eur 78.28 # jpy 0.65
Заключение
При обходе словаря стоит руководствоваться следующей логикой:
- если в цикле используются и ключи, и значения словаря, то нужно использовать метод .items() ;
- если в цикле используются только значения словаря, а ключи не важны, то нужно использовать метод .values() ;
- если в цикле нужны ключи словаря и ничего больше, то нужно использовать метод .keys() .
Идеоматичный код проще читается и, как правило, работает быстрее.
Посмотрите запись классического выступления Реймонда Хеттингера, где он рассказывает про написание идеоматичного код. Много внимания уделяется циклам и словарям.
Обратите внимание, что это запись выступления от 2013 года, когда ещё вовсю был в ходу Python 2. В выступлении часто сравнивается Python 2 и Python 3. Не запутайтесь.
Если понравилась статья, то подпишитесь на уведомления о новых постах в блоге, чтобы ничего не пропустить!
Ссылки
- очень подробный разбор по обходу словарей на RealPython;
- документация про представления словарей;
- и, конечно же, посмотрите выступление Реймонда Хеттингера, обожаю этого чувака.