Словари в Python: полное практическое руководство

Материал основан на разборе Real Python. Ниже — главное и практические шаги, которые можно быстро применить в работе.


Содержание
  1. Почему словари так важны в Python
  2. С чего начать работу со словарями Python
  3. Создание словарей в Python
  4. Литералы словарей
  5. Конструктор dict()
  6. Использование метода класса .fromkeys()
  7. Доступ к значениям словаря
  8. Постепенное заполнение словарей
  9. Назначение ключей вручную
  10. Добавление ключей в цикле for
  11. Создание словарей с помощью включений
  12. Изучение методов класса dict
  13. Получение данных из словарей
  14. Добавление пар ключ-значение и обновление словарей
  15. Удаление данных из словарей
  16. Использование операторов со словарями
  17. Принадлежность: in и not in
  18. Использование встроенных функций со словарями
  19. Проверка истинности данных в словарях: all() и any()
  20. Определение количества элементов словаря: len()
  21. Поиск минимального и максимального значений: min() и max()
  22. Сортировка словарей по ключам, значениям и элементам: sorted()
  23. Суммирование значений словаря: sum()
  24. Итерация по словарям
  25. Обход словарей по ключам
  26. Итерация по значениям словаря
  27. Цикл по элементам словаря
  28. Когда использовать keys(), values() и items()

Почему словари так важны в Python

Словари Python — это мощный встроенный тип данных, который позволяет хранить пары ключ-значение для эффективного извлечения и обработки данных. Изучение словарей необходимо разработчикам, которые хотят эффективно обрабатывать данные. В этом руководстве вы узнаете, как создавать словари с помощью литералов и конструктора dict(), а также как использовать операторы Python и встроенные функции для работы с ними.

Изучив словари Python, вы сможете получать доступ к значениям через поиск по ключу и изменять содержимое словаря с помощью различных методов. Эти знания пригодятся вам при обработке данных, управлении конфигурацией и работе с данными в форматах JSON и CSV.

К концу этого руководства вы поймёте, что:

Словарь в Python — это изменяемая коллекция пар ключ-значение, которая обеспечивает эффективное извлечение данных с использованием уникальных ключей.

Как dict(), так и {} могут создавать словари в Python. Используйте {} для лаконичного синтаксиса и dict() для динамического создания из итерируемых объектов.

dict() — это класс, используемый для создания словарей. Однако в Python его принято называть встроенной функцией.

.__dict__ — это специальный атрибут в Python, который хранит записываемые атрибуты объекта в виде словаря.

Python dict реализован в виде хэш-таблицы (hashmap), что обеспечивает быстрый поиск по ключам.

Чтобы получить максимальную пользу от этого руководства, вы должны быть знакомы с базовым синтаксисом Python и такими концепциями, как переменные, циклы и встроенные функции. Также будет полезен некоторый опыт работы с базовыми типами данных Python.

По этой теме полезно отдельно посмотреть Составьте еженедельное расписание занятий, чтобы расширить контекст и сравнить подходы.

По этой теме полезно отдельно посмотреть Аннотации типов для декораторов в Python, чтобы расширить контекст и сравнить подходы.

С чего начать работу со словарями Python

Словари — один из наиболее важных и полезных встроенных типов данных Python. Они предоставляют изменяемую коллекцию пар ключ-значение, которая позволяет эффективно получать доступ к значениям и изменять их через соответствующие ключи:

>> config = { … "color" : "green" , … "width" : 42 , … "height" : 100 , … "font" : "Courier" , … } >>> # Получить значение через его ключ >>> config [ "color" ] 'green' >>> # Обновить значение >>> config [ "font" ] = "Helvetica" >>> config { 'color': 'green', 'width': 42, 'height': 100, 'font': 'Helvetica' }

Словарь Python состоит из коллекции пар ключ-значение, где каждый ключ соответствует своему связанному значению. В этом примере "color" — это ключ, а "green" — связанное значение.

Словари являются фундаментальной частью Python. Вы найдёте их в основе таких концепций, как области видимости и пространства имён, что можно увидеть с помощью встроенных функций globals() и locals():

>> globals () { '__name__': '__main__', '__doc__': None, '__package__': None, … }

Функция globals() возвращает словарь, содержащий пары ключ-значение, которые сопоставляют имена с объектами, находящимися в текущей глобальной области видимости.

Python также использует словари для поддержки внутренней реализации классов. Рассмотрим следующий демонстрационный класс:

>> class Number : … def __init__ ( self , value ): … self . value = value … >>> Number ( 42 ) . __dict__ {'value': 42}

Специальный атрибут .__dict__ — это словарь, который сопоставляет имена атрибутов с их соответствующими значениями в классах и объектах Python. Такая реализация делает поиск атрибутов и методов быстрым и эффективным в объектно-ориентированном коде.

Вы можете использовать словари для решения многих задач программирования в вашем коде Python. Они пригодятся при обработке файлов CSV и JSON, работе с базами данных, загрузке файлов конфигурации и во многих других случаях.

Словари Python обладают следующими характеристиками:

Изменяемые (Mutable): Значения словаря можно обновлять на месте.

Динамические (Dynamic): Словари могут увеличиваться и уменьшаться по мере необходимости.

Эффективные (Efficient): Они реализованы в виде хэш-таблиц, что обеспечивает быстрый поиск по ключу.

Упорядоченные (Ordered): Начиная с Python 3.7, словари хранят свои элементы в том же порядке, в котором они были вставлены.

Ключи словаря имеют ряд ограничений. Они должны быть:

Хэшируемыми (Hashable): Это означает, что вы не можете использовать нехэшируемые объекты, такие как списки, в качестве ключей словаря.

Уникальными (Unique): Это означает, что в ваших словарях не будет дублирующихся ключей.

Напротив, значения в словаре не имеют ограничений. Они могут быть любого типа Python, включая другие словари, что делает возможным создание вложенных словарей.

Словари — это коллекции пар. Поэтому вы не можете вставить ключ без соответствующего значения и наоборот. Поскольку они идут в паре, вы всегда должны вставлять ключ вместе с соответствующим значением.

