Как выполнить итерацию по словарю в Python - 1 часть
Просто Python | Data science | ML | AIСловари являются одной из наиболее важных и полезных встроенных структур данных в Python. Они повсюду и являются фундаментальной частью самого языка. В своем коде вы будете использовать словари для решения многих задач программирования, которые могут потребовать выполнения итераций по имеющемуся словарю. В этом руководстве вы глубоко погрузитесь в то, как выполнять итерации по словарю в Python.
В этом руководстве вы будете:
- Познакомьтесь с некоторыми основными функциями словарей
- Выполните итерацию по словарю на Python, используя различные методы и инструменты
- Преобразуйте свои словари во время выполнения итерации по ним в Python
- Изучите другие инструменты и методы, которые облегчают итерацию по словарю
Чтобы извлечь максимальную пользу из этого руководства, вы должны иметь базовое представление о словарях Python, знать, как использовать for циклы Python, и быть знакомым с понятиями. Знание других инструментов, таких как встроенные функции map() и filter() и модули itertools и collections, также является плюсом.

Как выполнить итерацию по словарю в Python
Содержание
- Начало работы со словарями Python
- Понимание того, как выполнять итерации по словарю в PythonПрямой обход словаря
- Перебор элементов словаря: метод .items()
- Выполнение итерации по ключам словаря: метод .keys()
- Переход по значениям словаря: метод .values()
- Изменение значений словаря во время итерации
- Безопасное удаление элементов из словаря во время итерации
- Выполнение итерации по словарям: для примеров циклаФильтрация элементов по их значению
- Выполнение вычислений с ключами и значениями
- Замена ключей и значений с помощью итерации
- Выполнение итерации по словарям: примеры пониманияФильтрация элементов по их значению: пересмотрено
- Замена ключей и значений с помощью итерации: пересмотрено
Начало работы со словарями Python
Словари являются краеугольным камнем Python. Многие аспекты языка построены вокруг словарей. Модули, классы, объекты, globals()и locals() - все это примеры того, как словари глубоко встроены в реализацию Python.
Вот как в официальной документации Python определяется словарь:
Ассоциативный массив, где произвольные ключи сопоставляются со значениями. Ключами может быть любой объект с__hash__()и__eq__()методами. (Источник)
В этом определении следует отметить пару моментов:
- Словари сопоставляют ключи со значениями и сохраняют их в массиве или коллекции. Пары ключ-значение обычно известны как элементы.
- Ключи словаря должны иметь хэшируемый тип, что означает, что они должны иметь хэш-значение, которое никогда не меняется в течение срока службы ключа.
В отличие от последовательностей, которые являются итерируемыми и поддерживают доступ к элементам с использованием целочисленных индексов, словари индексируются по ключам. Это означает, что вы можете получить доступ к значениям, хранящимся в словаре, используя связанный ключ, а не целочисленный индекс.
Ключи в словаре очень похожи на set, который представляет собой набор хешируемых и уникальных объектов. Поскольку ключи должны быть хешируемыми, вы не можете использовать изменяемые объекты в качестве ключей словаря.
С другой стороны, значения словаря могут быть любого типа Python, независимо от того, являются ли они хэшируемыми или нет. Для значений буквально нет ограничений. Вы можете использовать что угодно в качестве значения в словаре Python.
Примечание: Концепции и темы, о которых вы узнаете в этом разделе и на протяжении всего этого руководства, относятся к реализации Python на CPython. Другие реализации, такие как PyPy, IronPython и Jython, могут демонстрировать различное поведение словаря и функции, которые выходят за рамки этого руководства.
До Python 3.6 словари были неупорядоченными структурами данных. Это означает, что порядок элементов обычно не соответствовал порядку вставки:
>>>
>>> # Python 3.5
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}
>>> likes
{'color': 'blue', 'pet': 'dog', 'fruit': 'apple'}
Обратите внимание, что порядок элементов в результирующем словаре не соответствует порядку, в котором вы изначально вставили элементы.
В Python версии 3.6 и выше ключи и значения словаря сохраняют тот же порядок, в котором вы вставляете их в базовый словарь. Начиная с версии 3.6, словари представляют собой компактные упорядоченные структуры данных:
>>>
>>> # Python 3.6
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}
>>> likes
{'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
Поддержание порядка элементов - довольно полезная функция. Однако, если вы работаете с кодом, поддерживающим более старые версии Python, тогда вы не должны полагаться на эту функцию, потому что она может привести к ошибочному поведению. В более новых версиях можно полностью безопасно полагаться на эту функцию.
Другой важной особенностью словарей является то, что они являются изменяемыми типами данных. Это означает, что вы можете добавлять, удалять и обновлять их элементы на месте по мере необходимости. Стоит отметить, что эта изменчивость также означает, что вы не можете использовать словарь в качестве ключа в другом словаре.
Понимание того, как выполнять итерации по словарю в Python
Как разработчик Python, вы часто будете сталкиваться с ситуациями, когда вам нужно выполнять итерацию по существующему словарю во время выполнения некоторых действий над его парами ключ-значение. Итак, для вас важно узнать о различных вариантах итерации по словарю в Python.
Когда дело доходит до выполнения итерации по словарю в Python, язык предоставляет несколько отличных инструментов и приемов, которые помогут вам в этом. Вы узнаете о некоторых из этих инструментов и приемов в этом руководстве. Для начала вы изучите основы итерации по словарям и их ключам, значениям и элементам с использованием for циклов.
Прямой обход словаря
В словарях Python есть некоторые специальные методы, которые Python использует внутренне для выполнения некоторых операций. Эти методы используют соглашение об именовании, заключающееся в добавлении двойного подчеркивания в начале и в конце имени метода.
Вы можете использовать встроенную dir() функцию, чтобы получить список методов и атрибутов, которые предоставляет любой объект Python. Если вы запустите dir() с пустым словарем в качестве аргумента, то получите все методы и атрибуты dict класса:
>>>
>>> dir({})
['__class__', '__contains__', '__delattr__', ... , '__iter__', ...]
При более внимательном рассмотрении предыдущего вывода обнаруживается '__iter__' запись, представляющая собой метод, который Python автоматически вызывает, когда вам требуется итератор для типа данных контейнера. Этот метод должен возвращать новый объект-итератор, который позволяет выполнять итерацию по всем элементам базового типа контейнера.
Для словарей Python .__iter__() по умолчанию позволяет выполнять прямую итерацию по ключам. Это означает, что если вы используете словарь непосредственно в for цикле, Python автоматически вызовет .__iter__() этот словарь, и вы получите итератор, который перебирает его ключи:
>>>
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}
>>> for key in likes:
... print(key)
...
color
fruit
pet
Python достаточно умен, чтобы знать, что likes является словарем и что он реализует .__iter__(). В этом примере Python вызывает .__iter__() автоматически, и это позволяет вам выполнять итерацию по ключам likes без дополнительных усилий с вашей стороны.
Это основной способ выполнить итерацию по словарю в Python. Вам просто нужно поместить словарь непосредственно в for цикл, и все готово!
Если вы используете этот подход вместе с [key] оператором, то вы можете получить доступ к значениям вашего словаря во время перебора ключей:
>>>
>>> for key in likes: ... print(key, "->", likes[key]) ... color -> blue fruit -> apple pet -> dog
В этом примере вы используете key и likes[key] одновременно для доступа к ключам и значениям вашего целевого словаря соответственно. Этот метод позволяет выполнять различные операции как с ключами, так и со значениями likes.
Несмотря на то, что выполнять итерацию по словарю напрямую в Python довольно просто, вы часто обнаружите, что словари предоставляют более удобные и понятные инструменты для достижения того же результата. Так обстоит дело с .items() методом, который определяет быстрый способ выполнения итерации по элементам или парам ключ-значение словаря.
Перебор элементов словаря: .items() Метод
При работе со словарями общим требованием может быть одновременное выполнение итераций по ключам и значениям. .items() Метод позволяет вам делать именно это. Метод возвращает объект view, содержащий элементы словаря в виде кортежей ключ-значение:
>>>
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}
>>> likes.items()
dict_items([('color', 'blue'), ('fruit', 'apple'), ('pet', 'dog')])
Объекты представления словаря обеспечивают динамическое представление элементов словаря. Здесь динамическое означает, что при изменении словаря представления отражают эти изменения.
Представления являются итеративными, поэтому вы можете выполнять итерацию по элементам словаря, используя объект view, который является результатом вызова .items(), как вы можете видеть в примере ниже:
>>>
>>> for item in likes.items():
... print(item)
...
('color', 'blue')
('fruit', 'apple')
('pet', 'dog')
В этом примере .items() возвращает объект view, который выдает пары ключ-значение по одному за раз и позволяет выполнять итерацию по ним.
Если вы внимательнее посмотрите на отдельные элементы, которые .items() выдают, то вы заметите, что они являются tuple объектами:
>>>
>>> for item in likes.items():
... print(item)
... print(type(item))
...
('color', 'blue')
<class 'tuple'>
('fruit', 'apple')
<class 'tuple'>
('pet', 'dog')
<class 'tuple'>
В этом обновленном цикле вы используете встроенную type() функцию для проверки типа данных каждого элемента, который .items() выдает. Как вы можете подтвердить в выходных данных цикла, все элементы являются кортежами. Как только вы это узнаете, вы можете использовать tuple распаковку для параллельного перебора ключей и значений.
Для достижения параллельной итерации по ключам и значениям вам просто нужно распаковать элементы каждого элемента в две разные переменные, одну для ключа, а другую для значения:
>>>
>>> for key, value in likes.items(): ... print(key, "->", value) ... color -> blue fruit -> apple pet -> dog
Распаковку выполняют переменные key и value в заголовке вашего for цикла. Каждый раз, когда выполняется цикл, key получает ссылку на текущий ключ и value получает ссылку на значение. Таким образом, у вас больше контроля над содержимым словаря. Таким образом, вы сможете обрабатывать ключи и значения отдельно в удобочитаемом и Pythonic виде.
Итерация по ключам словаря: .keys() метод
Словари Python предлагают второй способ для вас выполнять итерацию по своим ключам. Помимо использования целевого словаря непосредственно в цикле, вы также можете использовать .keys() метод. Этот метод возвращает объект view, содержащий только ключи словаря:
>>>
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}
>>> likes.keys()
dict_keys(['color', 'fruit', 'pet'])
.keys() Метод возвращает объект, который обеспечивает динамическое представление ключей в likes. Вы можете использовать этот объект view для выполнения итерации по ключам словаря. Чтобы сделать это, вызовите .keys() в заголовке for цикла:
>>>
>>> for key in likes.keys(): ... print(key) ... color fruit pet
Когда вы вызываете .keys() on likes, вы получаете представление ключей. Python знает, что объекты view могут повторяться, поэтому он начинает цикл.
Вы можете задаться вопросом, почему вы используете .keys() вместо того, чтобы просто выполнять итерацию по словарю напрямую. Быстрый ответ заключается в том, что использование .keys() явно позволяет вам лучше сообщать о намерении выполнять итерацию только по ключам.
Переход по значениям словаря: .values() метод
Еще одна распространенная потребность, с которой вы столкнетесь при выполнении итерации по словарям, - это перебирать только значения. Способ сделать это - использовать .values() метод, который возвращает представление со значениями в базовом словаре:
>>>
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}
>>> likes.values()
dict_values(['blue', 'apple', 'dog'])
В этом коде .values() возвращает объект view, который выдает значения из likes. Как и в случае с другими объектами view, результат .values() также является итеративным, поэтому вы можете использовать его в цикле:
>>>
>>> for value in likes.values(): ... print(value) ... blue apple dog
Используя .values(), у вас есть доступ только к значениям вашего целевого словаря, likes. Обратите внимание, что этот инструмент итерации не предоставляет вам доступ к ключу, связанному с каждым значением. Итак, вы должны использовать этот метод, если вам нужно получить доступ только к значениям в целевом словаре.
Изменение значений словаря во время итерации
Иногда вам нужно будет изменять значения в словаре во время выполнения итерации по ним в Python. В следующем примере вы обновляете цену группы продуктов в словаре:
>>>
>>> fruits = {"apple": 0.40, "orange": 0.35, "banana": 0.25}
>>> for fruit, price in fruits.items():
... fruits[fruit] = round(price * 0.9, 2)
...
>>> fruits
{'apple': 0.36, 'orange': 0.32, 'banana': 0.23}
В этом примере вы используете выражение fruits[fruit] = round(price * 0.9, 2) для изменения значений fruits и применения 10-процентной скидки.
В приведенном выше примере следует отметить тонкую деталь: для обновления значений вы используете исходный словарь вместо простого обновления текущего price напрямую с помощью чего-то вроде price = round(price * 0.9, 2). Зачем вам это нужно, fruits[fruit] если у вас есть прямой доступ к price? Возможно ли обновление price напрямую?
Реальная проблема заключается в том, что переназначение fruit или price не отражается в исходном словаре. Что действительно произойдет, так это то, что вы потеряете ссылку на компонент dictionary, ничего не изменив в словаре.
Безопасное удаление элементов из словаря во время итерации
Поскольку словари Python изменяемы, вы можете удалять существующие пары ключ-значение из них по мере необходимости. В следующем примере вы удаляете элемент выборочно, в соответствии с его конкретным значением. Обратите внимание, что для безопасного сжатия словаря во время выполнения итерации по нему необходимо использовать копию:
>>>
>>> fruits = {"apple": 0.40, "orange": 0.35, "banana": 0.25}
>>> for fruit in fruits.copy():
... if fruits[fruit] >= 0.30:
... del fruits[fruit]
...
>>> fruits
{'banana': 0.25}
В этом примере вы используете .copy() для создания мелкой копии вашего целевого словаря, fruits. Затем вы выполняете цикл по копии, удаляя элементы из исходного словаря. В приведенном примере вы используете del инструкцию для удаления элементов словаря. Однако вы также можете использовать .pop() с целевым ключом в качестве аргумента.
Если вы не используете копию вашего целевого словаря при попытке удалить элементы в цикле, то вы получите сообщение об ошибке:
>>>
>>> fruits = {"apple": 0.40, "orange": 0.35, "banana": 0.25}
>>> for fruit in fruits:
... if fruits[fruit] >= 0.30:
... del fruits[fruit]
...
Traceback (most recent call last):
File "<input>", line 1, in <module>
for fruit in fruits:
RuntimeError: dictionary changed size during iteration
Когда вы пытаетесь удалить элемент из словаря во время итерации, Python выдает RuntimeError. Поскольку исходный словарь изменил свой размер, неясно, как продолжить итерацию. Итак, чтобы избежать этой проблемы, всегда используйте копию вашего словаря при итерации.
Выполнение итерации по словарям: for Примеры циклов
К настоящему моменту вы изучили основные способы выполнения итераций по словарю в Python. Теперь вы знаете, как выполнять итерации по ключам, значениям и элементам словаря, используя различные инструменты и техники. Пришло время двигаться дальше и написать несколько примеров того, что вы можете делать с содержимым словаря во время выполнения итерации по нему в for цикле.
Примечание: В разделе, посвященном примерам понимания, вы узнаете, что вы также можете использовать понимания для решения тех же задач более сжатым способом.
Для начала вы начнете с примера того, как фильтровать элементы словаря по значению с помощью for цикла.
Фильтрация элементов по их значению
Иногда вы будете находиться в ситуациях, когда у вас есть словарь и вы хотите создать новый, содержащий только те данные, которые удовлетворяют заданному условию. Вы можете сделать это с помощью условного оператора во время обхода словаря. Рассмотрим следующий игрушечный пример:
>>>
>>> numbers = {"one": 1, "two": 2, "three": 3, "four": 4}
>>> small_numbers = {}
>>> for key, value in numbers.items():
... if value <= 2:
... small_numbers[key] = value
...
>>> small_numbers
{'one': 1, 'two': 2}
В этом примере вы фильтруете элементы со значением меньше 2 и добавляете их в свой small_numbers словарь. Этот новый словарь содержит только элементы, удовлетворяющие условию value <= 2, которое является вашим условием фильтрации.
Есть еще один метод, который вы можете использовать для фильтрации элементов из словаря. Ключевые объекты представления похожи на наборы Python. Таким образом, они поддерживают set операции, такие как объединение, пересечение и различие. Вы можете воспользоваться этим поведением, подобным набору, для фильтрации определенных ключей из словаря.
Например, в приведенном ниже коде вы используете set difference для фильтрации citrus из вашего fruits словаря:
>>>
>>> fruits = {"apple": 0.40, "orange": 0.35, "banana": 0.25}
>>> fruits.keys() - {"orange"}
{'apple', 'banana'}
Когда вы запускаете fruits.keys() - {"orange"}, вы действительно выполняете set операцию разности. Вы можете использовать этот трюк для создания нового словаря без цитрусовых:
>>>
>>> non_citrus = {}
>>> for key in fruits.keys() - {"orange"}:
... non_citrus[key] = fruits[key]
...
>>> non_citrus
{'apple': 0.4, 'banana': 0.25}
В этом примере вы создаете новый словарь из набора ключей, который вы получаете в результате вычисления разницы между ключами вашего словаря и набором ненужных ключей.
Тот факт, что ключевые объекты представления ведут себя как наборы, является малоизвестной особенностью, которая может быть полезна в некоторых ситуациях. Поэтому храните ее в своем наборе инструментов.
Выполнение вычислений с ключами и значениями
Выполнение вычислений со значениями словаря во время выполнения итерации по самому словарю - еще одна распространенная задача. Предположим, вы сохранили данные о продажах вашей компании в словаре, и теперь вы хотите узнать общий доход за год.
Чтобы решить эту проблему, вы можете использовать переменную accumulator с начальным значением, равным нулю. Затем вы можете накапливать каждое значение в вашем словаре в этой переменной:
>>>
>>> incomes = {"apple": 5600.00, "orange": 3500.00, "banana": 5000.00}
>>> total_income = 0.00
>>> for income in incomes.values():
... total_income += income
...
>>> total_income
14100.0
Здесь вы выполняете итерацию по значениям в вашем incomes словаре и последовательно накапливаете их в total_income. Расширенное назначение total_income += income творит чудеса, и в конце цикла вы получаете общий доход за год.
Как и во многих задачах в Python, у вас будет лучший способ выполнить те же вычисления, что и в примере ниже. Вы можете использовать встроенную sum() функцию:
>>>
>>> sum(incomes.values()) 14100.0
В этом примере вы передаете значения из вашего incomes словаря непосредственно в качестве аргумента в sum(). Функция неявно выполняет итерацию по значениям и вычисляет их сумму в процессе.
Несмотря на то, что sum() решение является кратким, быстрым и читаемым, циклическое решение является более общим и позволяет выполнять вычисления, отличные от простого суммирования значений.
Замена ключей и значений с помощью итерации
Предположим, у вас есть словарь и вам нужно превратить ключи в значения, а значения - в ключи. В этой ситуации вы можете использовать for цикл для выполнения итерации по исходному словарю, пока вы создаете новый с замененными ключами и значениями:
>>>
>>> numbers = {"one": 1, "two": 2, "three": 3, "four": 4}
>>> swapped = {}
>>> for key, value in numbers.items():
... swapped[value] = key
...
>>> swapped
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
Выражение swapped[value] = key выполняет за вас всю тяжелую работу, меняя местами ключи и значения в новом словаре. Обратите внимание, что для работы этого кода данные, хранящиеся в значениях вашего исходного словаря, должны иметь хэшируемый тип данных. В противном случае вы получите сообщение об ошибке.
Опять же, в Python есть другие инструменты, которые позволяют записать предыдущий пример более кратким способом. На этот раз вы можете использовать встроенную zip() функцию вместе с dict() конструктором:
>>>
>>> dict(zip(numbers.values(), numbers.keys()))
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
В этом примере вы используете zip() для генерации кортежей пар значение-ключ. Для этого zip() неявно выполняется итерация по значениям и ключам вашего numbers словаря. Затем вы используете полученные кортежи в качестве аргументов для dict() и создаете нужный словарь.
Выполнение итерации по словарям: примеры понимания
Понимание словаря - это компактный способ обработки и преобразования данных с целью получения в результате нового словаря. В отличие от понимания списка, для понимания словаря требуется ключ, который соответствует значению. Сначала вы можете предоставить два выражения, разделенные двоеточием (:). После этого вы предоставите for предложение, и вы также можете включить необязательное if предложение.
Чтобы проиллюстрировать, как работает понимание словаря, предположим, что у вас есть два списка данных, и вам нужно создать из них новый словарь. В этом случае вы можете использовать встроенный zip() для параллельного перебора элементов обоих списков:
>>>
>>> categories = ["color", "fruit", "pet"]
>>> objects = ["blue", "apple", "dog"]
>>> likes = {key: value for key, value in zip(categories, objects)}
>>> likes
{'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
В этом примере zip() получает две итерации, categories и objects, в качестве аргументов и создает итератор, который объединяет элементы из каждой итерации. tuple Объекты, которые zip() генерируются, затем распаковываются в key и value, которые вы, наконец, используете для создания нового нужного словаря.
Примечание: Приведенный выше пример демонстрирует, как работает понимание словаря в Python. Тем не менее, лучшим способом написания примера было бы следующее:
>>>
>>> categories = ["color", "fruit", "pet"]
>>> objects = ["blue", "apple", "dog"]
>>> dict(zip(categories, objects))
{'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
zip() Функция генерирует пары ключ-значение из исходных списков, в то время как dict() конструктор создает новый словарь для вас. Разве это не круто?
Понимание словаря открывает широкий спектр новых возможностей и предоставляет вам отличный инструмент для итерации по словарям на Python и их преобразования.
Фильтрация элементов по их значению: пересмотрено
Чтобы фильтровать элементы в словаре с пониманием, вам просто нужно добавить if предложение, которое определяет ваше условие фильтрации. Ранее вы работали с условием value <= 2. Вы можете получить тот же результат с пониманием словаря:
>>>
>>> numbers = {"one": 1, "two": 2, "three": 3, "four": 4}
>>> {key: value for key, value in numbers.items() if value <= 2}
{'one': 1, 'two': 2}
Теперь ваш результирующий словарь содержит только те элементы, которые удовлетворяют вашему условию. По сравнению с решением предыдущего раздела, это решение более краткое и эффективное.
Замена ключей и значений с помощью итерации: пересмотрено
Вы также можете подойти к проблеме замены ключей и значений, используя понимание словаря. С помощью этого инструмента вы можете написать более краткое решение на языке Python, которое также является более эффективным. Вот как:
>>>
>>> numbers = {"one": 1, "two": 2, "three": 3, "four": 4}
>>> {value: key for key, value in numbers.items()}
{1: 'one', 2: 'two', 3: 'three', 4: 'four'}
С таким пониманием вы создаете новый словарь, в котором ключи заменяют значения, и наоборот. Этот новый подход дает вам возможность писать более читаемый, краткий и эффективный код.
Опять же, условие для работы этого кода такое же, как вы видели ранее: значения должны быть объектами с возможностью хэширования. В противном случае вы не сможете использовать их в качестве ключей для вашего нового словаря.
Перевод статьи: Leodanis Pozo Ramos - How to Iterate Through a Dictionary in Python