Добавил:
Developer Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лекции / 6. Кортежи. Словари - Jupyter Notebook

.pdf
Скачиваний:
28
Добавлен:
15.12.2022
Размер:
483.73 Кб
Скачать

10.10.2022, 01:48

6. Кортежи. Словари - Jupyter Notebook

Кортежи. Словари.

Кортежи (tuples)

Кортежи встречаются не только в программировании, но и в математике. В математике под кортежем обычно понимают упорядоченное множество. Про множества мы немного говорили на прошлой лекции, множество ‒ это просто набор каких-то элементов, причем элементы множества не должны повторятся. Порядок элементов в множестве не важен: {1, 2, 3} и {3, 2, 1} ‒ это одно и то же множество. В кортеже мы точно знаем, какой элемент является первым, какой ‒ вторым, и так далее.

Внешне кортежи несильно отличаются от списков. Единственное внешнее отличие ‒ элементы кортежа заключаются в круглые, а не в квадратные скобочки.

In [1]:

1my_tuple = (1, 2, 4, 6, 9)

Кэлементам кортежа можно обращаться точно так же, как к элементам списка:

In [2]:

1 my_tuple[0]

Out[2]:

1

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

In [3]:

1 my_tuple[2] = 65

---------------------------------------------------------------------------

TypeError Traceback (most recent call last)

<ipython-input-3-a0083389ad43> in <module>

----> 1 my_tuple[2] = 65

TypeError: 'tuple' object does not support item assignment

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

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

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/6. Кортежи. Словари.ipynb

1/11

10.10.2022, 01:48

6. Кортежи. Словари - Jupyter Notebook

In [4]:

1 list(my_tuple) Out[4]:

[1, 2, 4, 6, 9]

И наоборот:

In [5]:

1 tuple([1,2,3]) Out[5]:

(1, 2, 3)

Словари (dictionaries)

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

Давайте представим, что нам нужно создать словарь, который мы будем использовать для программки к мюзиклу "Notre Dame de Paris" (да, меня не отпускает). Будем записывать в словарь prog пары соответствий герой-актер.

In [6]:

1 prog = {'Gringoire' : 'Pelletier', 'Frollo' : 'Lavoie', 'Phoebus': 'Fiori'}

Первый элемент в каждой паре (до двоеточия) назвается ключом (key), второй элемент в каждой паре (после двоеточия) ‒ значением (value). Посмотрим на словарь:

In [7]:

1 prog

Out[7]:

{'Gringoire': 'Pelletier', 'Frollo': 'Lavoie', 'Phoebus': 'Fiori'}

Обращение к элементам словаря

Как и в случае со списками или кортежами, к элементам словаря можно обращаться. Только выбор элемента производится не по индексу, а по ключу: сначала указываем название словаря, а потом в квадратных скобках ‒ ключ, по которому мы хотим вернуть значение. Например, выясним, кто играет роль Феба:

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/6. Кортежи. Словари.ipynb

2/11

10.10.2022, 01:48

6. Кортежи. Словари - Jupyter Notebook

In [8]:

1 prog['Phoebus'] Out[8]:

'Fiori'

А что будет, если мы запросим элемент по ключу, которого нет в словаре?

In [9]:

1 prog['Esmeralda']

---------------------------------------------------------------------------

KeyError

Traceback (most recent call last)

<ipython-input-9-a18d7b346a4e> in <module>

----> 1 prog['Esmeralda']

 

KeyError: 'Esmeralda'

 

В глубине души Python начинает грустно петь "Where is she, your Esmeralda?", но вместо эмоций выдает сухое KeyError. Ошибка ключа -- ну нет в словаре элемента с ключом Esmeralda!

Теперь представьте себе такую ситуацию: у нас есть список героев (ключей) и мы хотим в цикле вернуть по ним в фамилии актеров (значения). Какого-то одного из героев нет. Что произойдет? На каком-то этапе Python выдаст ошибку, мы вывалимся из цикла и на этом наша работа остановится. Обидно, да? Чтобы такого избежать, получать значение по ключу можно другим способом ‒ используя метод

.get() :

In [10]:

1 prog.get('Esmeralda') # ни результата, ни ошибки

Если выведем результат на экран явно, с помощью print() , увидим, что в случае, если пары с указанным ключом в словаре нет, Python выдаст значение None :

In [11]:

1 print(prog.get('Esmeralda'))

None

Удобство метода .get() заключается в том, что мы сами можем установить, какое значение будет возвращено, в случае, если пары с выбранным ключом нет в словаре. Так, вместо None мы можем вернуть строку Not found , и ломаться ничего не будет:

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/6. Кортежи. Словари.ipynb

3/11

10.10.2022, 01:48

6. Кортежи. Словари - Jupyter Notebook

In [10]:

1 prog.get('Esmeralda', 'Not found')

Out[10]:

'Not found'