Примечание: В некоторых ситуациях вам может потребоваться добавить ключи в словарь, не решив, каким должно быть связанное значение. В таких случаях вы можете использовать метод .setdefault() для создания ключей со значением по умолчанию или значением-заполнителем.

На практике вы можете использовать словарь, когда вам нужна эффективная и изменяемая структура данных, которая сопоставляет ключи со значениями. В следующих разделах вы узнаете, как создавать и использовать словари в вашем коде Python.

Создание словарей в Python

Создавать словари в Python можно несколькими способами в зависимости от ваших потребностей. Наиболее распространённый способ — использовать литералы словарей, представляющие собой разделённую запятыми последовательность пар ключ-значение в фигурных скобках. Второй способ — использовать конструктор dict(), который позволяет создавать словари из итерируемых объектов с парами ключ-значение, других отображений или последовательности именованных аргументов. Он также позволяет создавать пустые словари при вызове без аргументов.

В следующих разделах вы подробнее разберёте, как создавать словари Python с помощью литералов и конструктора dict().

Литералы словарей

Словарь можно определить, заключив разделённую запятыми последовательность пар ключ-значение в фигурные скобки ( {} ). Для разделения ключей и их значений необходимо использовать двоеточие ( : ). Вот синтаксис литерала словаря:

{ < key_1 > : < value_1 > , < key_2 > : < value_2 > , … , < key_N > : < value_N > , } Ключи и значения являются полностью необязательными, что означает возможность использовать пустую пару фигурных скобок для создания пустого словаря. Далее идут ключи, двоеточие и значение, связанное с текущим ключом. Для разделения пар используется запятая.

Ключи должны быть хешируемыми объектами, такими как числа, строки или кортежи. Хешируемость означает, что они могут быть переданы в хеш-функцию. Хеш-функция принимает данные произвольного размера и отображает их в значение фиксированного размера, называемое хеш-значением — или просто хешем, — которое используется для поиска в таблице и сравнения. В Python встроенные неизменяемые типы данных являются хешируемыми, а изменяемые типы — нехешируемыми.

Примечание: В множествах Python также используются фигурные скобки для определения их литералов, однако они заключают отдельные элементы, а не пары ключ-значение. Для создания пустого множества необходимо использовать set() вместо пустой пары фигурных скобок, поскольку этот синтаксис зарезервирован для пустых словарей.

Следующий код определяет словарь, который сопоставляет города или штаты с названиями соответствующих команд Главной лиги бейсбола (MLB):

>> MLB_teams = { … "Colorado" : "Rockies" , … "Chicago" : "White Sox" , … "Boston" : "Red Sox" , … "Minnesota" : "Twins" , … "Milwaukee" : "Brewers" , … "Seattle" : "Mariners" , … } В качестве ключей словаря можно использовать только хешируемые объекты Python. Следующий пример показывает словарь с целочисленными, вещественными и булевыми объектами в качестве ключей:

>> { 42 : "aaa" , 2.78 : "bbb" , True : "ccc" } {42: 'aaa', 2.78: 'bbb', True: 'ccc'} В качестве ключей можно использовать даже такие объекты, как типы данных и функции:

>> types = { int : 1 , float : 2 , bool : 3 } >>> types {<class 'int'>: 1, <class 'float'>: 2, <class 'bool'>: 3} >>> types [ float ] 2 >>> types [ bool ] 3 Однако нехешируемые объекты использовать в качестве ключей нельзя. При попытке сделать это вы получите ошибку:

>> {[ 1 , 2 ]: "A list as a key? Hmm…" } Traceback (most recent call last): … TypeError : unhashable type: 'list' Списки Python являются нехешируемыми, поскольку любые изменения их содержимого изменили бы их хеш-значение, нарушая требование о том, что хеш-значения должны оставаться постоянными для хешируемых типов. На практике нельзя использовать никакой изменяемый тип данных в качестве ключа в словаре. Это означает, что списки, множества и сами словари не допускаются.

Если вам нужно использовать последовательности в качестве ключей словаря, можно использовать кортежи, поскольку кортежи являются неизменяемыми:

>> a_dict = {( 1 , 1 ): "a" , ( 1 , 2 ): "b" , ( 2 , 1 ): "c" , ( 2 , 2 ): "d" } >>> a_dict [( 1 , 1 )] 'a' >>> a_dict [( 2 , 1 )] 'c' Несмотря на то что кортежи являются неизменяемыми, они могут содержать изменяемые объекты. Нельзя использовать кортеж, содержащий изменяемые объекты, в качестве ключа словаря:

>> {( 1 , [ 1 , 1 ]): "a" } Traceback (most recent call last): … TypeError : unhashable type: 'list' В этом примере кортеж, который вы пытаетесь использовать в качестве ключа словаря, содержит список. В результате кортеж больше не является хешируемым, поэтому вы получаете ошибку.

Дублирующиеся ключи не допускаются в типе данных dict в Python. Из-за этого ограничения при присвоении значения существующему ключу вы не добавите второй экземпляр ключа. Вместо этого вы замените ранее связанное значение новым.

Например, предположим, что в данном городе есть вторая команда MLB. Вы можете попытаться добавить вторую команду, присвоив её тому же ключу:

>> MLB_teams [ "Chicago" ] = "Cubs" >>> MLB_teams { 'Colorado': 'Rockies', 'Chicago': 'Cubs', 'Boston': 'Red Sox', 'Minnesota': 'Twins', 'Milwaukee': 'Brewers', 'Seattle': 'Mariners', } В этом примере вы пытаетесь добавить новую пару ключ-значение для второй команды MLB в Чикаго. Однако происходит следующее: вы заменяете старое название команды ( "White Sox" ) новым ( "Cubs" ).

Аналогично, если вы указываете ключ второй раз при создании словаря, второе вхождение переопределит первое:

