Как перебрать словарь в Python
Словари являются одной из наиболее важных и полезных структур данных в Python. Они могут помочь вам решить широкий спектр задач программирования. Из этой статьи вы узнаете, как итерировать словарь в Python.
К концу этой статьи вы узнаете:
- Что такое словари, а также некоторые их основные функции и детали реализации
- Как итерировать словарь в Python, используя основные инструменты, предлагаемые языком
- Какие реальные задачи вы можете выполнить, просматривая словарь в Python
- Как использовать некоторые более продвинутые методы и стратегии для перебора словаря в Python
Для получения дополнительной информации о словарях, вы можете обратиться к следующим ресурсам:
- Dictionaries in Python
- Itertools in Python 3, By Example
- The documentation for
map()
andfilter()
Готовы? Поехали!
Несколько слов о словарях
Словари являются краеугольным камнем Python. Сам язык построен вокруг словарей. Модули, классы, объекты, globals(), locals(): все это словари. Словари были центральным элементом для Python с самого начала.
Официальная документация Python определяет словарь следующим образом:
Ассоциативный массив, где произвольные ключи отображаются на значения. Ключами могут быть любые объекты с методами __hash__() и __eq__(). (Источник)
Есть несколько моментов, о которых следует помнить:
- Словари сопоставляют ключи со значениями и сохраняют их в массиве или коллекции.
- Ключи должны быть хэшируемого типа (hashable), что означает, что в качестве ключа используют хэш значения ключа, который никогда не меняется в течение срока жизни ключа.
Словари часто используются для решения всевозможных задач программирования, поэтому они являются фундаментальной частью инструментария разработчика Python.
В отличие от последовательностей (sequences), которые так же являются итерационными поддерживающими доступ к элементам с использованием целочисленных индексов, словари индексируются по ключам.
Ключи в словаре очень похожи на множества set
, представляющие собой коллекцию уникальных объектов, которые можно хэшировать. Поскольку объекты должны быть хешируемыми, изменяемые (mutable) объекты нельзя использовать в качестве ключей словаря.
С другой стороны, значения могут быть любого типа Python, независимо от того, являются они хэшируемыми или нет. Там нет буквально никаких ограничений.
В Python 3.6 и более поздних версиях ключи и значения словаря перебираются в том же порядке, в котором они были созданы. Однако это поведение может отличаться в разных версиях Python и зависит от истории вставок и удалений словаря.
В Python 2.7 словари являются неупорядоченными структурами. Порядок элементом словарей неизменяемый. Это означает, что порядок элементов является детерминированным и повторяемым. Давайте посмотрим на пример:
>>> # Python 2.7
>>> a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> a_dict
{'color': 'blue', 'pet': 'dog', 'fruit': 'apple'}
>>> a_dict
{'color': 'blue', 'pet': 'dog', 'fruit': 'apple'}
>>> # Python 2.7. New interactive session
>>> a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> a_dict
{'color': 'blue', 'pet': 'dog', 'fruit': 'apple'}
>>> a_dict
{'color': 'blue', 'pet': 'dog', 'fruit': 'apple'}
В Python 3.5 словари все еще неупорядочены, но на этот раз рандомизированные структуры данных. Это означает, что каждый раз, когда вы снова запускаете словарь, вы получаете другой порядок элементов. Давайте посмотрим:
>>> # Python 3.5
>>> a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> a_dict
{'color': 'blue', 'pet': 'dog', 'fruit': 'apple'}
>>> a_dict
{'color': 'blue', 'pet': 'dog', 'fruit': 'apple'}
>>> # Python 3.5. New interactive session
>>> a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> a_dict
{'fruit': 'apple', 'pet': 'dog', 'color': 'blue'}
>>> a_dict
{'fruit': 'apple', 'pet': 'dog', 'color': 'blue'}
В Python 3.6 и более поздних версиях словари являются упорядоченными структурами данных, что означает, что они хранят свои элементы в том же порядке, в котором они были созданы, как вы можете видеть здесь:
>>> # Python 3.6 and beyond
>>> a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> a_dict
{'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> a_dict
{'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
Другой важной особенностью словарей является то, что они являются изменчивыми структурами данных, что означает, что вы можете добавлять, удалять и обновлять их элементы. Стоит отметить, что это также означает, что их нельзя использовать в качестве ключей для других словарей, так как они не являются объектами, которые можно хэшировать.
Примечание. Все, что описано в этом разделе, относится к базовой реализации Python, CPython.
Другие реализации Python, такие как PyPy, IronPython или Jython, могут демонстрировать другое поведение словаря, которые выходят за рамки данной статьи.
Как перебирать словарь в Python: основы
Словари являются полезной и широко используемой структурой данных в Python. Как программист Python, вы часто будете в ситуациях, когда вам придется перебирать словарь, в то время как вы выполняете некоторые действия над его парами ключ-значение.
Когда дело доходит до перебора словаря в Python, язык предоставляет вам несколько отличных инструментов, которые мы рассмотрим в этой статье.
Прямая итерация по ключам
Словари Python являются отображающими объектами. Это означает, что они наследуют некоторые специальные методы, которые Python внутренне использует для выполнения некоторых операций. Эти методы называются с использованием соглашения об именах, заключающегося в добавлении двойного подчеркивания в начале и в конце имени метода.
Чтобы визуализировать методы и атрибуты любого объекта Python, вы можете использовать dir(), которая является встроенной функцией. Если вы запустите dir() с пустым словарем в качестве аргумента, вы сможете увидеть все методы и атрибуты, которые реализуют словари:
>>> dir({})
['__class__', '__contains__', '__delattr__', ... , '__iter__', ...]
Примечание: вывод предыдущего кода был сокращен (…) для экономии места.
Для мапинга (например, словарей) .__iter__() должен перебирать ключи. Это означает, что если вы поместите словарь непосредственно в цикл for
, Python автоматически вызовет .__iter__() для этого словаря, и вы получите итератор по его ключам:
>>> a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> for key in a_dict:
... print(key)
...
color
fruit
pet
Это самый простой способ перебора словаря в Python. Просто поместите его прямо в цикл for, и все готово!
Если вы используете этот подход вместе с небольшой уловкой, то вы можете обрабатывать ключи и значения любого словаря. Хитрость заключается в использовании оператора индексации [] со словарем и его ключами для получения доступа к значениям:
>>> for key in a_dict:
... print(key, '->', a_dict[key])
...
color -> blue
fruit -> apple
pet -> dog
Итерация по .items()
Когда вы работаете со словарями, вероятно, вы захотите работать как с ключами, так и со значениями. Одним из наиболее полезных способов перебора словаря в Python является использование метода .items(), который возвращает новый вид элементов словаря:
>>> a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> d_items = a_dict.items()
>>> d_items # Here d_items is a view of items
dict_items([('color', 'blue'), ('fruit', 'apple'), ('pet', 'dog')])
Представления могут быть перебраны для получения соответствующих данных, поэтому вы можете итерировать словарь в Python, используя объект представления, возвращаемый .items():
>>> for item in a_dict.items():
... print(item)
...
('color', 'blue')
('fruit', 'apple')
('pet', 'dog')
Если вы присмотритесь к отдельным элементам, полученным с помощью .items(), вы заметите, что они действительно являются кортежами объектов. Давайте посмотрим:
>>> for item in a_dict.items():
... print(item)
... print(type(item))
...
('color', 'blue')
<class 'tuple'>
('fruit', 'apple')
<class 'tuple'>
('pet', 'dog')
<class 'tuple'>
>>> for key, value in a_dict.items():
... print(key, '->', value)
...
color -> blue
fruit -> apple
pet -> dog
Примечание: обратите внимание, что .values() и .keys() возвращают объекты представления так же, как .items(), как вы увидите в следующих двух разделах.
Итерация через .keys()
Если вам просто нужно работать с ключами словаря, то вы можете использовать метод .keys(), который возвращает новый объект представления, содержащий ключи словаря:
>>> a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> keys = a_dict.keys()
>>> keys
dict_keys(['color', 'fruit', 'pet'])
>>> for key in a_dict.keys():
... print(key)
...
color
fruit
pet
>>> for key in a_dict.keys():
... print(key, '->', a_dict[key])
...
color -> blue
fruit -> apple
pet -> dog
Итерация по .values()
Также можно использовать значения для перебора словаря. Один из способов сделать это – использовать .values(), который возвращает представление со значениями словаря:
>>> a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> values = a_dict.values()
>>> values
dict_values(['blue', 'apple', 'dog'])
Как и любой объект представления, объект, возвращаемый функцией .values(), также может быть итерирован. В этом случае .values() возвращает значения a_dict:
>>> for value in a_dict.values():
... print(value)
...
blue
apple
dog
in
)), что является важной функцией, если вы пытаетесь узнать, есть ли определенный элемент в словаре или нет:>>> a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> 'pet' in a_dict.keys()
True
>>> 'apple' in a_dict.values()
True
>>> 'onion' in a_dict.values()
False
Изменение значений и ключей
Часто бывает необходимо изменить значения и ключа, когда вы перебираете словарь в Python. Есть некоторые моменты, которые вы должны принять во внимание, чтобы выполнить эту задачу.
Например, значения можно изменять всякий раз, когда вам нужно, но вам нужно будет использовать исходный словарь и ключ, который отображает значение, которое вы хотите изменить:
>>> prices = {'apple': 0.40, 'orange': 0.35, 'banana': 0.25}
>>> for k, v in prices.items():
... prices[k] = round(v * 0.9, 2) # Apply a 10% discount
...
>>> prices
{'apple': 0.36, 'orange': 0.32, 'banana': 0.23}
Так зачем вам использовать оригинальный словарь, если у вас есть доступ к его ключу (k) и его значениям (v)? Если мы можем изменить их напрямую?
Реальная проблема заключается в том, что изменения k и v не отражаются в исходном словаре. То есть, если вы измените какой-либо из них (k или v) непосредственно внутри цикла, то, что действительно происходит, так это то, что вы потеряете ссылку на соответствующий компонент словаря, не изменяя ничего в словаре.
С другой стороны, ключи могут быть добавлены или удалены из словаря путем преобразования представления, возвращаемого функцией .keys(), в объект list:
>>> prices = {'apple': 0.40, 'orange': 0.35, 'banana': 0.25}
>>> for key in list(prices.keys()): # Use a list instead of a view
... if key == 'orange':
... del prices[key] # Delete a key from prices
...
>>> prices
{'apple': 0.4, 'banana': 0.25}
Наконец, если вы попытаетесь удалить ключ из prices, используя напрямую .keys(), тогда Python вызовет RuntimeError, сообщающую, что размер словаря изменился во время итерации:
>>> # Python 3. dict.keys() returns a view object, not a list
>>> prices = {'apple': 0.40, 'orange': 0.35, 'banana': 0.25}
>>> for key in prices.keys():
... if key == 'orange':
... del prices[key]
...
Traceback (most recent call last):
File "<input>", line 1, in <module>
for key in prices.keys():
RuntimeError: dictionary changed size during iteration
Примечание. В Python 2 объекты .items(), .keys() и .values() возвращают список объектов. Но .iteritems(), iterkeys() и .itervalues() возвращают итераторы. Итак, если вы используете Python 2, то вы можете изменить ключи словаря, используя .keys() напрямую.
С другой стороны, если вы используете iterkeys() в своем коде Python 2 и пытаетесь изменить ключи словаря, вы получите RuntimeError.
Примеры из реального мира
До сих пор вы видели более простые способы перебора словаря в Python. Теперь пришло время посмотреть, как вы можете выполнять некоторые действия с элементами словаря во время итерации. Давайте посмотрим на некоторые примеры из реальной жизни.
Примечание. Позже в этой статье вы увидите другой способ решения тех же самых проблем с помощью других инструментов Python.
Превращение ключей в значение и наоборот
Предположим, у вас есть словарь и по какой-то причине необходимо превратить ключи в значения и наоборот. В этой ситуации вы можете использовать цикл for для перебора словаря и создания нового словаря, используя ключи в качестве значений и наоборот:
>>> a_dict = {'one': 1, 'two': 2, 'thee': 3, 'four': 4}
>>> new_dict = {}
>>> for key, value in a_dict.items():
... new_dict[value] = key
...
>>> new_dict
{1: 'one', 2: 'two', 3: 'thee', 4: 'four'}
Фильтрация
Иногда вы будете в ситуациях, когда у вас есть словарь, и вы захотите создать новый, чтобы хранить только данные, которые удовлетворяют заданному условию. Вы можете сделать это с помощью if внутри цикла for следующим образом:
>>> a_dict = {'one': 1, 'two': 2, 'thee': 3, 'four': 4}
>>> new_dict = {} # Create a new empty dictionary
>>> for key, value in a_dict.items():
... # If value satisfies the condition, then store it in new_dict
... if value <= 2:
... new_dict[key] = value
...
>>> new_dict
{'one': 1, 'two': 2}
Выполнять некоторые расчеты
Также часто требуется выполнять некоторые вычисления, пока вы перебираете словарь в Python. Предположим, вы сохранили данные о продажах вашей компании в словаре, и теперь вы хотите узнать общий доход за год.
Чтобы решить эту проблему, вы можете определить переменную с начальным значением ноль. Затем вы можете накапливать каждое значение вашего словаря в этой переменной:
>>> incomes = {'apple': 5600.00, 'orange': 3500.00, 'banana': 5000.00}
>>> total_income = 0.00
>>> for value in incomes.values():
... total_income += value # Accumulate the values in total_income
...
>>> total_income
14100.0
Использование генераторов (comprehensions)
Генераторы словарей (Dictionary comprehension) – это компактный способ обработки всех или части элементов в коллекции и возврата словаря в качестве результата. В отличие от списочных представлений, им нужны два выражения, разделенные двоеточием, за которым следуют предложения for и if (необязательно). Когда выполняется генератор словаря, полученные пары ключ-значение вставляются в новый словарь в том же порядке, в котором они были созданы.
Предположим, например, что у вас есть два списка данных, и вам нужно создать новый словарь из них. В этом случае вы можете использовать zip (* iterables) в Python для циклического обхода элементов обоих списков:
>>> objects = ['blue', 'apple', 'dog']
>>> categories = ['color', 'fruit', 'pet']
>>> a_dict = {key: value for key, value in zip(categories, objects)}
>>> a_dict
{'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
Генератор словарей открывает широкий спектр новых возможностей и предоставляет вам отличный инструмент для перебора словаря в Python.
Еще раз о превращение ключей в значение и наоборот
Если вы по-другому взгляните на проблему превращения ключей в значения и наоборот, вы увидите, что вы могли бы написать более эффективное решение с использованием генератора словарей:
>>> a_dict = {'one': 1, 'two': 2, 'thee': 3, 'four': 4}
>>> new_dict = {value: key for key, value in a_dict.items()}
>>> new_dict
{1: 'one', 2: 'two', 3: 'thee', 4: 'four'}
Условие для работы этого кода такое же, как вы видели ранее: значения должны быть объектами, которые можно хэшировать. В противном случае вы не сможете использовать их в качестве ключей для a_dict.
Пересмотр фильтрации
Чтобы отфильтровать элементы в словаре с генератором, вам просто нужно добавить условие if, которое определяет условие, которое вы хотите выполнить. В предыдущем примере, когда вы фильтровали словарь, это условие было, если v <= 2. С этим условием if, добавленным в конец генератора словаря, вы отфильтруете элементы, значения которых больше 2. Давайте посмотрим:
>>> a_dict = {'one': 1, 'two': 2, 'thee': 3, 'four': 4}
>>> new_dict = {k: v for k, v in a_dict.items() if v <= 2}
>>> new_dict
{'one': 1, 'two': 2}
Пересмотр выполнение расчетов
Помните пример с продажами компании? Если вы используете генератор списков (list comprehension) для перебора значений словаря, вы получите более компактный, быстрый и Pythonic-код:
>>> incomes = {'apple': 5600.00, 'orange': 3500.00, 'banana': 5000.00}
>>> total_income = sum([value for value in incomes.values()])
>>> total_income
14100.0
Если вы работаете с действительно большим словарем, и использование памяти является проблемой для вас, тогда вы можете использовать выражение-генератор (generator expression) вместо генератора списков. выражение-генератор – это выражение, которое возвращает итератор. Это похоже на генератор списков, но вместо квадратных скобок для его определения необходимо использовать круглые скобки:
>>> total_income = sum(value for value in incomes.values())
>>> total_income
14100.0
Примечание. Если вы новичок в выражение-генератор (generator expressions), вы можете взглянуть на Introduction to Python Generators, чтобы лучше изучить тему.
Наконец, есть более простой способ решить эту проблему, просто используя incomes.values() непосредственно в качестве аргумента для sum():
>>> total_income = sum(incomes.values())
>>> total_income
14100.0
Удаление выбранных элементов
Теперь предположим, что у вас есть словарь, и вам нужно создать новый с удаленными выбранными ключами. Помните, как объекты словаря похожи на sets? Эти сходства выходят за рамки просто коллекции хэшируемых и уникальных объектов. Эти объекты также поддерживают общие операции над множествами. Давайте посмотрим, как вы можете воспользоваться этим, чтобы удалить определенные элементы из словаря:
>>> incomes = {'apple': 5600.00, 'orange': 3500.00, 'banana': 5000.00}
>>> non_citric = {k: incomes[k] for k in incomes.keys() - {'orange'}}
>>> non_citric
{'apple': 5600.0, 'banana': 5000.0}
Сортировка словаря
Часто необходимо сортировать элементы коллекции. Начиная с Python 3.6, словари являются упорядоченными структурами данных, поэтому, если вы используете Python 3.6 (и более поздние версии), вы сможете сортировать элементы любого словаря с помощью sorted() и с помощью генератора словаря:
>>> # Python 3.6, and beyond
>>> incomes = {'apple': 5600.00, 'orange': 3500.00, 'banana': 5000.00}
>>> sorted_income = {k: incomes[k] for k in sorted(incomes)}
>>> sorted_income
{'apple': 5600.0, 'banana': 5000.0, 'orange': 3500.0}
Итерация в отсортированном порядке
Иногда вам может понадобиться перебрать словарь в Python, но вы хотите сделать это в отсортированном порядке. Это может быть достигнуто с помощью sorted(). Когда вы вызываете sorted(iterable), вы получаете list с элементами в отсортированном порядке.
Давайте посмотрим, как вы можете использовать sorted() для перебора словаря, когда вам нужно сделать это в отсортированном порядке.
Сортировка по ключам
Если вам нужно перебрать словарь в Python и отсортировать его по ключам, вы можете использовать свой словарь в качестве аргумента для sorted(). Это вернет list, содержащий ключи в отсортированном порядке, и вы сможете их перебирать:
>>> incomes = {'apple': 5600.00, 'orange': 3500.00, 'banana': 5000.00}
>>> for key in sorted(incomes):
... print(key, '->', incomes[key])
...
apple -> 5600.0
banana -> 5000.0
orange -> 3500.0
Примечание. Порядок сортировки будет зависеть от типа данных, который вы используете для ключей или значений, и от внутренних правил, которые Python использует для сортировки этих типов данных.
Сортировка по значениям
Вам также может понадобиться перебрать словарь в Python с его элементами, отсортированными по значениям. Вы также можете использовать sorted(), но со вторым аргументом key.
Аргумент key определяет функцию одного аргумента, которая используется для извлечения ключа сравнения для каждого элемента, который вы обрабатываете.
Чтобы отсортировать элементы словаря по значениям, вы можете написать функцию, которая возвращает значение каждого элемента, и использовать эту функцию в key аргумента для sorted():
>>> incomes = {'apple': 5600.00, 'orange': 3500.00, 'banana': 5000.00}
>>> def by_value(item):
... return item[1]
...
>>> for k, v in sorted(incomes.items(), key=by_value):
... print(k, '->', v)
...
('orange', '->', 3500.0)
('banana', '->', 5000.0)
('apple', '->', 5600.0)
Вы также можете просто перебирать значения словаря в отсортированном порядке, не беспокоясь о ключах. В этом случае вы можете использовать .values() следующим образом:
>>> for value in sorted(incomes.values()):
... print(value)
...
3500.0
5000.0
5600.0
Реверсия
Если вам нужно отсортировать словари в обратном порядке, вы можете добавить reverse = True в качестве аргумента для sorted(). Ключевое слово аргумент reverse должно принимать логическое значение. Если установлено значение True, то элементы сортируются в обратном порядке:
>>> incomes = {'apple': 5600.00, 'orange': 3500.00, 'banana': 5000.00}
>>> for key in sorted(incomes, reverse=True):
... print(key, '->', incomes[key])
...
orange -> 3500.0
banana -> 5000.0
apple -> 5600.0
Наконец, важно отметить, что sorted() не меняет порядок основного словаря. Что на самом деле происходит, так это то, что sorted() создает независимый список со своими элементами в отсортированном порядке, поэтому incomes остаются прежними:
Разрушительная итерация с помощью .popitem()
Иногда нужно перебрать словарь в Python и последовательно удалить его элементы. Для выполнения этой задачи можно использовать .popitem(), которая удалит и возвратит произвольную пару ключ-значение из словаря. С другой стороны, когда вы вызываете .popitem() в пустом словаре, он вызывает ошибку KeyError.
Пример:
# File: dict_popitem.py
a_dict = {'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
while True:
try:
print(f'Dictionary length: {len(a_dict)}')
item = a_dict.popitem()
# Do something with item here...
print(f'{item} removed')
except KeyError:
print('The dictionary has no item now...')
break
Если мы запустим этот скрипт из командной строки, то мы получим следующие результаты:
$ python3 dict_popitem.py
Dictionary length: 3
('pet', 'dog') removed
Dictionary length: 2
('fruit', 'apple') removed
Dictionary length: 1
('color', 'blue') removed
Dictionary length: 0
The dictionary has no item now...
Использование некоторых из встроенных функций Python
Python предоставляет некоторые встроенные функции, которые могут быть полезны при работе со словарями. Эти функции являются своего рода инструментом итерации, который предоставляет вам еще один способ перебора словаря. Давайте посмотрим на некоторые из них.
map()
map() определяется как map(function, iterable, …) и возвращает итератор, который применяет функцию к каждому элементу итерируемого. Таким образом, map() можно рассматривать как инструмент итерации, который можно использовать для перебора словаря.
Предположим, у вас есть словарь, содержащий цены на несколько продуктов, и вам нужно применить скидку к ним. В этом случае вы можете определить функцию, которая управляет скидкой, а затем использует ее в качестве первого аргумента для map(). Вторым аргументом может быть price.items():
>>> prices = {'apple': 0.40, 'orange': 0.35, 'banana': 0.25}
>>> def discount(current_price):
... return (current_price[0], round(current_price[1] * 0.95, 2))
...
>>> new_prices = dict(map(discount, prices.items()))
>>> new_prices
{'apple': 0.38, 'orange': 0.33, 'banana': 0.24}
Обратите внимание, что discount() возвращает кортеж в форме (key, value), где current_price[0] представляет ключ, а round(current_price [1] * 0.95, 2) представляет новое значение.
filter()
filter () – это еще одна встроенная функция, которую вы можете использовать для перебора словаря и фильтрации некоторых его элементов. Эта функция определяется как filter(function, iterable) и возвращает итератор из тех элементов итерируемого, для которых функция возвращает значение True.
Предположим, вы хотите знать продукты с ценой ниже 0,40. Вам нужно определить функцию, чтобы определить, удовлетворяет ли цена этому условию, и передать ее в качестве первого аргумента для filter(). Вторым аргументом может быть prices.keys():
>>> prices = {'apple': 0.40, 'orange': 0.35, 'banana': 0.25}
>>> def has_low_price(price):
... return prices[price] < 0.4
...
>>> low_price = list(filter(has_low_price, prices.keys()))
>>> low_price
['orange', 'banana']
Использование collections.ChainMap
collections
– полезный модуль из стандартной библиотеки Python, предоставляющий специализированные типы данных контейнеров. Одним из таких типов данных является ChainMap, который является словарным классом для создания единого представления нескольких сопоставлений (например, словарей). С ChainMap вы можете сгруппировать несколько словарей вместе, чтобы создать одно обновляемое представление.
Теперь предположим, что у вас есть два (или более) словаря, и вам нужно перебирать их вместе как один. Для этого вы можете создать объект ChainMap и инициализировать его своими словарями:
>>> from collections import ChainMap
>>> fruit_prices = {'apple': 0.40, 'orange': 0.35}
>>> vegetable_prices = {'pepper': 0.20, 'onion': 0.55}
>>> chained_dict = ChainMap(fruit_prices, vegetable_prices)
>>> chained_dict # A ChainMap object
ChainMap({'apple': 0.4, 'orange': 0.35}, {'pepper': 0.2, 'onion': 0.55})
>>> for key in chained_dict:
... print(key, '->', chained_dict[key])
...
pepper -> 0.2
orange -> 0.35
onion -> 0.55
apple -> 0.4
После импорта ChainMap из collections вам необходимо создать объект ChainMap со словарями, которые вы хотите объединить в цепочку, а затем вы можете свободно перебирать полученный объект, как если бы вы делали это с обычным словарем.
Объекты ChainMap также реализуют .keys(), values() и .items(), как это делает стандартный словарь, поэтому вы можете использовать эти методы для итерации по словарному объекту, сгенерированному ChainMap, точно так же, как вы это делаете с обычным словарь:
>>> for key, value in chained_dict.items():
... print(key, '->', value)
...
apple -> 0.4
pepper -> 0.2
orange -> 0.35
onion -> 0.55
Использование itertools
Iterotools – модуль, который предоставляет некоторые полезные инструменты для выполнения итерационных задач. Давайте посмотрим, как можно использовать некоторые из них для перебора словаря в Python.
Циклическая итерация с помощью cycle()
Предположим, вы хотите перебрать словарь в Python, но вам нужно перебирать его несколько раз в одном цикле. Чтобы выполнить эту задачу, вы можете использовать itertools.cycle(iterable), который заставляет итератор возвращать элементы из iterable и сохранять копию каждого из них. Когда итерация исчерпана, cycle() возвращает элементы из сохраненной копии. Это выполняется циклически, поэтому вы можете остановить цикл.
В следующем примере вы будете перебирать элементы словаря три раза подряд:
>>> from itertools import cycle
>>> prices = {'apple': 0.40, 'orange': 0.35, 'banana': 0.25}
>>> times = 3 # Define how many times you need to iterate through prices
>>> total_items = times * len(prices)
>>> for item in cycle(prices.items()):
... if not total_items:
... break
... total_items -= 1
... print(item)
...
('apple', 0.4)
('orange', 0.35)
('banana', 0.25)
('apple', 0.4)
('orange', 0.35)
('banana', 0.25)
('apple', 0.4)
('orange', 0.35)
('banana', 0.25)
Итерация с chain()
itertools также предоставляет функцию chain(*iterables), которая получает некоторые итерируемые аргументы в качестве аргументов и создает итератор, который возвращает элементы из итерируемого объекта до тех пор, пока он не будет исчерпан, а затем итерирует по следующему итерируемуго объекту и т. д., пока все они не будут исчерпаны.
Это позволяет вам перебирать несколько словарей в цепочке, как в случае с collections.ChainMap:
>>> from itertools import chain
>>> fruit_prices = {'apple': 0.40, 'orange': 0.35, 'banana': 0.25}
>>> vegetable_prices = {'pepper': 0.20, 'onion': 0.55, 'tomato': 0.42}
>>> for item in chain(fruit_prices.items(), vegetable_prices.items()):
... print(item)
...
('apple', 0.4)
('orange', 0.35)
('banana', 0.25)
('pepper', 0.2)
('onion', 0.55)
('tomato', 0.42)
Также возможно использовать .keys() или .values(), в зависимости от ваших потребностей, с условием быть однородным: если вы используете .keys() в качестве аргумента для chain(), то вам нужно использовать .keys( ) для остальных из них.
Использование оператора распаковки словаря (**)
Python 3.5 приносит новую и интересную функцию. PEP 448 – Additional Unpacking Generalizations могут упростить вашу жизнь, когда дело доходит до перебора нескольких словарей в Python. Давайте посмотрим, как это работает, на коротком примере.
Предположим, у вас есть два (или более) словаря, и вам нужно выполнять их итерацию вместе, без использования collection.ChainMap или itertools.chain(). В этом случае можно использовать оператор распаковки словаря (**), чтобы объединить два словаря в новый и затем выполнить итерацию по нему:
>>> fruit_prices = {'apple': 0.40, 'orange': 0.35}
>>> vegetable_prices = {'pepper': 0.20, 'onion': 0.55}
>>> # How to use the unpacking operator **
>>> {**vegetable_prices, **fruit_prices}
{'pepper': 0.2, 'onion': 0.55, 'apple': 0.4, 'orange': 0.35}
>>> # You can use this feature to iterate through multiple dictionaries
>>> for k, v in {**vegetable_prices, **fruit_prices}.items():
... print(k, '->', v)
...
pepper -> 0.2
onion -> 0.55
apple -> 0.4
orange -> 0.35
Важно отметить, что если словари, которые вы пытаетесь объединить, имеют повторяющиеся или общие ключи, то значения самого послденего словаря будут преобладать:
>>> vegetable_prices = {'pepper': 0.20, 'onion': 0.55}
>>> fruit_prices = {'apple': 0.40, 'orange': 0.35, 'pepper': .25}
>>> {**vegetable_prices, **fruit_prices}
{'pepper': 0.25, 'onion': 0.55, 'apple': 0.4, 'orange': 0.35}
Заключение
В этой статье мы основы того, как перебирать словарь в Python, а также некоторые более продвинутые методы и стратегии!
Вы узнали:
- Что такое словари, а также некоторые их основные функции и детали реализации
- Каковы основные способы перебора словаря в Python:
- Какие задачи вы можете выполнить, итерируя словарь
- Как использовать некоторые более сложные методы и стратегии для перебора словаря
No Comments