Но недостающий элемент мы всегда можем добавить!

In [11]:

1 prog['Esmeralda'] = 'Segara'

2 prog

Out[11]:

{'Gringoire': 'Pelletier', 'Frollo': 'Lavoie', 'Phoebus': 'Fiori', 'Esmeralda': 'Segara'}

Внимание: Если элемент с указанным ключом уже существует, новый с таким же ключом не добавится! Ключ ‒ это уникальный идентификатор элемента. Если мы добавим в словарь новый элемент с уже существующим ключом, мы просто изменим старый ‒ словари являются изменяемыми объектами. Например, так (изменения в программе):

In [12]:

1 prog['Esmeralda'] = 'Noa'

2 prog

Out[12]:

{'Gringoire': 'Pelletier', 'Frollo': 'Lavoie', 'Phoebus': 'Fiori', 'Esmeralda': 'Noa'}

Раз элементами словаря являются пары ключ-значение, наверняка есть способ выбрать из словаря ключи и значения отдельно. Действительно, для этого есть методы .keys() и values() . Вызовем сначала все ключи:

In [13]:

1 prog.keys()

Out[13]:

dict_keys(['Gringoire', 'Frollo', 'Phoebus', 'Esmeralda'])

Объект, который мы только что увидели, очень похож на список. Но обычным списком на самом деле не является. Давайте попробуем выбрать первый элемент prog.keys() :

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/6. Кортежи. Словари.ipynb

4/11

10.10.2022, 01:48

6. Кортежи. Словари - Jupyter Notebook

In [14]:

 

1

 

keys = prog.keys()

 

 

 

2

 

keys[0]

 

 

 

 

 

---------------------------------------------------------------------------

TypeError

Traceback (most recent call last)

<ipython-input-14-5481656211fb> in <module>

1

keys = prog.keys()

 

----> 2

keys[0]

 

TypeError: 'dict_keys' object is not subscriptable

Не получается! Потому что полученный объект имеет специальный тип dict_keys , а не list . Но это всегда можно поправить, превратив объект dict_keys в список:

In [15]:

1 list(keys)[0] # получается!

Out[15]:

'Gringoire'

Аналогичным образом можно работать и со значениями:

In [16]:

1 prog.values()

Out[16]:

dict_values(['Pelletier', 'Lavoie', 'Fiori', 'Noa'])

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

числовой id студента-его оценка.

In [18]:

1 numbers = {1 : 7, 2 : 8, 3 : 9}

Обращаться к элементам мы будем, естественно, без кавычек, так как ключами являются числа:

In [19]:

1 numbers[1] # оценка студента с id равным 1

Out[19]:

7

Словари могут состоять из элементов смешанного типа. Например, вместо числового id можно явно записать имя студента:

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/6. Кортежи. Словари.ipynb

5/11

10.10.2022, 01:48

6. Кортежи. Словари - Jupyter Notebook

In [20]:

1 marks = {"Петя": 6, "Вася": 9}

In [21]:

1 marks["Петя"] Out[21]:

6

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

In [22]:

1 my_dict = {'swear' : ['клясться', 'ругаться'], 'dream' : ['спать', 'мечтать']}

По ключу мы получим значение в виде списка:

In [23]:

1 my_dict['swear'] Out[23]:

['клясться', 'ругаться']

Так как значением является список, можем отдельно обращаться к его элементам:

In [24]:

1 my_dict['swear'][0] # первый элемент

Out[24]:

'клясться'

А теперь давайте подумаем, как можно вывести на экран элементы словаря по очереди, в цикле. Первая попытка:

In [25]:

1 for k in prog:

2print(k)

Gringoire

Frollo

Phoebus

Esmeralda

Попытка не совсем удалась: на экран были выведены только ключи. А как вывести пары?

Задача: для каждого героя мюзикла из словаря prog вывести на экран сообщение вида

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/6. Кортежи. Словари.ipynb

6/11

10.10.2022, 01:48

6. Кортежи. Словари - Jupyter Notebook

Fiori plays the role of Phoebus

Решение: вспомним, что мы можем получать значения по ключу, указывая его в квадратных скобках, и проделаем это для всех ключей в словаре:

In [28]:

1 for k in prog:

2print(prog[k], "plays the role of", k)

Pelletier plays the role of Gringoire

Lavoie plays the role of Frollo

Fiori plays the role of Phoebus

Noa plays the role of Esmeralda

Упражнение полезное, но, на самом деле, существует специальный метод .items() , который позволяет обращаться сразу к парам элементов:

In [26]:

1 for k, v in prog.items():

2print(k, v)

Gringoire Pelletier

Frollo Lavoie

Phoebus Fiori

Esmeralda Noa

Для того, чтобы вывести и ключ, и значение, нужно в цикле for перечислить две переменные через запятую. И совсем не обязательно называть их k и v или key и value ; Python сам поймет, что первая переменная соответствует ключу, а вторая ‒ значению. Для примера решим поставленную выше задачу с помощью items() .

