# Словари

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

"Неупорядоченный" – значит, что последовательность расположения пар не важна, в следствие чего обращение к элементам по индексам невозможно.

В других языках структуры, схожие со словарями, называются по-другому. Например, в Java подобный тип данных называется отображением.

Чтобы представление о словаре стало более понятным, проведем аналогию с обычным словарем, например, англо-русским. На каждое английское слово в таком словаре есть русское слово-перевод: cat – кошка, dog – собака, table – стол и т. д. Если англо-русский словарь описать с помощью Python, то английские слова можно сделать ключами, а русские – их значениями:

```python
{'cat': 'кошка', 'dog': 'собака', 'bird': 'птица'}
```

Обратите внимание на фигурные скобки, именно с их помощью определяется словарь. Синтаксис словаря на Питоне описывается такой схемой:

![Словарь в Python (схема)](https://younglinux.info/sites/default/files/images/python/dictionary.gif)

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

```python
>>> a['cat']
'кошка'
>>> a['bird']
'птица'
```

Словари, как и списки, являются изменяемым типом данных: позволительно изменять, добавлять и удалять элементы (пары "ключ:значение"). Изначально словарь можно создать пустым (например, `d = {}`) и потом заполнить его элементами. Добавление и изменение имеет одинаковый синтаксис: `словарь[ключ] = значение`. Ключ может быть как уже существующим (тогда происходит изменение значения), так и новым (происходит добавление элемента словаря). Удаление элемента осуществляется с помощью встроенной оператора `del` языка Python.

```python
>>> a = {}
>>> a[1] = 2.34
>>> a[2] = 4.88
>>> a
{1: 2.34, 2: 4.88}
>>> a[1] = 3.01 
>>> a
{1: 3.01, 2: 4.88}
>>> del a[2]
>>> a
{1: 3.01}
```

**В словаре не может быть двух элементов с одинаковыми ключами. Однако могут быть одинаковые значения у разных ключей.**

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

```python
>>> nums = {'one': (1, 'I'), 'two': (2, 'II')}
>>> person1 = {'name': 'Tom', 'data': [4, 2.5]}
>>> person1['data'][0]
4
```

### Перебор элементов словаря в цикле for

Элементы словаря перебираются в цикле `for` также, как элементы других сложных объектов. Однако "по-умолчанию" извлекаются только ключи:

```python
>>> nums
{1: 'one', 2: 'two', 3: 'three'}
>>> for i in nums:
...     print(i)
...
1
2
3
```

Но по ключам всегда можно получить значения:

```python
>>> for i in nums:
...     print(nums[i])
...
one
two
three
```

С другой стороны у словаря как класса есть метод `items()`, который создает особую структуру, состоящую из кортежей. Каждый кортеж включает ключ и значение:

```python
>>> n = nums.items()
>>> n
dict_items([(1, 'one'), (2, 'two'), (3, 'three')])
```

В цикле `for` можно распаковывать кортежи, таким образом сразу извлекая как ключ, так и его значение:

```python
>>> for key, value in nums.items():
...     print(key, 'is', value)
...
1 is one
2 is two
3 is three
```

Методы словаря `keys()` и `values()` позволяют получить отдельно перечни ключей и значений. Так что если, например, надо перебрать только значения или только ключи, лучше воспользоваться одним из этих методов:

```python
>>> v_nums = []
>>> for v in nums.values():
...     v_nums.append(v)
...
>>> v_nums
['one', 'two', 'three']
```

### Методы словаря

Кроме рассмотренных выше трех методов `items()`, `keys()` и `values()` словари обладают еще восемью. Это методы `clear()`, `copy()`, `fromkeys()`, `get()`, `pop()`, `popitem()`, `setdefault()`, `update()`.

Метод `clear()` удаляет все элементы словаря, но не удаляет сам словарь. В итоге остается пустой словарь:

```python
>>> nums
{'one': (1, 'I'), 'two': (2, 'II')}
>>> nums.clear()
>>> nums
{}
```

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

```python
>>> n1 = {'a': 1, 'b': 2}
>>> n2 = n1
>>> n3 = n1.copy()
>>> n2['c'] = 3
>>> n1
{'a': 1, 'b': 2, 'c': 3}
>>> n2
{'a': 1, 'b': 2, 'c': 3}
>>> n3
{'a': 1, 'b': 2}
```

Метод `fromkeys()` позволяет создать словарь из списка, элементы которого становятся ключами. Применять метод можно как классу `dict`, так и к его объектам:

```python
>>> a = [1, 2, 3]
>>> c = dict.fromkeys(a)
>>> c
{1: None, 2: None, 3: None}
>>> d = dict.fromkeys(a, 10)
>>> d
{1: 10, 2: 10, 3: 10}
>>> c
{1: None, 2: None, 3: None}
```

Метод `get()` позволяет получить элемент по его ключу:

```python
>>> nums.get(1)
'one'
```

Равносильно `nums[1]`.

Метод `pop()` удаляет из словаря элемент по указанному ключу и возвращает значение удаленной пары. Метод `popitem()` не принимает аргументов, удаляет и возвращает произвольный элемент.

```python
>>> nums.pop(1)
'one'
>>> nums
{2: 'two', 3: 'three'}
>>> nums.popitem()
(2, 'two')
>>> nums
{3: 'three'}
```

С помощью `setdefault()` можно добавить элемент в словарь:

```python
>>> nums.setdefault(4, 'four')
'four'
>>> nums
{3: 'three', 4: 'four'}
```

Равносильно `nums[4] = 'four'`, если элемент с ключом 4 отсутствует в словаре. Если он уже есть, то `nums[4] = 'four'` перезапишет старое значение, `setdefault()` – нет.

С помощью `update()` можно добавить в словарь другой словарь:

```python
>>> nums.update({6: 'six', 7: 'seven'})
>>> nums
{3: 'three', 4: 'four', 6: 'six', 7: 'seven'}
```

Также метод обновляет значения существующих ключей. Включает еще ряд особенностей.

### Практическая работа

1. Создайте словарь, связав его с переменной school, и наполните данными, которые бы отражали количество учащихся в разных классах (1а, 1б, 2б, 6а, 7в и т. п.). Внесите изменения в словарь согласно следующему: а) в одном из классов изменилось количество учащихся, б) в школе появился новый класс, с) в школе был расформирован (удален) другой класс. Вычислите общее количество учащихся в школе.
2. Создайте словарь, где ключами являются числа, а значениями – строки. Примените к нему метод `items()`, полученный объект `dict_items` передайте в написанную вами функцию, которая создает и возвращает новый словарь, "обратный" исходному, т. е. ключами являются строки, а значениями – числа.