>> MLB_teams = { … "Colorado" : "Rockies" , … "Chicago" : "White Sox" , … "Chicago" : "Cubs" , … "Boston" : "Red Sox" , … "Minnesota" : "Twins" , … "Milwaukee" : "Brewers" , … "Seattle" : "Mariners" , … } >>> MLB_teams { 'Colorado': 'Rockies', 'Chicago': 'Cubs', # "White Sox" is not present 'Boston': 'Red Sox', 'Minnesota': 'Twins', 'Milwaukee': 'Brewers', 'Seattle': 'Mariners' } В этом примере ваш словарь в итоге содержит пару "Chicago": "Cubs", поскольку она была вставлена после "Chicago": "White Sox" с тем же ключом.

В отличие от ключей словаря, для значений словаря нет никаких ограничений. Буквально никаких. Значением словаря может быть объект любого типа, включая изменяемые типы, такие как списки и словари, а также пользовательские объекты:

>> class Point : … def __init__ ( self , x , y ): … self . x = x … self . y = y … >>> { … "colors" : [ "red" , "green" , "blue" ], … "plugins" : { "py_code" , "dev_sugar" , "fasting_py" }, … "timeout" : 3 , … "position" : Point ( 42 , 21 ), … } В этом примере вы создаёте словарь со списком, множеством, целым числом и пользовательским объектом в качестве значений. Все эти объекты работают, поскольку для значений нет ограничений.

Также нет ограничений на то, чтобы конкретное значение встречалось в словаре несколько раз:

>> { 0 : "a" , 1 : "a" , 2 : "a" , 3 : "a" } {0: 'a', 1: 'a', 2: 'a', 3: 'a'} В этом примере ваш словарь содержит несколько экземпляров буквы a в качестве значения. Это совершенно допустимо, поскольку на значения не распространяется требование уникальности.

Конструктор dict()

Словари также можно создавать с помощью конструктора dict(). Аргументами для dict() могут служить последовательность именованных аргументов, другое отображение или итерируемый объект с парами ключ-значение. Вот сигнатуры конструктора:

dict () dict ( kwargs ) dict ( mapping , kwargs ) dict ( iterable , ** kwargs ) Если вызвать конструктор dict() без аргументов, вы получите пустой словарь:

>> dict () {} В большинстве случаев для создания пустых словарей используется пустая пара фигурных скобок. Однако в некоторых ситуациях использование конструктора может быть более явным.

Если ключи вашего словаря являются строками, представляющими допустимые идентификаторы Python, их можно указать в качестве именованных аргументов. Вот как можно создать словарь MLB_teams с помощью этого подхода:

>> MLB_teams = dict ( … Colorado = "Rockies" , … Chicago = "White Sox" , … Boston = "Red Sox" , … Minnesota = "Twins" , … Milwaukee = "Brewers" , … Seattle = "Mariners" , … ) >>> MLB_teams { 'Colorado': 'Rockies', 'Chicago': 'White Sox', 'Boston': 'Red Sox', 'Minnesota': 'Twins', 'Milwaukee': 'Brewers', 'Seattle': 'Mariners' } Ещё раз: для создания словаря с помощью именованных аргументов ключи должны быть строками, содержащими допустимые имена Python. В противном случае они не будут работать в качестве имён аргументов. Это синтаксическое ограничение Python.

Также можно создать словарь из итерируемого объекта с парами ключ-значение. Вот как можно создать словарь MLB_teams таким способом:

>> MLB_teams = dict ( … [ … ( "Colorado" , "Rockies" ), … ( "Chicago" , "White Sox" ), … ( "Boston" , "Red Sox" ), … ( "Minnesota" , "Twins" ), … ( "Milwaukee" , "Brewers" ), … ( "Seattle" , "Mariners" ), … ] … ) >>> MLB_teams { 'Colorado': 'Rockies', 'Chicago': 'White Sox', 'Boston': 'Red Sox', 'Minnesota': 'Twins', 'Milwaukee': 'Brewers', 'Seattle': 'Mariners' } В этом примере вы создаёте словарь с помощью списка кортежей из двух элементов. Первый элемент выступает в роли ключа, а второй — связанного с ним значения.

Удобный способ создания словарей из последовательностей значений — объединить их с помощью встроенной функции zip() и затем вызвать dict(), как показано ниже:

>> places = [ … "Colorado" , … "Chicago" , … "Boston" , … "Minnesota" , … "Milwaukee" , … "Seattle" , … ] >>> teams = [ … "Rockies" , … "White Sox" , … "Red Sox" , … "Twins" , … "Brewers" , … "Mariners" , … ] >>> dict ( zip ( places , teams )) { 'Colorado': 'Rockies', 'Chicago': 'White Sox', 'Boston': 'Red Sox', 'Minnesota': 'Twins', 'Milwaukee': 'Brewers', 'Seattle': 'Mariners' } Функция zip() принимает один или несколько итерируемых объектов в качестве аргументов и возвращает кортежи, объединяющие элементы из каждого итерируемого объекта. Обратите внимание, что исходные данные должны храниться в упорядоченных последовательностях для корректной работы этой техники, поскольку порядок имеет принципиальное значение. В противном случае можно получить словарь, в котором ключи сопоставлены со значениями неверно.

Использование метода класса .fromkeys()

Тип данных dict имеет метод класса .fromkeys(), который позволяет создавать новые словари из итерируемого объекта с ключами и значения по умолчанию. Сигнатура метода выглядит следующим образом:

. fromkeys ( iterable , value = None , / ) Аргумент iterable предоставляет ключи, которые вы хотите включить в свой словарь. Несмотря на то что входной итерируемый объект может содержать дублирующиеся элементы, итоговый словарь будет иметь уникальные ключи, как обычно.

Аргумент value позволяет определить подходящее значение по умолчанию для всех ключей. По умолчанию этот аргумент равен None, что может служить хорошим значением по умолчанию в ряде сценариев. Вот пример создания нового словаря с помощью метода .fromkeys():

>> inventory = dict . fromkeys ([ "apple" , "orange" , "banana" , "mango" ], 0 ) >>> inventory {'apple': 0, 'orange': 0, 'banana': 0, 'mango': 0} В этом примере вы создаёте словарь для хранения инвентаря фруктов. Изначально у вас есть список фруктов в наличии, но нет соответствующих количеств. Поэтому вы используете 0 в качестве количества по умолчанию при вызове .fromkeys().

Доступ к значениям словаря

После того как вы создали словарь, вы можете получить доступ к его содержимому по ключам. Чтобы извлечь значение из словаря, вы можете указать соответствующий ключ в квадратных скобках ( [] ) после имени словаря:

>> MLB_teams [ "Minnesota" ] 'Twins' >>> MLB_teams [ "Colorado" ] 'Rockies' Вы можете обращаться к словарю по конкретным ключам, чтобы получить связанные с ними значения. Поиск по ключу в словарях — весьма эффективная операция, поскольку словари реализованы в виде хеш-таблиц.

Если вы обращаетесь к ключу, которого нет в словаре, Python вызывает исключение:

>> MLB_teams [ "Indianapolis" ] Traceback (most recent call last): … KeyError : 'Indianapolis' Когда вы пытаетесь получить доступ к ключу, которого не существует в словаре, вы получаете исключение KeyError.

Теперь предположим, что у вас есть следующий словарь с данными о человеке:

>> person = { … "first_name" : "John" , … "last_name" : "Doe" , … "age" : 35 , … "spouse" : "Jane" , … "children" : [ "Ralph" , "Betty" , "Bob" ], … "pets" : { "dog" : "Frieda" , "cat" : "Sox" }, … } Этот словарь содержит список и словарь в качестве части своих значений. Чтобы получить доступ к элементам вложенного списка, вы можете использовать соответствующий ключ, а затем нужный индекс. Чтобы получить доступ к паре ключ-значение во вложенном словаре, вы можете использовать внешний ключ, а затем внутренний:

>> person [ "children" ][ 0 ] 'Ralph' >>> person [ "children" ][ 2 ] 'Bob' >>> person [ "pets" ][ "dog" ] 'Frieda' >>> person [ "pets" ][ "cat" ] 'Sox' Используя ключ и индекс, вы можете получать доступ к элементам вложенных списков. Аналогично, используя внешний и внутренний ключи, вы можете получать доступ к значениям во вложенных словарях. При этом уровень вложенности определяет, сколько ключей или индексов вам придётся использовать.

Постепенное заполнение словарей

Словари Python — это динамически изменяемые структуры данных. Это означает, что вы можете динамически добавлять пары ключ-значение в свои словари, а Python позаботится об увеличении размера словаря за вас. Это свойство полезно, поскольку позволяет динамически заполнять словари данными.

При заполнении словарей существуют три распространённые техники, которые вы можете использовать. Вы можете:

Назначать ключи вручную

Добавлять ключи в цикле for

Создавать словарь с помощью включения

В следующих разделах вы узнаете, как использовать эти техники для заполнения словарей в Python.

Назначение ключей вручную

Иногда вы начинаете с создания пустого словаря с пустой парой фигурных скобок. Затем вы начинаете добавлять новые пары ключ-значение по одной. Рассмотрим следующий пример, в котором вы заполняете словарь данными о человеке:

>> person = {} >>> person [ "first_name" ] = "John" >>> person [ "last_name" ] = "Doe" >>> person [ "age" ] = 35 >>> person [ "spouse" ] = "Jane" >>> person [ "children" ] = [ "Ralph" , "Betty" , "Bob" ] >>> person [ "pets" ] = { "dog" : "Frieda" , "cat" : "Sox" } >>> person { 'first_name': 'John', 'last_name': 'Doe', 'age': 35, 'spouse': 'Jane', 'children': ['Ralph', 'Betty', 'Bob'], 'pets': {'dog': 'Frieda', 'cat': 'Sox'} } Вы можете вручную заполнять свои словари новыми парами ключ-значение, присваивая значения новым ключам. Внутренне Python создаст для вас пару ключ-значение. Имейте в виду, что ключи уникальны. Если вы присвоите новое значение существующему ключу, старое значение будет потеряно.

Добавление ключей в цикле for

Вы также встретите ситуации, когда цикл for является хорошим подходом для заполнения пустого словаря новыми данными. Например, предположим, что у вас есть диапазон чисел и вы хотите создать словарь, который сопоставляет каждое число с соответствующим значением его квадрата. Чтобы создать и заполнить словарь, вы можете использовать следующий код:

>> squares = {} >>> for integer in range ( 1 , 10 ): … squares [ integer ] = integer ** 2 … >>> squares {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81} В этом примере вы сначала создаёте пустой словарь с помощью пары фигурных скобок. Затем вы используете цикл для итерации по диапазону целых чисел. Внутри цикла вы заполняете словарь, используя числа в качестве ключей и значения квадратов в качестве соответствующих значений.

Создание словарей с помощью включений

В Python есть включения словарей (dictionary comprehensions) — ещё один отличный инструмент для создания и заполнения словарей с лаконичным синтаксисом. Вот как вы можете создать свой словарь квадратов с помощью включения:

>> squares = { integer : integer ** 2 for integer in range ( 1 , 10 )} >>> squares {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81} Включения словарей — это выражения, которые строят и возвращают новый словарь. В этом примере вы используете включение для создания словаря, который сопоставляет числа с их значениями квадратов.

Примечание: Чтобы узнать больше о включениях словарей, ознакомьтесь с руководством Python Dictionary Comprehensions: How and When to Use Them.

Включения предоставляют мощный способ создавать новые словари, преобразовывать и фильтровать существующие словари и многое другое. Это отличный инструмент, который стоит иметь в своём арсенале.

Изучение методов класса dict

В Python-словарях есть несколько методов, которые можно вызывать для выполнения распространённых операций: доступ к ключам, значениям и элементам. Также существуют методы для обновления и удаления значений. В следующих разделах вы познакомитесь с этими методами и узнаете, как использовать их в своём Python-коде.

Получение данных из словарей

Для начала вы узнаете о методах, которые можно использовать для доступа к данным, хранящимся в существующем словаре. Вы также познакомитесь с методами для получения отдельного ключа и извлечения всех значений, ключей и пар из словаря. Эти методы полезны в реальном программировании на Python.

Метод .get() предоставляет удобный способ получить значение, связанное с ключом, без предварительной проверки существования этого ключа. Ключ, который нужно найти, является первым аргументом .get(). Второй аргумент, необязательный, — это значение по умолчанию, которое будет использовано, если целевой ключ отсутствует в словаре. Обратите внимание, что значение по умолчанию параметра default равно None:

>>> inventory = { "apple" : 100 , "orange" : 80 , "banana" : 100 }
>>> inventory . get ( "apple" )
100
>>> print ( inventory . get ( "mango" ))
None

Если целевой ключ существует в словаре, вы получаете соответствующее значение. Если ключ не найден и вы не указали default, вы получаете None.

Можно также указать удобное значение для default:

>>> inventory . get ( "mango" , 0 )
0

В этом примере ключ "mango" отсутствует в словаре inventory. Из-за этого в качестве результата вы получаете пользовательское значение по умолчанию (0).

Метод .values() возвращает объект-представление словаря, который предоставляет динамическое представление значений в словаре:

>>> inventory = { "apple" : 100 , "orange" : 80 , "banana" : 100 }
>>> inventory . values ()
dict_values([100, 80, 100])

Объект dict_values содержит все значения из inventory. Обратите внимание, что любые повторяющиеся значения будут возвращены столько раз, сколько они встречаются.

Метод .keys() возвращает объект-представление словаря с динамическим представлением ключей целевого словаря:

>>> inventory = { "apple" : 100 , "orange" : 80 , "banana" : 100 }
>>> inventory . keys ()
dict_keys(['apple', 'orange', 'banana'])

Объект-представление dict_keys содержит все ключи словаря inventory. Поскольку ключи словаря уникальны, дублирующихся ключей не будет. Благодаря этой уникальности dict_keys также поддерживает операции над множествами, такие как объединение и пересечение. С другой стороны, dict_values не поддерживает операции над множествами, поскольку значения не гарантированно уникальны.

Метод .items() возвращает представление словаря, содержащее кортежи из ключей и значений. Первый элемент каждого кортежа — это ключ, а второй — связанное с ним значение:

>>> inventory = { "apple" : 100 , "orange" : 80 , "banana" : 100 }
>>> inventory . items ()
dict_items([('apple', 100), ('orange', 80), ('banana', 100)])

Объект-представление dict_items содержит пары ключ-значение вашего словаря inventory в виде двухэлементных кортежей формата (key, value).

Добавление пар ключ-значение и обновление словарей

Встроенный тип данных dict в Python также имеет методы для добавления и обновления пар ключ-значение. Для этой цели предназначены методы .setdefault() и .update(). Вы познакомитесь с ними в следующих разделах.

Метод .setdefault() позволяет устанавливать значения по умолчанию для ключей. Если key присутствует в словаре, метод возвращает связанное с ним значение. Если key отсутствует в словаре, он вставляется со значением default в качестве связанного значения. После этого метод возвращает default:

>>> inventory = { "apple" : 100 , "orange" : 80 }
>>> inventory . setdefault ( "apple" )
100
>>> print ( inventory . setdefault ( "mango" ))
None
>>> inventory
{'apple': 100, 'orange': 80, 'mango': None}
>>> inventory . setdefault ( "banana" , 0 )
0
>>> inventory
{'apple': 100, 'orange': 80, 'mango': None, 'banana': 0}

Когда вы вызываете .setdefault() с существующим ключом, вы получаете связанное с ним значение. Если ключ отсутствует, вы получаете None — значение по умолчанию — и вставляется новая пара ключ-значение. Если ключ отсутствует и вы указываете пользовательское значение по умолчанию, вы получаете это пользовательское значение по умолчанию и новую пару ключ-значение.

Метод .update() объединяет словарь с другим словарём или с итерируемым объектом из пар ключ-значение. Если other является словарём, то a_dict.update(other) объединяет записи из other в a_dict. Для каждого ключа в other возможен один из следующих результатов:

Если ключ отсутствует в a_dict, то пара ключ-значение из other добавляется в a_dict.

Если ключ присутствует в a_dict, то соответствующее значение в a_dict обновляется до значения из other.

Вот пример, показывающий объединение двух словарей:

>>> config = {
...     "color" : "green" ,
...     "width" : 42 ,
...     "height" : 100 ,
...     "font" : "Courier" ,
... }
>>> user_config = {
...     "path" : "/home" ,
...     "color" : "red" ,
...     "font" : "Arial" ,
...     "position" : ( 200 , 100 ),
... }
>>> config . update ( user_config )
>>> config
{ 'color': 'red', 'width': 42, 'height': 100, 'font': 'Arial', 'path': '/home', 'position': (200, 100) }

В этом примере вы обновляете словарь config содержимым словаря user_config. Обратите внимание, как существующие ключи были обновлены, а отсутствующие добавлены в конец config.

Аргумент other также может быть последовательностью пар ключ-значение:

>>> config . update ([( "width" , 200 ), ( "api_key" , 1234 )])
>>> config
{ 'color': 'red', 'width': 200, 'height': 100, 'font': 'Arial', 'path': '/home', 'position': (200, 100), 'api_key': 1234 }

Здесь вы передаёте список кортежей в качестве аргумента .update(). Метод обновляет существующие ключи или добавляет новые по мере необходимости.

Наконец, можно также вызвать .update() с именованными аргументами:

>>> config . update ( color = "yellow" , script = "__main__.py" )
>>> config
{ 'color': 'yellow', 'width': 200, 'height': 100, 'font': 'Arial', 'path': '/home', 'position': (200, 100), 'api_key': 1234, 'script': '__main__.py' }

В этом примере вы вызываете .update() с именованными аргументами, и метод обновляет существующие ключи или добавляет новые по мере необходимости.

Удаление данных из словарей

Удаление пар ключ-значение — ещё одна распространённая операция, которую может потребоваться выполнять над словарями. Для этого класс dict предоставляет несколько полезных методов. В следующих разделах вы познакомитесь с этими методами и узнаете, как они работают.

Метод .pop() удаляет пары ключ-значение по ключам. Если ключ существует, метод возвращает связанное с ним значение. С другой стороны, если ключ не существует и default не указан, вы получаете KeyError. В противном случае вы получаете значение по умолчанию:

>>> inventory = { "apple" : 100 , "orange" : 80 , "banana" : 100 }
>>> inventory . pop ( "apple" )
100
>>> inventory
{'orange': 80, 'banana': 100}
>>> inventory . pop ( "mango" )
Traceback (most recent call last):
    ...
KeyError : 'mango'
>>> inventory . pop ( "mango" , 0 )
0

Если целевой ключ отсутствует в словаре и указан необязательный аргумент default, то это значение возвращается и исключение не вызывается.

Когда нужно одновременно удалить элемент и сохранить его значение, обычно используют .pop(). Если нужно просто удалить элемент, как правило, используют оператор del:

>>> del inventory [ "banana" ]
>>> inventory
{'orange': 80}

В этом примере вы удаляете ключ "banana" и связанное с ним значение, не возвращая значение, как это делает .pop().

Метод .popitem() удаляет пару ключ-значение из словаря. Этот метод возвращает удалённую пару в виде кортежа формата (key, value). Пары удаляются в порядке LIFO (последним пришёл — первым ушёл):

>>> inventory = { "apple" : 100 , "orange" : 80 , "banana" : 100 }
>>> inventory . popitem ()
('banana', 100)
>>> inventory
{'apple': 100, 'orange': 80}
>>> inventory . popitem ()
('orange', 80)
>>> inventory
{'apple': 100}
>>> inventory . popitem ()
('apple', 100)
>>> inventory
{}

Вызов .popitem() удаляет пару ключ-значение из словаря и возвращает её в виде двухэлементного кортежа. Первый элемент — это ключ, второй — значение. Обратите внимание, что элементы удаляются справа налево, начиная с последнего добавленного элемента.

Примечание: В версиях Python до 3.7 метод .popitem() возвращал произвольную пару ключ-значение, поскольку до этой версии словари Python были неупорядоченными.

Если словарь пуст, .popitem() вызывает исключение KeyError:

>>> inventory . popitem ()
Traceback (most recent call last):
    ...
KeyError : 'popitem(): dictionary is empty'

Когда вы вызываете .popitem() на пустом словаре, вы получаете KeyError, поскольку удалять нечего.

Метод .clear() удаляет все элементы из словаря:

>>> inventory = { "apple" : 100 , "orange" : 80 , "banana" : 100 }
>>> inventory
{'apple': 100, 'orange': 80, 'banana': 100}
>>> inventory . clear ()
>>> inventory
{}

Вызов метода .clear() на существующем словаре удалит все текущие пары ключ-значение из словаря.

Метод .copy() возвращает поверхностную копию словаря:

>>> inventory = { "apple" : 100 , "orange" : 80 , "banana" : 100 }
>>> inventory_copy = inventory . copy ()
>>> inventory_copy
{'apple': 100, 'orange': 80, 'banana': 100}
>>> inventory_copy is inventory
False

Вызов .copy() создаёт новый объект словаря с теми же парами ключ-значение, что и оригинал. Обратите внимание, что копия независима от оригинала, что подтверждается проверкой идентичности с помощью is.

Примечание: Чтобы узнать больше о копировании объектов в Python, ознакомьтесь с материалом Shallow vs Deep Copying of Python Objects.

Имейте в виду, что .copy() создаёт только поверхностную копию, поэтому вложенные объекты, такие как списки или словари внутри оригинала, по-прежнему будут совместно использоваться копией и оригиналом.

Использование операторов со словарями

В Python есть несколько операторов, которые можно использовать со словарями. Наиболее примечательными из них являются операторы принадлежности, равенства и объединения. В следующих разделах вы узнаете, как эти операторы работают со словарями, написав и запустив несколько быстрых примеров.

Принадлежность: in и not in

Операторы принадлежности in и not in позволяют определить, находится ли заданный ключ, значение или элемент в словаре, в зависимости от целевого итерируемого объекта, который вы используете.

Примечание: Чтобы узнать больше о проверках принадлежности, ознакомьтесь с материалом Python's "in" and "not in" Operators: Check for Membership.

Например, чтобы проверить, что:

Ключ находится в словаре, вы можете использовать сам словарь или метод .keys() для предоставления целевого итерируемого объекта.

Значение находится в словаре, вы можете использовать метод .values() для предоставления целевого итерируемого объекта.

Элемент находится в словаре, вы можете использовать метод .items() для предоставления целевого итерируемого объекта.

Для иллюстрации предположим, что вы хотите проверить, находится ли заданный город в вашем словаре MLB_teams. Для этого вы можете использовать операторы in и not in с самим словарём или с методом .keys():

>>> MLB_teams = {
...     "Colorado" : "Rockies" ,
...     "Chicago" : "White Sox" ,
...     "Boston" : "Red Sox" ,
...     "Minnesota" : "Twins" ,
...     "Milwaukee" : "Brewers" ,
...     "Seattle" : "Mariners" ,
... }
>>> "Milwaukee" in MLB_teams
True
>>> "Indianapolis" in MLB_teams
False
>>> "Indianapolis" not in MLB_teams
True
>>> "Milwaukee" in MLB_teams . keys ()
True
>>> "Indianapolis" in MLB_teams . keys ()
False
>>> "Indianapolis" not in MLB_teams . keys ()
True

В первой проверке принадлежности вы проверяете, включён ли Milwaukee в словарь MLB_teams. Поскольку этот город есть в словаре, вы получаете True в качестве результата. Затем вы проверяете, является ли Indianapolis членом словаря, что возвращает False.

В этой первой серии примеров вы используете словарь в качестве целевого итерируемого объекта для операторов in и not in. Во второй серии примеров вы используете .keys(). Как видите, оба способа работают одинаково. Однако использование .keys() при проверке принадлежности является избыточным и немного менее эффективным, чем использование словаря напрямую.

Для сравнения времени выполнения нажмите, чтобы открыть сворачиваемый раздел ниже, и запустите скрипт на своём компьютере:

Сравнение проверки принадлежности для dict и dict.keys() Показать/Скрыть

Запустите этот скрипт, чтобы проверить скорость проверок принадлежности для dict и dict.keys():

import timeit
MLB_teams = {
    "Colorado" : "Rockies" ,
    "Chicago" : "White Sox" ,
    "Boston" : "Red Sox" ,
    "Minnesota" : "Twins" ,
    "Milwaukee" : "Brewers" ,
    "Seattle" : "Mariners" ,
}

Использование встроенных функций со словарями

В Python есть несколько встроенных функций, которые можно использовать для обработки словарей или работы с ними. Ниже приведена краткая сводка некоторых из этих функций:

Как видите, все эти функции преследуют разные цели. Кроме того, их можно использовать с различными компонентами словаря. В следующих разделах вы узнаете, как применять эти функции для обработки словарей Python.

Проверка истинности данных в словарях: all() и any()

Для начала предположим, что у вас есть словарь, который сопоставляет продукты с их количеством. Вы хотите узнать, все ли продукты есть в наличии. Чтобы это выяснить, можно использовать функцию all() со значениями словаря в качестве аргумента:

>> inventory = { "apple" : 100 , "orange" : 80 , "banana" : 100 , "mango" : 200 } >>> all ( inventory . values ()) True >>> # Update the stock >>> inventory [ "mango" ] = 0 >>> all ( inventory . values ()) False

В первом вызове all() вы получаете True, потому что все количества продуктов отличаются от 0. Во втором примере вы получаете False, потому что манго закончилось. Функцию any() можно использовать аналогичным образом.

Примечание: Чтобы узнать больше о all() и any(), ознакомьтесь со следующими руководствами:

Эти функции также можно использовать с ключами. Для этого можно использовать либо сам словарь напрямую, либо метод .keys(). Наконец, использование этих функций с элементами не имеет смысла, поскольку метод .items() возвращает непустые кортежи.

Определение количества элементов словаря: len()

Иногда нужно знать количество пар ключ-значение в существующем словаре. Встроенная функция len() возвращает именно это число:

>> MLB_teams = { … "Colorado" : "Rockies" , … "Chicago" : "White Sox" , … "Boston" : "Red Sox" , … "Minnesota" : "Twins" , … "Milwaukee" : "Brewers" , … "Seattle" : "Mariners" , … } >>> len ( MLB_teams ) 6

Когда вы используете словарь в качестве аргумента для len(), функция возвращает количество элементов в словаре. В этом примере входной словарь содержит шесть пар ключ-значение, поэтому результатом будет 6.

Поиск минимального и максимального значений: min() и max()

Если вам когда-либо понадобится найти минимальное и максимальное значение, хранящееся в словаре, можно использовать встроенные функции min() и max():

>> computer_parts = { … "CPU" : 299.99 , … "Motherboard" : 149.99 , … "RAM" : 89.99 , … "GPU" : 499.99 , … "SSD" : 129.99 , … "Power Supply" : 79.99 , … "Case" : 99.99 , … "Cooling System" : 59.99 , … } >>> min ( computer_parts . values ()) 59.99 >>> max ( computer_parts . values ()) 499.99

В этом примере вы используете функции min() и max() для нахождения наименьшей и наибольшей цены с помощью метода .values(). Эти функции также можно использовать с ключами словаря и даже с элементами. Однако обратите внимание, что эти функции в основном применяются с числовыми значениями.

Сортировка словарей по ключам, значениям и элементам: sorted()

Сортировка элементов словаря может быть ещё одним распространённым требованием. Для этого можно использовать встроенную функцию sorted(). Для иллюстрации предположим, что у вас есть словарь, сопоставляющий имена студентов с их средними оценками, и вы хотите отсортировать данные по оценкам.

Вот как можно выполнить эту сортировку:

>> students = { … "Alice" : 89.5 , … "Bob" : 76.0 , … "Charlie" : 92.3 , … "Diana" : 84.7 , … "Ethan" : 88.9 , … "Fiona" : 95.6 , … "George" : 73.4 , … "Hannah" : 81.2 , … } >>> dict ( sorted ( students . items (), key = lambda item : item [ 1 ])) { 'George': 73.4, 'Bob': 76.0, 'Hannah': 81.2, 'Diana': 84.7, 'Ethan': 88.9, 'Alice': 89.5, 'Charlie': 92.3, 'Fiona': 95.6 } >>> dict ( sorted ( students . items (), key = lambda item : item [ 1 ], reverse = True )) { 'Fiona': 95.6, 'Charlie': 92.3, 'Alice': 89.5, 'Ethan': 88.9, 'Diana': 84.7, 'Hannah': 81.2, 'Bob': 76.0, 'George': 73.4 }

Функция sorted() возвращает список отсортированных значений, поэтому её вызов оборачивается в dict() для построения нового отсортированного словаря. В первом вызове вы сортируете элементы по значению в порядке возрастания. Для этого используется лямбда-функция, которая принимает кортеж из двух значений в качестве аргумента и возвращает второй элемент с индексом 1.

Во втором вызове sorted() вы устанавливаете аргумент reverse в значение True, чтобы функция возвращала список элементов в обратном порядке.

Примечание: Чтобы глубже погрузиться в сортировку словарей, ознакомьтесь с руководством Sorting a Python Dictionary: Values, Keys, and More.

Словарь также можно отсортировать по ключам:

>> dict ( sorted ( students . items (), key = lambda item : item [ 0 ])) { 'Alice': 89.5, 'Bob': 76.0, 'Charlie': 92.3, 'Diana': 84.7, 'Ethan': 88.9, 'Fiona': 95.6, 'George': 73.4, 'Hannah': 81.2 }

В этом примере вы сортируете словарь по ключам с помощью лямбда-функции, которая возвращает первое значение во входном кортеже.

Наконец, с помощью sorted() можно также отсортировать ключи и значения:

>> sorted ( students ) ['Alice', 'Bob', 'Charlie', 'Diana', 'Ethan', 'Fiona', 'George', 'Hannah'] >>> sorted ( students . values ()) [73.4, 76.0, 81.2, 84.7, 88.9, 89.5, 92.3, 95.6]

В первом вызове sorted() вы используете словарь в качестве аргумента. Это приводит к получению списка отсортированных ключей. Затем вы используете метод .values(), чтобы получить список отсортированных значений.

Суммирование значений словаря: sum()

Встроенную функцию sum() также можно использовать со словарями. Например, с её помощью можно суммировать числовые значения или ключи словаря.

Примечание: Чтобы узнать больше о sum(), ознакомьтесь с материалом Python's sum(): The Pythonic Way to Sum Values.

Для иллюстрации предположим, что у вас есть словарь с данными о ежедневных продажах и вы хотите узнать средний объём ежедневных продаж. В этом сценарии можно сделать следующее:

>> daily_sales = { … "Monday" : 1500 , … "Tuesday" : 1750 , … "Wednesday" : 1600 , … "Thursday" : 1800 , … "Friday" : 2000 , … "Saturday" : 2200 , … "Sunday" : 2100 , … } >>> sum ( daily_sales . values ()) / len ( daily_sales ) 1850.0

В этом примере вы используете функцию sum() для вычисления общего объёма продаж. Для этого применяется метод .values(). Затем вычисляется среднее значение с помощью len().

Итерация по словарям

Итерация по коллекциям данных, включая словари, — распространённая задача в программировании. В этом смысле словари Python весьма универсальны: они позволяют итерироваться по ключам, значениям и элементам.

Примечание: чтобы узнать больше об итерации по словарям, ознакомьтесь с руководством How to Iterate Through a Dictionary in Python.

В следующих разделах вы изучите основы итерации по словарям Python и их компонентам. Для начала вы начнёте с итерации по ключам словаря.

Обход словарей по ключам

Существует два разных способа итерации по ключам словаря. Можно использовать словарь напрямую или применить метод .keys(). Следующие примеры показывают, как использовать оба подхода:

students = {
    "Alice": 89.5,
    "Bob": 76.0,
    "Charlie": 92.3,
    "Diana": 84.7,
    "Ethan": 88.9,
    "Fiona": 95.6,
    "George": 73.4,
    "Hannah": 81.2,
}
for student in students:
    print(student)
for student in students.keys():
    print(student)

В этих примерах вы сначала итерируетесь по ключам словаря, используя словарь напрямую в заголовке цикла. Во втором цикле вы применяете метод .keys() для итерации по ключам. Оба цикла эквивалентны. Второй цикл более явный и читаемый, однако он может быть менее эффективным, чем первый, из-за дополнительного вызова метода.

Обратите внимание, что в обоих циклах вы также можете получить доступ к значениям словаря:

for student in students:
    print(student, "->", students[student])

Чтобы получить доступ к значениям при таком типе итерации, можно использовать исходный словарь и операцию поиска по ключу, как показано в выделенной строке.

Итерация по значениям словаря

Когда речь идёт об итерации по значениям словаря, для передачи данных в цикл можно использовать метод .values(). Для иллюстрации предположим, что вы работаете со словарём MLB_teams и вам нужно итерироваться только по названиям команд:

MLB_teams = {
    "Colorado": "Rockies",
    "Chicago": "White Sox",
    "Boston": "Red Sox",
    "Minnesota": "Twins",
    "Milwaukee": "Brewers",
    "Seattle": "Mariners",
}
for team in MLB_teams.values():
    print(team)

Для итерации по значениям словаря можно использовать метод .values(). В этом примере вы итерируетесь по зарегистрированным командам MLB одну за другой. Обратите внимание, что при использовании метода .values() вы не можете получить доступ к ключам словаря.

Цикл по элементам словаря

Наконец, во многих случаях вам потребуется одновременно получать и ключ, и связанное с ним значение. Для этого удобнее всего использовать метод .items(), который возвращает пары (ключ, значение):

for city, team in MLB_teams.items():
    print(city, "->", team)

Такой формат удобен, когда вам нужно выводить отчёты, формировать таблицы, проверять пары значений или преобразовывать словарь в другой вид. В отличие от цикла только по ключам или только по значениям, здесь вы сразу получаете полный контекст.

Если вы работаете с более сложными структурами данных, .items() особенно полезен при фильтрации и сортировке:

students = {
    "Alice": 89.5,
    "Bob": 76.0,
    "Charlie": 92.3,
}
for name, score in students.items():
    if score >= 90:
        print(name, score)

В этом примере цикл проходит по всем парам из словаря и выбирает только те элементы, которые соответствуют условию. Это один из самых частых паттернов в прикладном Python-коде.

Когда использовать keys(), values() и items()

Выбор метода зависит от того, какие данные вам действительно нужны в цикле:

  • Используйте сам словарь или .keys(), когда важны только ключи.
  • Используйте .values(), когда работаете только со значениями.
  • Используйте .items(), когда нужны и ключ, и значение одновременно.

Если задача сводится к проверке наличия ключа, обычно быстрее и проще использовать сам словарь напрямую. Если же вы готовите вывод, отчёт или преобразование структуры, .items() почти всегда оказывается самым читаемым вариантом.

Словари относятся к базовым инструментам Python. Они позволяют хранить и быстро извлекать данные по ключу, удобно обновляются на месте и хорошо подходят для конфигураций, промежуточных вычислений, JSON-структур и прикладных задач обработки данных.

В этом руководстве вы разобрали:

  • как создавать словари разными способами;
  • как читать, добавлять и обновлять пары ключ-значение;
  • как применять встроенные функции вроде len(), min(), max(), sorted() и sum();
  • как итерироваться по ключам, значениям и элементам словаря.

Практический вывод простой: если данные естественно представляются как соответствие между именем и значением, в Python почти всегда стоит начинать именно со словаря. Чем лучше вы понимаете dict, тем проще писать читаемый и быстрый код.

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x