In [30]:

1 for hero, actor in prog.items():

2print(actor, "plays the role of", hero)

Pelletier plays the role of Gringoire

Lavoie plays the role of Frollo

Fiori plays the role of Phoebus

Noa plays the role of Esmeralda

Если мы посмотрим на prog.items() , мы увидим, что этот объект очень похож на список, состоящий из кортежей:

In [27]:

1 prog.items()

Out[27]:

dict_items([('Gringoire', 'Pelletier'), ('Frollo', 'Lavoie'), ('Phoebus', 'F iori'), ('Esmeralda', 'Noa')])

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/6. Кортежи. Словари.ipynb

7/11

10.10.2022, 01:48

6. Кортежи. Словари - Jupyter Notebook

Как и случае с методами .keys() и .values() , полученный объект не является "обычным" списком. Поэтому при необходимости его нужно будет превратить в список:

In [28]:

1 list(prog.items())

Out[28]:

[('Gringoire', 'Pelletier'), ('Frollo', 'Lavoie'), ('Phoebus', 'Fiori'), ('Esmeralda', 'Noa')]

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

оценка:

In [29]:

1 grades = {"Вася": 7, "Петя" : 9, "Коля" : 8, "Лена" : 8,

2"Василиса" : 10}

Ивыведем на экран имена тех студентов, у которых оценка равна 8:

In [32]:

1 for name, grade in grades.items():

2if grade == 8:

3print(name)

Коля

Лена

Только два человека: Коля и Лена. А как проверить, есть ли в словаре элемент с определенным ключом? Воспользоваться уже знакомым оператором in :

In [33]:

1 "Коля" in grades.keys()

Out[33]:

True

In [34]:

1 "Ваня" in grades.keys()

Out[34]:

False

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

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/6. Кортежи. Словари.ipynb

8/11

10.10.2022, 01:48

6. Кортежи. Словари - Jupyter Notebook

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

In [36]:

1 my_dict = {} # пустой словарь

In [37]:

1

my_dict[1] = 1

2

my_dict['hello'] = 'world'

In [38]:

1 my_dict # уже не пустой

Out[38]:

{1: 1, 'hello': 'world'}

Чтобы понять, каким образом еще можно получить словарь, полезно вспомнить, какие объекты лежат в dict_items() .

In [39]:

1 my_dict.items()

Out[39]:

dict_items([(1, 1), ('hello', 'world')])

Как мы уже обсуждали, dict_items() ‒ это список кортежей. Значит, из списка кортежей можно, в свою очередь, получить словарь!

In [40]:

1 my_new_dict = dict([(1, 2), ("Hello", "World")])

In [41]:

1 my_new_dict

Out[41]:

{1: 2, 'Hello': 'World'}

А можно ли получить словарь на основе списков? Да, но для начала давайте посмотрим, как из элементов разных списков составить пары значений. Пусть у нас есть два списка: список имен и список оценок.

In [47]:

1 students = ["Веня", "Сеня", "Каролина", "Сабрина"] 2 grades = [6, 7, 8, 9]

Воспользуемся функцией zip() .

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/6. Кортежи. Словари.ipynb

9/11

10.10.2022, 01:48

6. Кортежи. Словари - Jupyter Notebook

In [48]:

1 list(zip(students, grades))

Out[48]:

[('Веня', 6), ('Сеня', 7), ('Каролина', 8), ('Сабрина', 9)]

Как следует из названия, функция zip() действует как "молния": соединяет две части, то есть два списка, делая из пары списков список пар. Удобно то, что эта функция может соединять не только два списка, но и больше.

In [49]:

1 rating = [3, 2, 4, 1] # место в рейтинге

In [50]:

1 list(zip(students, grades, rating))

Out[50]:

[('Веня', 6, 3), ('Сеня', 7, 2), ('Каролина', 8, 4), ('Сабрина', 9, 1)]

Кроме того, функция zip() полезна тем, что помогает создавать словари:

In [46]:

1 gradebook = dict(list(zip(students, grades))) 2 gradebook

Out[46]:

{'Веня': 6, 'Каролина': 8, 'Сабрина': 9, 'Сеня': 7}

Еще о списках: функция enumerate()

Представим себе такую задачу: у нас есть список студентов, и хотим выводить на экран порядковый номер студента в списке и его имя.

In [51]:

1 students

Out[51]:

['Веня', 'Сеня', 'Каролина', 'Сабрина']

Как этого добиться, используя уже знакомые способы? Можно подключить к решению этой задачи функцию range() и задать интервал от 0 до числа элементов в списке (как мы помним, правый конец исключается):

127.0.0.1:8888/notebooks/EXONTOOLS/2/Доп. занятия/6. Кортежи. Словари.ipynb

10/11