0% нашли этот документ полезным (0 голосов)
20 просмотров591 страница

Python

Загружено:

katya.katenok04
Авторское право
© All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd
0% нашли этот документ полезным (0 голосов)
20 просмотров591 страница

Python

Загружено:

katya.katenok04
Авторское право
© All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd

SECOND EDITION

Introducing Python
Modern Computing in Simple Packages

Bill Lubanovic

Beijing Boston Farnham Sebastopol Tokyo


Простой
Python
Современный стиль программирования
Второе издание

Билл Любанович

2021
ȻȻɄ
ɍȾɄ
Ʌ

 ɅɸɛɚɧɨɜɢɱȻɢɥɥ
Ʌ ɉɪɨɫɬɨɣ3\WKRQɋɨɜɪɟɦɟɧɧɵɣɫɬɢɥɶɩɪɨɝɪɚɦɦɢɪɨɜɚɧɢɹɟɢɡɞ²ɋɉɛɉɢɬɟɪ
²ɫɢɥ² ɋɟɪɢɹ©Ȼɟɫɬɫɟɥɥɟɪɵ2¶5HLOO\ª 
 ,6%1
©ɉɪɨɫɬɨɣ3\WKRQªɩɨɡɧɚɤɨɦɢɬɜɚɫɫɨɞɧɢɦɢɡɫɚɦɵɯɩɨɩɭɥɹɪɧɵɯɹɡɵɤɨɜɩɪɨɝɪɚɦɦɢɪɨɜɚɧɢɹɄɧɢɝɚ
ɢɞɟɚɥɶɧɨɩɨɞɨɣɞɟɬɤɚɤɧɚɱɢɧɚɸɳɢɦɬɚɤɢɨɩɵɬɧɵɦɩɪɨɝɪɚɦɦɢɫɬɚɦɠɟɥɚɸɳɢɦɞɨɛɚɜɢɬɶ3\WKRQ
ɤɫɩɢɫɤɭɨɫɜɨɟɧɧɵɯɹɡɵɤɨɜ
Ʌɸɛɨɦɭɩɪɨɝɪɚɦɦɢɫɬɭɧɭɠɧɨɡɧɚɬɶɧɟɬɨɥɶɤɨɹɡɵɤɧɨɢɟɝɨɜɨɡɦɨɠɧɨɫɬɢȼɵɧɚɱɧɟɬɟɫɨɫɧɨɜ
3\WKRQɢɟɝɨɫɬɚɧɞɚɪɬɧɨɣɛɢɛɥɢɨɬɟɤɢɍɡɧɚɟɬɟɤɚɤɧɚɯɨɞɢɬɶɡɚɝɪɭɠɚɬɶɭɫɬɚɧɚɜɥɢɜɚɬɶɢɢɫɩɨɥɶɡɨɜɚɬɶ
ɫɬɨɪɨɧɧɢɟɩɚɤɟɬɵɂɡɭɱɢɬɟɥɭɱɲɢɟɩɪɚɤɬɢɤɢɬɟɫɬɢɪɨɜɚɧɢɹɨɬɥɚɞɤɢɩɨɜɬɨɪɧɨɝɨɢɫɩɨɥɶɡɨɜɚɧɢɹɤɨɞɚ
ɢɩɨɥɭɱɢɬɟɩɨɥɟɡɧɵɟɫɨɜɟɬɵɩɨɪɚɡɪɚɛɨɬɤɟɉɪɢɦɟɪɵɤɨɞɚɢɭɩɪɚɠɧɟɧɢɹɩɨɦɨɝɭɬɜɫɨɡɞɚɧɢɢɩɪɢɥɨ-
ɠɟɧɢɣɞɥɹɪɚɡɥɢɱɧɵɯɰɟɥɟɣ
16+ ȼɫɨɨɬɜɟɬɫɬɜɢɢɫɎɟɞɟɪɚɥɶɧɵɦɡɚɤɨɧɨɦɨɬɞɟɤɚɛɪɹɝʋɎɁ

 ȻȻɄ
 ɍȾɄ

ɉɪɚɜɚɧɚɢɡɞɚɧɢɟɩɨɥɭɱɟɧɵɩɨɫɨɝɥɚɲɟɧɢɸɫ2¶5HLOO\ȼɫɟɩɪɚɜɚɡɚɳɢɳɟɧɵɇɢɤɚɤɚɹɱɚɫɬɶɞɚɧɧɨɣɤɧɢɝɢɧɟɦɨɠɟɬ
ɛɵɬɶɜɨɫɩɪɨɢɡɜɟɞɟɧɚɜɤɚɤɨɣɛɵɬɨɧɢɛɵɥɨɮɨɪɦɟɛɟɡɩɢɫɶɦɟɧɧɨɝɨɪɚɡɪɟɲɟɧɢɹɜɥɚɞɟɥɶɰɟɜɚɜɬɨɪɫɤɢɯɩɪɚɜ

ɂɧɮɨɪɦɚɰɢɹ ɫɨɞɟɪɠɚɳɚɹɫɹ ɜ ɞɚɧɧɨɣ ɤɧɢɝɟ ɩɨɥɭɱɟɧɚ ɢɡ ɢɫɬɨɱɧɢɤɨɜ ɪɚɫɫɦɚɬɪɢɜɚɟɦɵɯ ɢɡɞɚɬɟɥɶɫɬɜɨɦ ɤɚɤ ɧɚ
ɞɟɠɧɵɟ Ɍɟɦ ɧɟ ɦɟɧɟɟ ɢɦɟɹ ɜ ɜɢɞɭ ɜɨɡɦɨɠɧɵɟ ɱɟɥɨɜɟɱɟɫɤɢɟ ɢɥɢ ɬɟɯɧɢɱɟɫɤɢɟ ɨɲɢɛɤɢ ɢɡɞɚɬɟɥɶɫɬɜɨ ɧɟ ɦɨɠɟɬ
ɝɚɪɚɧɬɢɪɨɜɚɬɶɚɛɫɨɥɸɬɧɭɸɬɨɱɧɨɫɬɶɢɩɨɥɧɨɬɭɩɪɢɜɨɞɢɦɵɯɫɜɟɞɟɧɢɣɢɧɟɧɟɫɟɬɨɬɜɟɬɫɬɜɟɧɧɨɫɬɢɡɚɜɨɡɦɨɠɧɵɟ
ɨɲɢɛɤɢɫɜɹɡɚɧɧɵɟɫɢɫɩɨɥɶɡɨɜɚɧɢɟɦɤɧɢɝɢɂɡɞɚɬɟɥɶɫɬɜɨɧɟɧɟɫɟɬɨɬɜɟɬɫɬɜɟɧɧɨɫɬɢɡɚɞɨɫɬɭɩɧɨɫɬɶɦɚɬɟɪɢɚɥɨɜ
ɫɫɵɥɤɢɧɚɤɨɬɨɪɵɟɜɵɦɨɠɟɬɟɧɚɣɬɢɜɷɬɨɣɤɧɢɝɟɇɚɦɨɦɟɧɬɩɨɞɝɨɬɨɜɤɢɤɧɢɝɢɤɢɡɞɚɧɢɸɜɫɟɫɫɵɥɤɢɧɚɢɧɬɟɪɧɟɬ
ɪɟɫɭɪɫɵɛɵɥɢɞɟɣɫɬɜɭɸɳɢɦɢ

,6%1ɚɧɝɥ $XWKRUL]HG5XVVLDQWUDQVODWLRQRIWKH(QJOLVKHGLWLRQRI,QWURGXFLQJ3\WKRQ(
 ,6%1‹%LOO/XEDQRYLF
 7KLVWUDQVODWLRQLVSXEOLVKHGDQGVROGE\SHUPLVVLRQRI2¶5HLOO\0HGLD,QF
 ZKLFKRZQVRUFRQWUROVDOOULJKWVWRSXEOLVKDQGVHOOWKHVDPH
,6%1 ‹ɉɟɪɟɜɨɞɧɚɪɭɫɫɤɢɣɹɡɵɤɈɈɈɂɡɞɚɬɟɥɶɫɬɜɨ©ɉɢɬɟɪª
 ‹ɂɡɞɚɧɢɟɧɚɪɭɫɫɤɨɦɹɡɵɤɟɨɮɨɪɦɥɟɧɢɟɈɈɈɂɡɞɚɬɟɥɶɫɬɜɨ©ɉɢɬɟɪª

 ‹ɋɟɪɢɹ©Ȼɟɫɬɫɟɥɥɟɪɵ2¶5HLOO\ª
ƒƸƨƺƲƶƭƹƶƬƭƸƮƨƵưƭ

Введение .....................................................................................................................................................26
Благодарности ..........................................................................................................................................33
Об авторе....................................................................................................................................................34

ǿȈșȚȤ,ǶșȕȖȊȣ3\WKRQ
Глава 1. Python: с чем его едят ...........................................................................................................36
Глава 2. Данные: типы, значения, переменные и имена ............................................................55
Глава 3. Числа ..........................................................................................................................................67
Глава 4. Выбираем с помощью оператора if ..................................................................................82
Глава 5. Текстовые строки ...................................................................................................................91
Глава 6. Создаем циклы с помощью ключевых слов while и for.......................................... 113
Глава 7. Кортежи и списки ............................................................................................................... 119
Глава 8. Словари и множества ........................................................................................................ 144
Глава 9. Функции ................................................................................................................................ 166
Глава 10. Ой-ой-ой: объекты и классы ......................................................................................... 194
Глава 11. Модули, пакеты и программы ...................................................................................... 224

ǿȈșȚȤ,,3\WKRQȕȈȗȘȈȒȚȐȒȍ
Глава 12. Обрабатываем данные..................................................................................................... 242
Глава 13. Календари и часы.............................................................................................................. 271
Глава 14. Файлы и каталоги............................................................................................................. 283
Глава 15. Данные во времени: процессы и конкурентность ................................................. 302
  DzȘȈȚȒȖȍșȖȌȍȘȎȈȕȐȍ

Глава 16. Данные в коробке: надежные хранилища ................................................................ 327


Глава 17. Данные в пространстве: сети ........................................................................................ 368
Глава 18. Распутываем Всемирную паутину ............................................................................. 400
Глава 19. Быть питонщиком ............................................................................................................ 431
Глава 20. Пи-Арт .................................................................................................................................. 474
Глава 21. За работой ........................................................................................................................... 487
Глава 22. Python в науке.................................................................................................................... 503
ǷȘȐȓȖȎȍȕȐȧ
Приложение А. Аппаратное и программное обеспечение для начинающих
программистов ...................................................................................................................................... 520
Приложение Б. Установка Python 3 ............................................................................................. 530
Приложение В. Нечто совершенно иное: async ........................................................................ 538
Приложение Г. Ответы к упражнениям ...................................................................................... 544
Приложение Д. Вспомогательные таблицы .............................................................................. 587
Эпилог ...................................................................................................................................................... 591
ƖƫƳƨƪƳƭƵưƭ

Введение .....................................................................................................................................................26
Для кого эта книга ............................................................................................................................27
Что нового во втором издании .....................................................................................................27
Структура книги ...............................................................................................................................28
Версии Python ...................................................................................................................................31
Условные обозначения....................................................................................................................31
Использование примеров кода ....................................................................................................32
От издательства.................................................................................................................................32

Благодарности ..........................................................................................................................................33

Об авторе....................................................................................................................................................34

ǿȈșȚȤ,ǶșȕȖȊȣ3\WKRQ
Глава 1. Python: с чем его едят ...........................................................................................................36
Тайны ....................................................................................................................................................36
Маленькие программы ...................................................................................................................38
Более объемная программа ...........................................................................................................40
Python в реальном мире .................................................................................................................44
Python против языка с планеты Х ..............................................................................................45
Почему же Python? ..........................................................................................................................48
Когда не стоит использовать Python .........................................................................................49
Python 2 против Python 3 ..............................................................................................................50
Установка Python..............................................................................................................................51
Запуск Python ....................................................................................................................................51
Интерактивный интерпретатор ............................................................................................51
Файлы Python .............................................................................................................................52
Что дальше? .................................................................................................................................53
  ǶȋȓȈȊȓȍȕȐȍ

Момент просветления.....................................................................................................................53
Читайте далее.....................................................................................................................................54
Упражнения ........................................................................................................................................54

Глава 2. Данные: типы, значения, переменные и имена ............................................................55


В Python данные являются объектами .....................................................................................55
Типы ......................................................................................................................................................56
Изменчивость ....................................................................................................................................57
Значения-литералы .........................................................................................................................58
Переменные ........................................................................................................................................58
Присваивание ....................................................................................................................................60
Переменные — это имена, а не локации....................................................................................61
Присваивание нескольким именам ............................................................................................64
Переназначение имени ...................................................................................................................64
Копирование ......................................................................................................................................64
Выбираем хорошее имя переменной .........................................................................................65
Читайте далее.....................................................................................................................................66
Упражнения ........................................................................................................................................66

Глава 3. Числа ..........................................................................................................................................67


Булевы значения...............................................................................................................................67
Целые числа........................................................................................................................................68
Числа-литералы..........................................................................................................................68
Операции с целыми числами .................................................................................................69
Целые числа и переменные ....................................................................................................71
Приоритет операций .................................................................................................................73
Системы счисления ...................................................................................................................74
Преобразования типов .............................................................................................................76
Насколько объемен тип int .....................................................................................................78
Числа с плавающей точкой ...........................................................................................................79
Математические функции .............................................................................................................80
Читайте далее.....................................................................................................................................81
Упражнения ........................................................................................................................................81

Глава 4. Выбираем с помощью оператора if ..................................................................................82


Комментируем с помощью символа #.......................................................................................82
Продлеваем строки с помощью символа \...............................................................................83
Сравниваем с помощью операторов if, elif и else ...................................................................84
Что есть истина? ...............................................................................................................................87
Выполняем несколько сравнений с помощью оператора in ..............................................88
ǶȋȓȈȊȓȍȕȐȍ  

Новое: I Am the Walrus ...................................................................................................................89


Читайте далее.....................................................................................................................................90
Упражнения ........................................................................................................................................90
Глава 5. Текстовые строки ...................................................................................................................91
Создаем строки с помощью кавычек .........................................................................................91
Создаем строки с помощью функции str() ..............................................................................94
Создаем escape-последовательности с помощью символа \ ..............................................94
Объединяем строки с использованием символа +................................................................96
Размножаем строки с помощью символа * ..............................................................................96
Извлекаем символ с помощью символов [ ]............................................................................97
Извлекаем подстроки, используя разделение ........................................................................98
Измеряем длину строки с помощью функции len().......................................................... 100
Разделяем строку с помощью функции split().................................................................... 100
Объединяем строки с помощью функции join() ................................................................ 101
Заменяем символы с использованием функции replace() .............................................. 101
Устраняем символы с помощью функции strip() ............................................................... 102
Поиск и выбор ................................................................................................................................ 103
Регистр .............................................................................................................................................. 104
Выравнивание................................................................................................................................. 105
Форматирование............................................................................................................................ 105
Старый стиль: % ...................................................................................................................... 106
Новый стиль: используем символы {} и функцию format() ..................................... 108
Самый новый стиль: f-строки ............................................................................................. 110
Что еще можно делать со строками......................................................................................... 111
Читайте далее.................................................................................................................................. 111
Упражнения ..................................................................................................................................... 111
Глава 6. Создаем циклы с помощью ключевых слов while и for.......................................... 113
Повторяем действия с помощью цикла while ...................................................................... 113
Прерываем цикл с помощью оператора break............................................................... 114
Пропускаем итерации, используя оператор continue ................................................ 114
Проверяем, завершился ли цикл раньше, с помощью блока else ........................... 115
Выполняем итерации с использованием ключевых слов for и in ................................. 115
Прерываем цикл с помощью оператора break............................................................... 116
Пропускаем итерации, используя оператор continue ................................................ 116
Проверяем, завершился ли цикл раньше, с помощью блока else ........................... 116
Генерируем числовые последовательности с помощью функции range() .......... 117
Прочие итераторы ......................................................................................................................... 118
Читайте далее.................................................................................................................................. 118
Упражнения ..................................................................................................................................... 118
  ǶȋȓȈȊȓȍȕȐȍ

Глава 7. Кортежи и списки ............................................................................................................... 119


Кортежи ............................................................................................................................................ 119
Создаем кортежи с помощью запятых и оператора () ............................................... 120
Создаем кортежи с помощью функции tuple() ............................................................ 121
Объединяем кортежи с помощью оператора + ............................................................. 121
Размножаем элементы с помощью оператора * .......................................................... 122
Сравниваем кортежи ............................................................................................................. 122
Итерируем по кортежам с помощью for и in ................................................................. 122
Изменяем кортеж .................................................................................................................... 122
Списки ............................................................................................................................................... 123
Создаем списки с помощью скобок [] .............................................................................. 123
Создаем список или преобразуем в список с помощью функции list()............... 123
Создаем список из строки с использованием функции split() ............................... 124
Получаем элемент с помощью конструкции [смещение] ......................................... 124
Извлекаем элементы с помощью разделения ............................................................... 125
Добавляем элемент в конец списка с помощью функции append() ...................... 126
Добавляем элемент на определенное место с помощью функции insert() ......... 126
Размножаем элементы с помощью оператора * ........................................................... 127
Объединяем списки с помощью метода extend() или оператора + ....................... 127
Изменяем элемент с помощью конструкции [смещение] ........................................ 128
Изменяем элементы с помощью разделения................................................................. 128
Удаляем заданный элемент с помощью оператора del ............................................... 129
Удаляем элемент по значению с помощью функции remove() ............................... 129
Получаем и удаляем заданный элемент с помощью функции pop() .................... 129
Удаляем все элементы с помощью функции clear() ................................................... 130
Определяем смещение по значению с помощью функции index() ....................... 130
Проверяем на наличие элемента в списке с помощью оператора in ..................... 131
Подсчитываем количество включений значения с помощью
функции count() ...................................................................................................................... 131
Преобразуем список в строку с помощью функции join() ....................................... 131
Меняем порядок элементов с помощью функций sort() или sorted() ................. 132
Получаем длину списка с помощью функции len() ................................................... 133
Присваиваем с помощью оператора = ............................................................................. 133
Копируем списки с помощью функций copy() и list() или путем
разделения ................................................................................................................................. 134
Копируем все с помощью функции deepcopy() ........................................................... 134
Сравниваем списки ............................................................................................................... 135
Итерируем по спискам с помощью операторов for и in ............................................. 136
ǶȋȓȈȊȓȍȕȐȍ  

Итерируем по нескольким последовательностям с помощью


функции zip() ........................................................................................................................... 137
Создаем список с помощью списковых включений ................................................... 138
Списки списков ....................................................................................................................... 140
Кортежи или списки? .................................................................................................................. 141
Включений кортежей не существует ...................................................................................... 141
Читайте далее.................................................................................................................................. 142
Упражнения ..................................................................................................................................... 142

Глава 8. Словари и множества ........................................................................................................ 144


Словари ............................................................................................................................................. 144
Создаем словарь с помощью {} ........................................................................................... 144
Создаем словарь с помощью функции dict() ................................................................ 145
Преобразуем с помощью функции dict() ....................................................................... 146
Добавляем или изменяем элемент с помощью конструкции [ключ] ................... 146
Получаем элемент словаря с помощью конструкции [ключ]
или функции get() .................................................................................................................. 148
Получаем все ключи с помощью функции keys() ....................................................... 148
Получаем все значения с помощью функции values()............................................... 149
Получаем все пары «ключ — значение» с помощью функции items() ................. 149
Получаем длину словаря с помощью функции len() ................................................. 149
Объединяем словари с помощью конструкции {**a, **b}......................................... 149
Объединяем словари
с помощью функции update() ............................................................................................. 150
Удаляем элементы по их ключу с помощью оператора del ...................................... 151
Получаем элемент по ключу и удаляем его с помощью функции pop() ............. 151
Удаляем все элементы с помощью функции clear() ................................................... 151
Проверяем на наличие ключа с помощью оператора in ............................................ 152
Присваиваем значения с помощью оператора = .......................................................... 152
Копируем значения с помощью функции copy() ........................................................ 152
Копируем все с помощью функции deepcopy() .......................................................... 153
Сравниваем словари .............................................................................................................. 154
Итерируем по словарям с помощью for и in .................................................................. 154
Включения словарей.............................................................................................................. 155
Множества ....................................................................................................................................... 156
Создаем множество с помощью функции set() ............................................................ 157
Преобразуем другие типы данных с помощью функции set() ................................ 157
Получаем длину множества с помощью функции len()............................................ 158
Добавляем элемент с помощью функции add() ........................................................... 158
Удаляем элемент с помощью функции remove() ......................................................... 158
  ǶȋȓȈȊȓȍȕȐȍ

Итерируем по множествам с помощью for и in ............................................................ 158


Проверяем на наличие значения с помощью оператора in ...................................... 158
Комбинации и операторы .................................................................................................... 159
Включение множества........................................................................................................... 162
Создаем неизменяемое множество с помощью функции frozenset() ................... 162
Структуры данных, которые мы уже рассмотрели ............................................................ 163
Создание крупных структур данных ...................................................................................... 164
Читайте далее.................................................................................................................................. 164
Упражнения ..................................................................................................................................... 165

Глава 9. Функции ................................................................................................................................ 166


Определяем функцию с помощью ключевого слова def .................................................. 166
Вызываем функцию с помощью скобок ................................................................................ 167
Аргументы и параметры .............................................................................................................. 167
None — это полезно................................................................................................................. 169
Позиционные аргументы ..................................................................................................... 170
Аргументы — ключевые слова ............................................................................................ 171
Указываем значение параметра по умолчанию ............................................................ 171
Получаем/разбиваем аргументы — ключевые слова с помощью символа * ...... 172
Получаем/разбиваем аргументы — ключевые слова с помощью
символов ** ............................................................................................................................... 174
Аргументы, передаваемые только по ключевым словам ........................................... 175
Изменяемые и неизменяемые аргументы ...................................................................... 176
Строки документации .................................................................................................................. 176
Функции — это объекты первого класса ............................................................................... 177
Внутренние функции ................................................................................................................... 179
Анонимные функции: лямбда-выражения ........................................................................... 181
Генераторы ....................................................................................................................................... 182
Функции-генераторы ............................................................................................................ 182
Включения генераторов........................................................................................................ 183
Декораторы ...................................................................................................................................... 183
Пространства имен и область определения ......................................................................... 186
Использование символов _ и __ в именах............................................................................ 188
Рекурсия ........................................................................................................................................... 188
Асинхронные функции................................................................................................................ 190
Исключения .................................................................................................................................... 190
Обрабатываем ошибки с помощью операторов try и except .................................... 191
Создаем собственные исключения ................................................................................... 192
Читайте далее.................................................................................................................................. 193
Упражнения ..................................................................................................................................... 193
ǶȋȓȈȊȓȍȕȐȍ  

Глава 10. Ой-ой-ой: объекты и классы ......................................................................................... 194


Что такое объекты ......................................................................................................................... 194
Простые объекты ........................................................................................................................... 195
Определяем класс с помощью ключевого слова class ................................................ 195
Атрибуты.................................................................................................................................... 196
Методы ....................................................................................................................................... 197
Инициализация ....................................................................................................................... 197
Наследование .................................................................................................................................. 198
Наследование от родительского класса .......................................................................... 199
Переопределение методов.................................................................................................... 200
Добавление метода ................................................................................................................. 201
Получаем помощь от своего родителя с использованием
метода super() ........................................................................................................................... 202
Множественное наследование............................................................................................ 203
Примеси ..................................................................................................................................... 205
В защиту self .................................................................................................................................... 205
Доступ к атрибутам....................................................................................................................... 206
Прямой доступ ......................................................................................................................... 206
Геттеры и сеттеры .................................................................................................................... 206
Свойства для доступа к атрибутам ................................................................................... 207
Свойства для вычисляемых значений ............................................................................. 209
Искажение имен для безопасности .................................................................................. 209
Атрибуты классов и объектов ............................................................................................. 210
Типы методов .................................................................................................................................. 211
Методы объектов .................................................................................................................... 211
Методы классов ....................................................................................................................... 212
Статические методы............................................................................................................... 212
Утиная типизация ......................................................................................................................... 213
Магические методы ...................................................................................................................... 215
Агрегирование и композиция ................................................................................................... 218
Когда использовать объекты, а когда — что-то другое ..................................................... 218
Именованные кортежи ................................................................................................................ 219
Классы данных ............................................................................................................................... 221
attrs ..................................................................................................................................................... 222
Читайте далее.................................................................................................................................. 222
Упражнения ..................................................................................................................................... 222

Глава 11. Модули, пакеты и программы ...................................................................................... 224


Модули и оператор import ......................................................................................................... 224
Импортируем модуль ............................................................................................................ 224
  ǶȋȓȈȊȓȍȕȐȍ

Импортируем модуль с другим именем .......................................................................... 226


Импортируем только самое необходимое ...................................................................... 226
Пакеты ............................................................................................................................................... 227
Путь поиска модуля ............................................................................................................... 228
Относительный и абсолютный импорт ........................................................................... 229
Пакеты пространств имен .................................................................................................... 229
Модули против объектов ..................................................................................................... 230
Достоинства стандартной библиотеки Python ................................................................... 231
Обрабатываем отсутствующие ключи с помощью функций setdefault()
и defaultdict()............................................................................................................................ 231
Подсчитываем элементы с помощью функции Counter() ....................................... 233
Упорядочиваем по ключу с помощью OrderedDict()................................................. 235
Стек + очередь == deque ....................................................................................................... 235
Итерируем по структурам кода с помощью модуля itertools .................................. 236
Красиво выводим данные на экран с помощью функции pprint() ........................ 238
Работаем со случайными числами .................................................................................... 238
Нужно больше кода ...................................................................................................................... 239
Читайте далее.................................................................................................................................. 240
Упражнения ..................................................................................................................................... 240

ǿȈșȚȤ,,3\WKRQȕȈȗȘȈȒȚȐȒȍ
Глава 12. Обрабатываем данные..................................................................................................... 242
Текстовые строки: Unicode......................................................................................................... 243
Строки формата Unicode в Python 3 ................................................................................ 244
Кодирование и декодирование с помощью кодировки UTF-8 ............................... 246
Кодирование ............................................................................................................................. 247
Декодирование ......................................................................................................................... 249
Сущности HTML .................................................................................................................... 250
Нормализация .......................................................................................................................... 251
Подробная информация ....................................................................................................... 252
Текстовые строки: регулярные выражения .......................................................................... 253
Ищем точное начальное совпадение с помощью функции match()...................... 254
Ищем первое совпадение с помощью функции search()........................................... 255
Ищем все совпадения, используя функцию findall() ................................................. 255
Разбиваем совпадения с помощью функции split().................................................... 256
Заменяем совпадения с помощью функции sub() ....................................................... 256
Шаблоны: специальные символы ..................................................................................... 256
Шаблоны: использование спецификаторов .................................................................. 258
Шаблоны: указываем способ вывода совпадения ....................................................... 261
ǶȋȓȈȊȓȍȕȐȍ  

Бинарные данные .......................................................................................................................... 261


bytes и bytearray....................................................................................................................... 262
Преобразуем бинарные данные с помощью модуля struct....................................... 263
Другие инструменты для работы с бинарными данными ............................................... 266
Преобразуем байты/строки с помощью модуля binascii .......................................... 267
Битовые операторы ................................................................................................................ 267
Аналогия с ювелирными изделиями ...................................................................................... 268
Читайте далее.................................................................................................................................. 268
Упражнения ..................................................................................................................................... 268
Глава 13. Календари и часы.............................................................................................................. 271
Високосный год .............................................................................................................................. 272
Модуль datetime............................................................................................................................. 273
Модуль time ..................................................................................................................................... 275
Читаем и записываем дату и время ......................................................................................... 277
Все преобразования ...................................................................................................................... 281
Альтернативные модули ............................................................................................................. 281
Читайте далее.................................................................................................................................. 282
Упражнения ..................................................................................................................................... 282
Глава 14. Файлы и каталоги............................................................................................................. 283
Ввод информации в файлы и ее вывод из них .................................................................... 283
Создаем или открываем файлы с помощью функции open() ................................. 284
Записываем в текстовый файл с помощью функции print() ................................... 284
Записываем в текстовый файл с помощью функции write() .................................. 285
Считываем данные из текстового файла, используя функции read(),
readline() и readlines() ........................................................................................................... 286
Записываем данные в бинарный файл с помощью функции write() ................... 288
Читаем бинарные файлы с помощью функции read() ............................................... 289
Закрываем файлы автоматически с помощью ключевого слова with .................. 289
Меняем позицию с помощью функции seek() .............................................................. 289
Отображение в памяти ................................................................................................................ 291
Операции с файлами .................................................................................................................... 292
Проверяем существование файла с помощью функции exists() ............................ 292
Проверяем тип с помощью функции isfile().................................................................. 292
Копируем файлы, используя функцию copy() ............................................................. 293
Изменяем имена файлов с помощью функции rename() .......................................... 293
Создаем ссылки с помощью функции link() или symlink() ..................................... 293
Изменяем разрешения с помощью функции chmod() ............................................... 294
Изменение владельца файла с помощью функции chown().................................... 294
Удаляем файл с помощью функции remove()............................................................... 294
  ǶȋȓȈȊȓȍȕȐȍ

Каталоги............................................................................................................................................ 295
Создаем каталог с помощью функции mkdir()............................................................. 295
Удаляем каталог, используя функцию rmdir() ............................................................. 295
Выводим на экран содержимое каталога с помощью функции listdir() .............. 295
Изменяем текущий каталог с помощью функции chdir() ........................................ 296
Перечисляем совпадающие файлы, используя функцию glob()............................ 296
Pathname ........................................................................................................................................... 297
Получаем путь с помощью функции abspath() ............................................................ 298
Получаем символьную ссылку с помощью функции realpath() ............................ 298
Построение пути с помощью функции [Link]() ................................................. 298
Модуль pathlib ......................................................................................................................... 298
BytesIO и StringIO ........................................................................................................................ 299
Читайте далее.................................................................................................................................. 301
Упражнения ..................................................................................................................................... 301
Глава 15. Данные во времени: процессы и конкурентность ................................................. 302
Программы и процессы ............................................................................................................... 302
Создаем процесс с помощью модуля subprocess .......................................................... 303
Создаем процесс с помощью модуля multiprocessing ................................................ 304
Убиваем процесс, используя функцию terminate() .................................................... 305
Получаем системную информацию с помощью модуля os ...................................... 306
Получаем информацию о процессах с помощью модуля psutil.............................. 306
Автоматизация команд ................................................................................................................ 307
Invoke .......................................................................................................................................... 307
Другие вспомогательные методы для команд ..................................................................... 308
Конкурентность ............................................................................................................................. 308
Очереди ...................................................................................................................................... 309
Процессы.................................................................................................................................... 310
Потоки ........................................................................................................................................ 311
[Link] ................................................................................................................... 314
Зеленые потоки и gevent ...................................................................................................... 317
twisted ......................................................................................................................................... 320
asyncio ......................................................................................................................................... 321
Redis ............................................................................................................................................. 321
Помимо очередей .................................................................................................................... 325
Читайте далее.................................................................................................................................. 326
Упражнения ..................................................................................................................................... 326
Глава 16. Данные в коробке: надежные хранилища ................................................................ 327
Плоские текстовые файлы ......................................................................................................... 327
Текстовые файлы, дополненные пробелами ........................................................................ 328
ǶȋȓȈȊȓȍȕȐȍ  

Структурированные текстовые файлы .................................................................................. 328


CSV .............................................................................................................................................. 328
XML ............................................................................................................................................. 331
Примечание о безопасности XML ................................................................................... 333
HTML.......................................................................................................................................... 333
JSON ............................................................................................................................................ 334
YAML........................................................................................................................................... 337
Tablib............................................................................................................................................ 338
Pandas .......................................................................................................................................... 338
Конфигурационные файлы ................................................................................................. 340
Бинарные файлы ........................................................................................................................... 341
Электронные таблицы ................................................................................................................. 341
HDF5 ........................................................................................................................................... 341
TileDB ......................................................................................................................................... 342
Реляционные базы данных......................................................................................................... 342
SQL .............................................................................................................................................. 343
DB-API ....................................................................................................................................... 345
SQLite.......................................................................................................................................... 345
MySQL ........................................................................................................................................ 347
PostgreSQL ................................................................................................................................ 347
SQLAlchemy .............................................................................................................................. 348
Другие пакеты для работы с базами данных ................................................................. 354
Хранилища данных NoSQL ....................................................................................................... 354
Семейство dbm ......................................................................................................................... 354
Memcached................................................................................................................................. 355
Redis ............................................................................................................................................. 356
Документоориентированные базы данных .................................................................... 363
Базы данных временных рядов .......................................................................................... 364
Графовые базы данных .......................................................................................................... 365
Другие серверы NoSQL ........................................................................................................ 365
Полнотекстовые базы данных................................................................................................... 366
Читайте далее.................................................................................................................................. 366
Упражнения ..................................................................................................................................... 366

Глава 17. Данные в пространстве: сети ........................................................................................ 368


TCP/IP .............................................................................................................................................. 368
Сокеты ........................................................................................................................................ 370
scapy ............................................................................................................................................. 374
Netcat ........................................................................................................................................... 374
  ǶȋȓȈȊȓȍȕȐȍ

Паттерны для работы с сетями ................................................................................................. 375


Паттерн «Запрос — ответ» ......................................................................................................... 375
ZeroMQ ....................................................................................................................................... 375
Другие инструменты обмена сообщениями .................................................................. 380
Паттерн «Публикация — подписка»....................................................................................... 380
Redis ............................................................................................................................................. 380
ZeroMQ ....................................................................................................................................... 382
Другие инструменты «Публикации — подписки» ...................................................... 383
Интернет-сервисы ......................................................................................................................... 384
Доменная система имен ........................................................................................................ 384
Модули Python для работы с электронной почтой .................................................... 385
Другие протоколы .................................................................................................................. 385
Веб-сервисы и API ........................................................................................................................ 385
Сериализация данных.................................................................................................................. 386
Сериализация с помощью pickle........................................................................................ 387
Другие форматы сериализации.......................................................................................... 388
Удаленные вызовы процедур..................................................................................................... 388
XML RPC ......................................................................................................................................... 389
JSON RPC .................................................................................................................................. 390
MessagePack RPC .................................................................................................................... 391
Zerorpc......................................................................................................................................... 392
gRPC ............................................................................................................................................ 393
Twirp ............................................................................................................................................ 393
Инструменты удаленного управления................................................................................... 394
Работаем с большими объемами данных .............................................................................. 394
Hadoop ........................................................................................................................................ 394
Spark ............................................................................................................................................ 395
Disco............................................................................................................................................. 395
Dask .............................................................................................................................................. 395
Работаем в облаках ....................................................................................................................... 396
Amazon Web Services .............................................................................................................. 397
Google .......................................................................................................................................... 397
Microsoft Azure ......................................................................................................................... 397
OpenStack .................................................................................................................................. 398
Docker ................................................................................................................................................ 398
Kubernetes .................................................................................................................................. 398
Читайте далее.................................................................................................................................. 398
Упражнения ..................................................................................................................................... 399
ǶȋȓȈȊȓȍȕȐȍ  

Глава 18. Распутываем Всемирную паутину ............................................................................. 400


Веб-клиенты .................................................................................................................................... 401
Тестируем с помощью telnet................................................................................................ 402
Тестируем с помощью curl ................................................................................................... 403
Тестируем с использованием httpie .................................................................................. 404
Тестируем с помощью httpbin ............................................................................................ 405
Стандартные веб-библиотеки Python.............................................................................. 405
За пределами стандартной библиотеки: requests......................................................... 407
Веб-серверы ..................................................................................................................................... 408
Простейший веб-сервер Python ......................................................................................... 409
Web Server Gateway Interface (WSGI) ............................................................................ 410
ASGI ............................................................................................................................................ 411
apache........................................................................................................................................... 411
NGINX ........................................................................................................................................ 412
Другие веб-серверы Python ................................................................................................. 413
Фреймворки для работы веб-серверами ............................................................................... 413
Bottle ........................................................................................................................................... 414
Flask ............................................................................................................................................. 416
Django.......................................................................................................................................... 420
Другие фреймворки ............................................................................................................... 421
Фреймворки для работы с базами данных ........................................................................... 421
Веб-сервисы и автоматизация................................................................................................... 422
Модуль webbrowser ................................................................................................................ 422
Модуль webview ...................................................................................................................... 423
REST API ......................................................................................................................................... 424
Поиск и выборка данных ............................................................................................................ 424
Scrapy .......................................................................................................................................... 425
BeautifulSoup ............................................................................................................................ 425
Requests-HTML ....................................................................................................................... 426
Давайте посмотрим фильм......................................................................................................... 426
Читайте далее.................................................................................................................................. 429
Упражнения ..................................................................................................................................... 429

Глава 19. Быть питонщиком ............................................................................................................ 431


О программировании ................................................................................................................... 431
Ищем код на Python ..................................................................................................................... 432
Установка пакетов ......................................................................................................................... 432
pip ................................................................................................................................................. 433
virtualenv .................................................................................................................................... 434
  ǶȋȓȈȊȓȍȕȐȍ

pipenv ........................................................................................................................................... 434


Менеджер пакетов .................................................................................................................. 434
Установка из исходного кода .............................................................................................. 435
Интегрированные среды разработки ...................................................................................... 435
IDLE ............................................................................................................................................ 435
PyCharm ..................................................................................................................................... 435
IPython........................................................................................................................................ 436
Jupyter Notebook...................................................................................................................... 438
JupyterLab .................................................................................................................................. 438
Именование и документирование ........................................................................................... 438
Добавление подсказок типов ..................................................................................................... 440
Тестирование кода ......................................................................................................................... 440
Программы pylint, pyflakes, flake8 или PEP-8............................................................... 441
Пакет unittest............................................................................................................................ 443
Пакет doctest............................................................................................................................. 447
Пакет nose .................................................................................................................................. 448
Другие фреймворки для тестирования ........................................................................... 449
Постоянная интеграция ........................................................................................................ 449
Отладка кода ................................................................................................................................... 450
Функция print() ...................................................................................................................... 450
Отладка с помощью декораторов ...................................................................................... 451
Отладчик pdb............................................................................................................................ 452
Функция breakpoint() ........................................................................................................... 458
Записываем в журнал сообщения об ошибках.................................................................... 458
Оптимизация кода ........................................................................................................................ 460
Измеряем время ...................................................................................................................... 461
Алгоритмы и структуры данных ....................................................................................... 464
Cython, NumPy и расширения C ....................................................................................... 465
PyPy ............................................................................................................................................. 465
Numba .......................................................................................................................................... 466
Управление исходным кодом .................................................................................................... 467
Mercurial ..................................................................................................................................... 467
Git ................................................................................................................................................. 467
Распространение ваших программ .......................................................................................... 470
Клонируйте эту книгу .................................................................................................................. 470
Как узнать больше ......................................................................................................................... 470
Книги ........................................................................................................................................... 471
Сайты .......................................................................................................................................... 471
Группы......................................................................................................................................... 472
ǶȋȓȈȊȓȍȕȐȍ  

Конференции ............................................................................................................................ 472


Вакансии, связанные с Python ........................................................................................... 472
Читайте далее.................................................................................................................................. 473
Упражнения ..................................................................................................................................... 473

Глава 20. Пи-Арт .................................................................................................................................. 474


Двумерная графика....................................................................................................................... 474
Стандартная библиотека ...................................................................................................... 474
PIL и Pillow ............................................................................................................................... 475
ImageMagick.............................................................................................................................. 478
Трехмерная графика ..................................................................................................................... 478
Трехмерная анимация .................................................................................................................. 479
Графические пользовательские интерфейсы (GUI) ......................................................... 479
Диаграммы, графики и визуализация .................................................................................... 481
Matplotlib ................................................................................................................................... 481
Seaborn ........................................................................................................................................ 483
Bokeh ........................................................................................................................................... 485
Игры ................................................................................................................................................... 485
Аудио и музыка .............................................................................................................................. 486
Читайте далее.................................................................................................................................. 486
Упражнения ..................................................................................................................................... 486

Глава 21. За работой ........................................................................................................................... 487


The Microsoft Office Suite ........................................................................................................... 487
Выполняем бизнес-задачи.......................................................................................................... 488
Обработка бизнес-данных .......................................................................................................... 489
Извлечение, преобразование и загрузка ......................................................................... 489
Валидация данных .................................................................................................................. 493
Дополнительные источники информации..................................................................... 493
Пакеты для работы с бизнес-данными с открытым исходным кодом ....................... 494
Python в области финансов........................................................................................................ 494
Безопасность бизнес-данных .................................................................................................... 495
Карты ................................................................................................................................................. 495
Форматы .................................................................................................................................... 496
Нарисуем карту на основе шейп-файла .......................................................................... 496
Geopandas................................................................................................................................... 498
Другие пакеты для работы с картами .............................................................................. 500
Приложения и данные .......................................................................................................... 501
Читайте далее.................................................................................................................................. 502
Упражнения ..................................................................................................................................... 502
  ǶȋȓȈȊȓȍȕȐȍ

Глава 22. Python в науке.................................................................................................................... 503


Математика и статистика в стандартной библиотеке ...................................................... 503
Математические функции ................................................................................................... 503
Работа с комплексными числами ...................................................................................... 505
Рассчитываем точное значение чисел с плавающей точкой
с помощью модуля decimal .................................................................................................. 506
Выполняем вычисления для рациональных чисел с помощью
модуля fractions ....................................................................................................................... 507
Используем Packed Sequences с помощью модуля array........................................... 507
Обрабатываем простую статистику с помощью модуля statistics ......................... 508
Перемножение матриц .......................................................................................................... 508
Python для науки ........................................................................................................................... 508
NumPy................................................................................................................................................ 508
Создаем массив с помощью функции array() ............................................................... 509
Создаем массив с помощью функции arange()............................................................. 510
Создаем массив с помощью функций zeros(), ones() и random()........................... 511
Изменяем форму массива с помощью метода reshape() ........................................... 512
Получаем элемент с помощью конструкции [] ............................................................ 513
Математика массивов ............................................................................................................ 514
Линейная алгебра.................................................................................................................... 514
Библиотека SciPy .......................................................................................................................... 515
Библиотека SciKit ......................................................................................................................... 516
Pandas................................................................................................................................................. 516
Python и научные области .......................................................................................................... 517
Читайте далее.................................................................................................................................. 518
Упражнения ..................................................................................................................................... 518

ǷȘȐȓȖȎȍȕȐȧ
Приложение А. Аппаратное и программное обеспечение для начинающих
программистов ...................................................................................................................................... 520
Аппаратное обеспечение ............................................................................................................. 520
Компьютеры пещерных людей........................................................................................... 520
Электричество.......................................................................................................................... 521
Изобретения ............................................................................................................................. 521
Идеальный компьютер .......................................................................................................... 522
Процессор .................................................................................................................................. 522
Память и кэш ............................................................................................................................ 522
Хранение .................................................................................................................................... 522
Ввод данных .............................................................................................................................. 523
ǶȋȓȈȊȓȍȕȐȍ  

Вывод данных........................................................................................................................... 523


Относительное время доступа............................................................................................ 523
Программное обеспечение ......................................................................................................... 524
Вначале был бит ...................................................................................................................... 524
Машинный язык...................................................................................................................... 524
Ассемблер .................................................................................................................................. 525
Высокоуровневые языки ...................................................................................................... 525
Операционные системы ........................................................................................................ 526
Виртуальные машины ........................................................................................................... 527
Контейнеры ............................................................................................................................... 527
Распределенные вычисления и сети ................................................................................ 527
Облако ........................................................................................................................................ 528
Kubernetes .................................................................................................................................. 528

Приложение Б. Установка Python 3 ............................................................................................. 530


Проверьте свою версию Python ................................................................................................ 530
Установка стандартной версии Python .................................................................................. 531
macOS.......................................................................................................................................... 532
Windows...................................................................................................................................... 534
Linux или Unix ......................................................................................................................... 535
Установка менеджера пакетов pip ........................................................................................... 535
Установка virtualenv ..................................................................................................................... 535
Другие способы работы с пакетами ........................................................................................ 536
Устанавливаем Anaconda ............................................................................................................ 536

Приложение В. Нечто совершенно иное: async ........................................................................ 538


Сопрограммы и циклы событий............................................................................................... 538
async против… ................................................................................................................................. 542
Асинхронные фреймворки и серверы .................................................................................... 542

Приложение Г. Ответы к упражнениям ...................................................................................... 544


1. Python: с чем его едят .............................................................................................................. 544
2. Типы данных, значения, переменные и имена ................................................................ 545
3. Числа ............................................................................................................................................. 545
4. Выбираем с помощью if........................................................................................................... 546
5. Текстовые строки ...................................................................................................................... 547
6. Создаем циклы с помощью ключевых слов while и for ................................................ 551
7. Кортежи и списки ..................................................................................................................... 552
8. Словари и множества............................................................................................................... 556
9. Функции....................................................................................................................................... 559
10. Ой-ой-ой: объекты и классы ................................................................................................. 560
  ǶȋȓȈȊȓȍȕȐȍ

11. Модули, пакеты и программы .............................................................................................. 564


12. Обрабатываем данные ............................................................................................................. 566
13. Календари и часы ...................................................................................................................... 571
14. Файлы и каталоги ..................................................................................................................... 572
15. Данные во времени: процессы и конкурентность .......................................................... 573
16. Данные в коробке: устойчивые хранилища ..................................................................... 574
17. Данные в пространстве: сети ................................................................................................. 577
18. Распутываем Всемирную паутину ...................................................................................... 584
19. Быть питонщиком ..................................................................................................................... 585
20. Пи-Арт .......................................................................................................................................... 585
21. За работой .................................................................................................................................... 586
22. Python в науке ............................................................................................................................ 586

Приложение Д. Вспомогательные таблицы .............................................................................. 587


Приоритет операторов ................................................................................................................. 587
Строковые методы ........................................................................................................................ 588
Изменение регистра ............................................................................................................... 588
Поиск ........................................................................................................................................... 588
Изменение ................................................................................................................................. 588
Форматирование ..................................................................................................................... 589
Тип строки ................................................................................................................................. 589
Атрибуты модуля string .............................................................................................................. 589

Эпилог ...................................................................................................................................................... 591


С любовью к Мэри, Тому и Рокси,
а также Кэрин и Эрику.
ƊƪƭƬƭƵưƭ

Как и обещает название, книга познакомит вас с одним из самых популярных язы-
ков программирования — Python. Издание предназначено как для начинающих
программистов, так и для тех, кто уже имеет опыт в написании программ и просто
желает добавить Python к списку доступных ему языков.
В большинстве случаев изучать компьютерный язык проще, чем человеческий, —
в нем меньше двусмысленностей и исключений, которые приходится запоминать.
Python — один из самых последовательных и понятных компьютерных языков, он
сочетает в себе простоту изучения, простоту использования и большую выразитель-
ную силу.
Компьютерные языки состоят из данных — аналогами в разговорной речи яв-
ляются существительные — и инструкций (или кода), которые можно сравнить
с глаголами. Изучить нужно будет и то и другое: вы освоите основы кода и струк-
тур данных и узнаете, как их объединить. Затем перейдете к более сложным темам,
а программы, которые вы будете читать и писать, станут длиннее и сложнее. Если
провести аналогию с работой по дереву, мы начнем с молотка, гвоздей и небольших
кусков древесины, а во второй половине книги обратимся к более специализиро-
ванным инструментам, которые можно сравнить с токарными станками и другими
более сложными устройствами.
Вам нужно знать не только сам язык, но и то, что с его помощью можно делать.
Мы начнем с языка Python и его стандартной библиотеки, готовой к работе прямо
«из коробки». Помимо этого, я покажу вам, как находить, загружать, устанавливать
и использовать качественные сторонние пакеты: касаться узких тем или рассматри-
вать сложные трюки не буду, а сделаю акцент на том, что после десяти лет работы
с Python считаю действительно полезным.
Несмотря на то что книга представляет собой введение в Python, в ней мы
затронем и несколько дополнительных тем, с которыми, на мой взгляд, следует
ознакомиться еще на начальном этапе. Работе с базами данных и Интернетом мы
тоже уделим внимание, однако не станем забывать, что технологии меняются очень
быстро — теперь от программиста на Python общество ждет знаний об облачных
технологиях, машинном обучении и создании потоков событий: основную инфор-
мацию по этим темам вы также здесь найдете.
Язык Python имеет некоторые специальные функции, работающие лучше,
чем адаптированные стили программирования из других языков. Например, ис-
пользование ключевого слова for и итераторов — более прямой способ создания
ǪȊȍȌȍȕȐȍ  

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


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

ǷȖȌȖȉȕȣȍȗȘȐȔȍȟȈȕȐȧȧȉțȌțȌȍȓȈȚȤȒȖȋȌȈȟȚȖȚȖȔȖȎȍȚȉȣȚȤȕȍȗȖȕȧȚȕȣȔȐȓȐȎȍ
șțȡȍșȚȊțȍȚȉȖȓȍȍȗȐȚȖȕșȒȐȑșȗȖșȖȉȘȍȠȐȚȤȗȘȖȉȓȍȔț

Python неидеален. Я обращу ваше внимание на то, что кажется сомнительным


и чего следует избегать, и предложу альтернативные варианты.
По некоторым темам, таким как наследование объектов, MVC или проектиро-
вание REST для работы с Интернетом, мое мнение может отличаться от общепри-
нятого. Вам самим решать, к кому прислушаться.

ǬȓȧȒȖȋȖȥȚȈȒȕȐȋȈ
Эта книга для всех, кто заинтересован в изучении одного из самых популярных во
всем мире языков программирования. Наличие или отсутствие опыта с другими
языками программирования не имеет значения.

ǿȚȖȕȖȊȖȋȖȊȖȊȚȖȘȖȔȐȏȌȈȕȐȐ
Что изменилось со времени выхода первого издания?
‰Добавилось около 100 страниц, в том числе с изображением котиков.
‰Количество глав удвоилось, но сами главы стали короче.
‰В начале книги появилась глава, посвященная типам данных, переменным
и именам.
‰Рассмотрены новые особенности Python, такие как f-строки.
‰Рекомендованы новые или улучшенные сторонние библиотеки.
‰Во всей книге присутствуют новые примеры кода.
‰Для начинающих разработчиков добавлен текст с описанием аппаратного и про-
граммного обеспечения.
‰Более опытные разработчики могут ознакомиться с библиотекой asyncio.
‰Рассмотрен новый стек технологий: контейнеры, облачные технологии, наука
о данных и машинное обучение.
  ǪȊȍȌȍȕȐȍ

‰Добавлены подсказки, с помощью которых вы сможете найти работу програм-


миста на Python.
Что не изменилось? Примеры, в которых используются плохие стихотворения
и утки. Они с нами навсегда.

ǹȚȘțȒȚțȘȈȒȕȐȋȐ
В первой части излагаются основы языка программирования Python: главы 1–11
следует читать по порядку. Я оперирую простейшими структурами данных и кода,
постепенно составляя из них более сложные и реалистичные программы. Во второй
части (главы 12–22) показывается, каким образом язык программирования Python
используется в определенных прикладных областях, таких как Интернет, базы дан-
ных, сети и т. д.: эти главы можно читать в любом порядке.
Вот краткое содержание всех глав и приложений и обзор новых терминов, с ко-
торыми вы там встретитесь.
‰Глава 1. «Python: с чем его едят». Компьютерные программы не так уж и отлича-
ются от других инструкций, с которыми вы сталкиваетесь каждый день. Мы рас-
смотрим небольшие программы, написанные на Python. Они продемонстрируют
синтаксис языка, его возможности и способы применения в реальном мире.
Вы узнаете, как запустить программу внутри интерактивного интерпретатора
(оболочки), а также из текстового файла, сохраненного на вашем компьютере.
‰Глава 2. «Данные: типы, значения, переменные и имена». В компьютерных языках
используются данные и инструкции. Компьютер по-разному хранит и обрабаты-
вает разные типы данных. Их значения или можно изменять (такие типы называ-
ются изменяемыми), или нельзя (неизменяемые типы). В программе, написанной
на Python, данные могут быть представлены как литералами (числами вроде 78
или текстовыми строками вроде "waffle"), так и именованными переменными.
В отличие от многих других языков программирования Python относится к пере-
менным как к именам, и это влечет за собой некоторые важные последствия.
‰Глава 3. «Числа». В этой главе показываются простейшие типы данных, применя-
емые в языке программирования Python: булевы переменные, целые числа и числа
с плавающей точкой. Вы также изучите простейшую математику. В примерах
этой главы интерактивный интерпретатор Python используется как калькулятор.
‰Глава 4. «Выбираем с помощью оператора if». С существительными (типами дан-
ных) и с глаголами (программными структурами) мы поработаем в нескольких
главах. Код, написанный на Python, обычно выполняется по одной строке за
раз: от начала программы до ее конца. Структура if позволяет запускать разные
строки кода исходя из результата сравнения определенных данных.
‰Глава 5. «Текстовые строки». Здесь мы обратимся к существительным и миру
текстовых строк. Вы научитесь создавать, объединять, изменять и получать
строки, а также выводить их на экран.
ǪȊȍȌȍȕȐȍ  

‰Глава 6. «Создаем циклы с помощью ключевых слов while и for». Снова глаголы.
Вы научитесь создавать цикл двумя способами — с помощью for и с помощью
while, а также узнаете, что такое итераторы — одно из основных понятий Python.
‰Глава 7. «Кортежи и списки». Пришло время рассмотреть первые структуры
данных более высокого уровня: списки и кортежи. Они представляют собой
последовательности значений, которыми вы будете пользоваться как конструк-
тором Lego для того, чтобы создавать более сложные структуры. Вы научитесь
проходить по ним с помощью итераторов, а также быстро создавать списки
с помощью списковых включений.
‰Глава 8. «Словари и множества». Словари и множества позволяют сохранять
данные не по позиции, а по их значению. Вы увидите, насколько это удобно, —
данная особенность Python станет одной из ваших любимых.
‰Глава 9. «Функции». Соединяйте структуры данных из предыдущих глав со струк-
турами кода, чтобы выполнять сравнение, выборку или повторение операций.
Упаковывайте код в функции и обрабатывайте ошибки с помощью исключений.
‰Глава 10. «Ой-ой-ой: объекты и классы». Слово «объект» недостаточно конкрет-
но, но имеет большое значение во многих компьютерных языках, в том числе
и в Python. Если вы уже занимались объектно-ориентированным программи-
рованием на других языках, то в сравнении с ними Python покажется вам более
простым. В этой главе объясняется, когда следует использовать объекты и классы,
а когда лучше выбрать другой путь.
‰Глава 11. «Модули, пакеты и программы». Вы узнаете, как перейти к более круп-
ным структурам кода — модулям, пакетам и программам, а также где можно разме-
стить код и данные, как ввести и вывести данные, обработать различные параметры,
просмотреть стандартную библиотеку Python и то, что находится вне ее.
‰Глава 12. «Обрабатываем данные». Вы научитесь профессионально обрабатывать
данные и управлять ими. Эта глава полностью посвящена текстовым и двоичным
данным, особенностям использования символов стандарта Unicode, а также
поиску текста с помощью регулярных выражений. Вы познакомитесь с типами
данных byte и bytearray — соперниками типа string, в которых содержатся не-
обработанные бинарные значения вместо текстовых символов.
‰Глава 13. «Календари и часы». С датой и временем работать бывает непросто.
Здесь мы рассмотрим распространенные проблемы и способы их решения.
‰Глава 14. «Файлы и каталоги». Простые хранилища данных используют файлы
и каталоги. В этой главе речь пойдет о создании и использовании файлов и ка-
талогов.
‰Глава 15. «Данные во времени: процессы и конкурентность». Это первая глава,
в которой мы приступаем к изучению системы. Начнем с данных во времени —
вы научитесь использовать программы, процессы и потоки для того, чтобы вы-
полнять больше работы за один промежуток времени (конкурентность). Среди
прочего будут упомянуты последние добавления в async (более подробно они
рассматриваются в приложении В).
  ǪȊȍȌȍȕȐȍ

‰Глава 16. «Данные в коробке: надежные хранилища». Данные могут храниться


в простых файлах и каталогах внутри файловых систем и структурироваться
с помощью распространенных форматов, таких как CSV, JSON и XML. Однако
по мере того, как объем и сложность данных будут расти, вам, возможно, придется
использовать базы данных — как традиционные реляционные, так и современные
базы данных NoSQL.
‰Глава 17. «Данные в пространстве: сети». Отправляйте ваш код и данные через
пространство по сетям с помощью служб, протоколов и API. В качестве примеров
рассматриваются как низкоуровневые сокеты, библиотеки обмена сообщениями
и системы массового обслуживания, так и развертывание в облачных системах.
‰Глава 18. «Распутываем Всемирную паутину». Всемирной сети посвящена от-
дельная глава, в которой рассматриваются клиенты, серверы, извлечение данных,
API и фреймворки. Вы научитесь искать сайты и извлекать из них данные, а за-
тем разработаете реальный сайт, используя параметры запросов и шаблоны.
‰Глава 19. «Быть питонщиком». В этой главе содержатся советы для программи-
стов, пишущих на Python: вы получите рекомендации по установке (с помощью
pip и virtualenv), использованию IDE, тестированию, отладке, журналированию,
контролю исходного кода и документации. Узнаете также, как найти и установить
полезные пакеты сторонних разработчиков, как упаковать свой код для повтор-
ного использования и где получить более подробную информацию.
‰Глава 20. «Пи-Арт». При помощи языка программирования Python можно соз-
давать произведения искусства: в графике, музыке, анимации и играх.
‰Глава 21. «За работой». У Python есть специальные приложения для бизнеса:
визуализация данных (графики, графы и карты), безопасность и регулирование.
‰Глава 22. «Python в науке». За последние несколько лет Python стал главным
языком науки, он используется в математике, статистике, физике, биологии и ме-
дицине. Его сильные стороны — наука о данных и машинное обучение. В этой главе
демонстрируются возможности таких инструментов, как NumPy, SciPy и Pandas.
‰Приложение А. «Аппаратное и программное обеспечение для начинающих про-
граммистов». Если вы новичок в мире программирования, из этого приложения
вы можете узнать, как на самом деле работает аппаратное и программное обе-
спечение и что означают некоторые термины, с которыми в дальнейшем вам
придется сталкиваться.
‰Приложение Б. «Установка Python 3». Если вы еще не установили Python 3 на
свой компьютер, в этом приложении вы найдете информацию о том, как это
сделать независимо от того, какая операционная система у вас установлена:
Windows, Mac OS/X, Linux или другой вариант Unix.
‰Приложение В. «Нечто совершенно иное: async». В разных релизах Python до-
бавляется функциональность для работы с асинхронностью — разобраться с ней
может быть сложно. Я упоминаю о ней в тех главах, в которых заходит речь об
асинхронности, но в этом приложении рассматриваю тему более подробно.
‰Приложение Г. «Ответы к упражнениям». Здесь содержатся ответы на упраж-
нения, приведенные в конце каждой главы. Не подглядывайте туда, пока не по-
ǪȊȍȌȍȕȐȍ  

пробуете решить задачи самостоятельно, в противном случае вы рискуете пре-


вратиться в козленочка.
‰Приложение Д. «Вспомогательные таблицы». В этом приложении содержатся
справочные данные.

ǪȍȘșȐȐ3\WKRQ
Языки программирования со временем изменяются — разработчики добавляют в них
новые возможности и исправляют ошибки. Примеры этой книги написаны и про-
тестированы для версии Python 3.7. Версия 3.7 является наиболее современной на
момент выхода этой книги, и о самых значимых нововведениях я расскажу. Версия 3.8
вышла в конце 2019 года — я рассмотрю самую ожидаемую функциональность1.
Узнать, что и когда было добавлено в язык программирования Python, можно, посетив
страницу KWWSVGRFVS\WKRQRUJZKDWVQHZ: там представлена техническая информация.
Она, скорее всего, покажется трудной для понимания, если вы только начинаете из-
учать Python, но может пригодиться в будущем, если вам нужно будет писать про-
граммы для компьютеров, на которых установлены другие версии Python.

ǻșȓȖȊȕȣȍȖȉȖȏȕȈȟȍȕȐȧ
В этой книге приняты следующие шрифтовые соглашения.
Курсив
Им обозначаются новые термины и понятия.
ǬȢȡȢȬȜȤȜȡȡȯȝȬȤȜȨȦ
Используется в листингах программного кода, а также для имен и расширений
файлов, названий путей, имен функций, команд, баз данных, переменных,
операторов и ключевых слов.
ǪȧȤȥȜȖȡȯȝȠȢȡȢȬȜȤȜȡȡȯȝȬȤȜȨȦ
Указывает текст, который необходимо заменить пользовательскими значениями
или значениями, определяемыми контекстом.

ǺȈȒȖȜȖȘȔȓȍȕȣșȖȊȍȚȗȘȍȌȓȖȎȍȕȐȍȐȓȐȏȈȔȍȟȈȕȐȍ

ǺȈȒȐȔȖȉȘȈȏȖȔȖȜȖȘȔȓȍȕȖȗȘȍȌțȗȘȍȎȌȍȕȐȍ

1
Оригинальное издание выпущено до выхода версии 3.8. Текущая версия — 3.8.2. — Примеч. ред.
  ǪȊȍȌȍȕȐȍ

ǰșȗȖȓȤȏȖȊȈȕȐȍȗȘȐȔȍȘȖȊȒȖȌȈ
Примеры кода и упражнения, приведенные в тексте, доступны для загрузки по адре-
су KWWSVJLWKXEFRPPDGVFKHPHLQWURGXFLQJS\WKRQ. Эта книга написана, чтобы помочь
вам в работе: вы можете применить код, содержащийся в ней, в ваших программах
и документации и не связываться с нами, чтобы спросить разрешения, если соби-
раетесь воспользоваться небольшим фрагментом кода. Например, если вы пишете
программу и кое-где вставляете в нее код из книги, никакого особого разрешения
не требуется. Однако если вы запишете на диск примеры из книги и начнете разда-
вать или продавать такие диски, разрешение на это получить необходимо. Если вы
цитируете это издание, отвечая на вопрос, или воспроизводите код из него в качестве
примера, разрешения не требуется. Но если включаете значительный фрагмент кода
из данной книги в документацию по вашему продукту, необходимо разрешение.
Ссылки на источник приветствуются, но не обязательны. В такие ссылки обычно
включаются название книги, имя ее автора, название издательства и номер ISBN.
Например: «Простой Python. Современный стиль программирования. 2-е изд. Билл
Любанович. Питер, 2020. 978-5-4461-1639-3».
При любых сомнениях относительно превышения разрешенного объема исполь-
зования примеров кода, приведенных в данной книге, можете обращаться к нам по
адресу SHUPLVVLRQV#RUHLOO\FRP.

ǶȚȐȏȌȈȚȍȓȤșȚȊȈ
Ваши замечания, предложения, вопросы отправляйте по адресу FRPS#SLWHUFRP (из-
дательство «Питер», компьютерная редакция).
Мы будем рады узнать ваше мнение!
На веб-сайте издательства ZZZSLWHUFRP вы найдете подробную информацию
о наших книгах.
ƉƳƨƫƶƬƨƸƵƶƹƺư

Искренне благодарю обозревателей и читателей, помогавших сделать эту книгу луч-


ше: Корбина Коллинза, Чарльза Гивра, Нейтана Стокса, Дейва Джорджа и Майка
Джеймса.
ƖƩƨƪƺƶƸƭ

Билл Любанович программировал в операционной системе Unix с 1977 года, раз-


рабатывал GUI с 1981 года, базы данных — с 1990 года, а веб-разработкой занимался
с 1993 года. Кроме того:
‰1982–1988 (Intran) — разрабатывал приложение Metaform на первой коммерче-
ской графической рабочей станции;
‰1990–1995 (Northwest Airlines) — написал визуальную систему управления до-
ходами, а также первый тест для анализа онлайн-маркетинга в Сети;
‰1994 (Tela) — стал сооснователем одного из первых интернет-провайдеров;
‰1995–1999 (WAM!NET) — разрабатывал веб-доски сообщений и 3М Digital
Media Repository;
‰1999–2005 (Mad Scheme) — стал сооснователем компании, занимающейся веб-
разработкой и хостингом;
‰2005 (O’Reilly) — в соавторстве написал несколько глав книги Linux Server
Security1;
‰2007 (O’Reilly) — в соавторстве написал книгу Linux System Administration2;
‰2010–2013 (Keep) — разработал и построил службы Core Services, соединяющие
веб-фронтенды и бэкенды, работающие с базами данных;
‰2014 (O’Reilly) — написал книгу Introducing Python (первое издание)3;
‰2015–2016 (Internet Archive) — работал над API и адаптацией Wayback Machine
на Python;
‰2016–2018 (CrowdStrike) — управлял сервисами на базе Python, которые обра-
батывают миллиарды ежедневных событий, связанных с безопасностью.
Билл счастливо живет в горах Сангре-де-Сасквоч в штате Миннесота со своей
чудесной семьей: женой Мэри, сыном Томом (и его женой Рокси) и дочерью Кэрин
(и ее мужем Эриком), ухаживает за кошками Ингой и Люси и котом Честером.

1
Bauer M. Linux Server Security, 2nd Edition. — O’Reilly, 2009.
2
Адельштайн Т., Любанович Б. Системное администрирование в Linux. — СПб.: Питер, 2010.
3
Любанович Б. Простой Python. Современный стиль программирования. — СПб.: Питер,
2019.
ǿǨǹǺȄ,
ƖƹƵƶƪǃ3\WKRQ
ƋƓƈƊƈ
3\WKRQƹƿƭƴƭƫƶƭƬLJƺ

Популярными становятся только уродливые языки.


Python — исключение из этого правила.

Дональд Кнут

ǺȈȑȕȣ
Начнем с двух небольших тайн и их разгадок. Что, по-вашему, означают следующие
две строки?
ſǰȳȘɨƀśſƀɨɯř••řɨř–—”™‘”Ŝ
ſǰȳȘɩƀśſƀŽɨ’™‹•‡ř’ɬř’ɩ–‘‰ř’ɨř–—”Ŝ

Выглядит как некая компьютерная программа. На самом деле это схема для вя-
зания — точнее, фрагмент, который описывает, как связать пятку носка. Похожие
носки показаны на рис. 1.1.

ǸȐșǪȧȏȈȕȣȍȕȖșȒȐ
ǫȓȈȊȈ3\WKRQșȟȍȔȍȋȖȍȌȧȚ  

Для меня эти строки имеют не больше смысла, чем судоку для одного из моих
котов, но вот моя жена совершенно точно понимает написанное. Если вы вяжете,
то тоже поймете.
Рассмотрим еще один таинственный текст, который можно увидеть записанным
на листочке из блокнота. Вы сразу поймете его предназначение, даже если и не до-
гадаетесь о том, каким будет конечный продукт:
ɨŵɩȥȦȢȟȢȖȢȝȟȢȚȞȜȠȔȥȟȔȜȟȜȠȔȤȗȔȤȜȡȔŚ
ɨŵɩȥȦȢȟȢȖȢȝȟȢȚȞȜȥȟȜȖȢȞŚ
ɩɨŵɩȥȦȔȞȔȡȔȠȧȞȜŚ
ɨȫȔȝȡȔȳȟȢȚȞȔȥȢȟȜŚ
ɨȫȔȝȡȔȳȟȢȚȞȔȥȔȩȔȤȔŚ
ɫȥȦȔȞȔȡȔȞȔȤȦȢȨșȟȰȡȢȗȢȣȲȤșſȢȩȟȔȚȘșȡȡȢȗȢƀŜ

ǯșȤșȘȦșȠȞȔȞȘȢȕȔȖȜȦȰȠȧȞȧřȧȕșȘȜȦșȥȰřȫȦȢȖȥșȜȡȗȤșȘȜșȡȦȯȢȩȟȔȚȘșȡȯŜ
DZȠșȬȔȝȦșȖȥșȜȡȗȤșȘȜșȡȦȯŜ
DzȭȔȦșȟȰȡȢțȔȠșȥȜȦșŜ
DZȘșȟȔȝȦșɩɥȬȔȤȜȞȢȖŜ
ǤșȤȚȜȦșȜȩȢȩȟȔȚȘșȡȡȯȠȜȘȢȥȟșȘȧȲȭșȗȢȱȦȔȣȔŜ
ǤȟȳȞȔȚȘȢȗȢȬȔȤȜȞȔś
ȣȤȜȥȯȣȰȦșȤȔțȘșȟȢȫȡȧȲȘȢȥȞȧȠȧȞȢȝŚ
ȤȔȥȞȔȦȔȝȦșȬȔȤȜȞȣȤȜȣȢȠȢȭȜȤȜȨȟșȡȢȝȥȞȔȟȞȜŚ
ȚȔȤȰȦșȡȔȥȞȢȖȢȤȢȘșȘȢȣȢȘȤȧȠȳȡȜȖȔȡȜȳŚ
ȣșȤșȖșȤȡȜȦșȜȢȕȚȔȤȰȦșȘȤȧȗȧȲȥȦȢȤȢȡȧŜ

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


продуктов, за которым следуют указания по приготовлению. Но что получится
в итоге? Это лефсе, норвежский деликатес, который напоминает тортилью (рис. 1.2).
Полейте блюдо маслом, вареньем или чем-либо еще, сверните и наслаждайтесь.

ǸȐșdzȍȜșȍ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Схема для вязания и рецепт имеют несколько схожих моментов:


‰фиксированный словарь, состоящий из слов, аббревиатур и символов: какие-то
могут быть вам знакомы, какие-то — нет;
‰правила, описывающие, что и где можно говорить, — синтаксис;
‰последовательность операций, которые должны быть выполнены в определенном
порядке;
‰в некоторых случаях — повторение определенных операций (цикл), например
способ приготовления каждого кусочка лефсе;
‰в некоторых случаях — ссылка на еще одну последовательность операций (говоря
компьютерными терминами, функцию). Например, когда вы прочтете приведен-
ный выше рецепт, вам может понадобиться рецепт приготовления картофельного
пюре;
‰предполагаемое знание контекста. Рецепт подразумевает ваше знание о том, что
такое вода и как ее кипятить. Схема для вязания подразумевает, что вы умеете
держать спицы в руках;
‰кое-какие данные, которые нужно использовать, создать или изменить, — кар-
тофель и нитки;
‰инструменты, которые используются для работы с данными, — горшки, миксеры,
духовки, вязальные спицы;
‰ожидаемый результат. В наших примерах результатом будет предмет для ног
и предмет для желудка. Главное — не перепутать.
Как ни назови — идиомы, жаргон, — примеры их использования можно встретить
везде. Жаргон помогает сэкономить время тем, кто его знает, а для других людей
оставляет информацию совершенно непонятной. Попробуйте расшифровать ко-
лонку газеты, посвященную бриджу, если вы не играете в эту игру, или научную
статью — если вы не ученый (или ученый, но в другой области).

ǴȈȓȍȕȤȒȐȍȗȘȖȋȘȈȔȔȣ
Подобные идеи вы встретите и в компьютерных программах, которые сами по себе
являются маленькими языками: через них люди говорят компьютеру, что делать.
Схему для вязания и рецепт я использовал для демонстрации того, что программы
не так страшны, как может показаться, — всего лишь нужно выучить верные слова
и правила.
Понять этот маленький язык гораздо легче, если в нем не очень много слов и пра-
вил и если вам не нужно изучать их все одновременно: за один раз наш мозг может
воспринять только ограниченное количество знаний.
Пришло время обратиться к настоящей программе (пример 1.1). Как вы думаете,
что она делает?
ǫȓȈȊȈ3\WKRQșȟȍȔȍȋȖȍȌȧȚ  

ǷȘȐȔȍȘFRXQWGRZQS\
ˆ‘” ‘—–†‘™‹ɬřɫřɪřɩřɨřɑЇ›Šɑś
’”‹–ſ ‘—–†‘™ƀ

Если вы считаете, что это программа, написанная на языке программирования


Python, которая выводит на экран следующее:
ɬ
ɫ
ɪ
ɩ
ɨ
Ї›Š

то вы знаете, что Python выучить проще, чем понять рецепт или схему для вяза-
ния. К тому же тренироваться писать на этом языке вы можете, сидя за удобным
и безопасным столом и избегая опасностей вроде горячей воды и спиц.
Программа, написанная на языке программирования Python, содержит некоторое
количество специальных слов и символов: for, in, print, запятые, точки с запятой,
скобки и т. д. — все они являются важной частью синтаксиса (правил) языка.
Хорошая новость заключается в том, что Python имеет более доступный и менее
объемный синтаксис по сравнению с большинством других языков программиро-
вания: текст кажется почти понятным — как и рецепт.
Пример 1.2 — тоже небольшая программа на Python: она позволяет выбрать одно
из заклинаний Гарри Поттера, хранящееся в списке, и вывести его на экран.

ǷȘȐȔȍȘVSHOOVS\
•’‡ŽŽ•ʰƃ
ɑ‹††‹—Ž—•Šɑř
ɑ‹‰ƒ”†‹—‡˜‹‘•ƒŠɑř
ɑ˜ƒ†ƒ‡†ƒ˜”ƒŠɑř
ɑš’‡ –‘ƒ–”‘—Šɑř
ɑ‘šŠɑř
ɑ—‘•Šɑř
Ƅ
’”‹–ſ•’‡ŽŽ•ƃɪƄƀ

Отдельные заклинания являются в Python строками (последовательностями тек-


стовых символов, заключенных в кавычки). Они разделены запятыми и помещены
в список — это можно определить по квадратным скобкам (ƃ и Ƅ). Слово spells — это
переменная, являющаяся именем списка, — с ее помощью мы можем работать со
списком. В нашем случае на экран будет выведено четвертое заклинание:
š’‡ –‘ƒ–”‘—Š

Почему мы сказали ɪ , если нам нужно было четвертое заклинание? Списки


Python, такие как spells, представляют собой последовательность значений, доступ
к которым осуществляется с использованием смещения от начала списка. Смещение
для первого элемента списка равно ɥ, а для четвертого — ɪ.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

dzȦȌȐȖȉȣȟȕȖșȟȐȚȈȦȚșȍȌȐȕȐȞȣȗȖȥȚȖȔțșȟȐȚȈȚȤșȕțȓȧȔȖȎȍȚȗȖȒȈȏȈȚȤșȧșȚȘȈȕ
ȕȣȔǶȌȕȈȒȖȊȗȘȖȋȘȈȔȔȐȘȖȊȈȕȐȐțȌȖȉȕȍȍȖȗȍȘȐȘȖȊȈȚȤșȔȍȡȍȕȐȧȔȐȈȕȍȗȖȏȐ
ȞȐȧȔȐǬȈȥȚȖȗȘȐȔȍȘȚȖȋȖȒȈȒȒȖȔȗȤȦȚȍȘȕȈȧȗȘȖȋȘȈȔȔȈȐȕȖȋȌȈȖȚȓȐȟȈȍȚșȧȖȚ
ȖȉȣȟȕȖȋȖȧȏȣȒȈ

Список — очень распространенная структура данных в языке программирования


Python. О том, как им пользоваться, будет рассказано в главе 7.
Программа из примера 1.3 выводит на экран цитату одного из участников ко-
медийного трио The Three Stooges («Три балбеса»), однако на выбор фразы влияет
не позиция в списке, а то, кто ее сказал.

ǷȘȐȔȍȘTXRWHVS\
“—‘–‡•ʰƇ
ɑ‘‡ɑśɑ™‹•‡‰—›řŠ—Šţɑř
ɑƒ””›ɑśɑ™Šɑř
ɑ—”Ž›ɑśɑ›—›—Šɑř
ƈ
•–‘‘‰‡ʰɑ—”Ž›ɑ
’”‹–ſ•–‘‘‰‡řɑ•ƒ›•śɑř“—‘–‡•ƃ•–‘‘‰‡Ƅƀ
Если вы запустите эту небольшую программу, она выведет следующее:
—”Ž›•ƒ›•ś›—›—Š
quotes — переменная, которая именует словарь Python: коллекцию уникальных
ключей (в примере ключом является имя участника трио) и связанных с ними значе-
ний (в нашем примере — значимое высказывание участника «Балбесов»). Используя
словарь, вы можете сохранять элементы и выполнять их поиск по именам: зачастую
это удобнее, чем работать со списком.
В примере с заклинаниями для создания списка использовались квадратные
скобки (ƃ и Ƅ), а в примере с цитатами для создания словаря — фигурные скобки
(Ƈ и ƈ). Также мы использовали двоеточие (ś) для того, чтобы связать каждый ключ
словаря с соответствующим значением. Более подробно о словарях можно про-
читать в главе 8.
Надеюсь, я не перегрузил вас синтаксисом. В следующих нескольких разделах
вы познакомитесь и с другими простыми правилами.

ǩȖȓȍȍȖȉȢȍȔȕȈȧȗȘȖȋȘȈȔȔȈ
Теперь рассмотрим что-то совершенно иное: в примере 1.4 представлена программа,
которая выполняет более сложную серию задач. Не рассчитывайте, что сразу пой-
мете, как она работает, — книга для того и предназначена, чтоб научить вас этому!
Таким образом я даю вам возможность увидеть и прочувствовать типичную полно-
размерную программу, написанную на языке Python. Если вы знаете другие языки
программирования, то можете сравнить их с Python прямо сейчас. Сможете ли вы,
не зная Python и еще не прочтя расшифровку, примерно представить, что делает
каждая строка? Вы уже видели примеры использования списка и словаря, а эта
программа демонстрирует еще несколько новых возможностей.
ǫȓȈȊȈ3\WKRQșȟȍȔȍȋȖȍȌȧȚ  

В первом издании книги программа из примера подключалась к сайту YouTube


и получала информацию о самых популярных роликах, таких как Charlie Bit My
Finger. Она хорошо работала до того момента, как компания Google отключила
поддержку этой службы. Во втором издании уже в новом примере (пример 1.4) мы
подключаемся к другому сайту, который, очевидно, просуществует гораздо доль-
ше, — Wayback Machine из Internet Archive (KWWSDUFKLYHRUJ) (бесплатного сервиса,
сохраняющего миллиарды веб-страниц, в том числе фильмы, телешоу, музыкальные
композиции, игры и иные цифровые артефакты за последние 20 лет). Еще несколько
примеров таких веб-API вы увидите в главе 18.
Программа попросит вас ввести URL и дату. Затем она спросит у Wayback
Machine, имеется ли копия этого веб-сайта за указанную дату. Если копия есть,
API вернет информацию о ней программе, которая, в свою очередь, выведет URL
и отобразит его в веб-браузере. Суть заключается в том, чтобы увидеть, как Python
справляется с разнообразными задачами — принимает пользовательские данные,
общается с веб-сайтами в Интернете и получает от них данные, извлекает оттуда
URL и убеждает веб-браузер отобразить этот URL.
Если бы мы получали обычную веб-страницу, заполненную текстом, отформа-
тированным как HTML, нам пришлось бы сначала придумать, как отобразить ее,
а потом выполнить много действий — все это можно радостно перепоручить веб-
браузеру. Мы также можем попробовать извлечь именно те данные, которые нам
нужны (более подробно о веб-скрапинге читайте в главе 18). Любой из выбранных
вариантов потребует выполнения большего количества работы и увеличит про-
грамму. Вместо этого Wayback Machine возвращает данные в формате JSON. JSON,
или JavaScript Object Notation, — это читабельный для человека текстовый формат,
который описывает типы и значения, а также выстраивает данные в определенном
порядке. Он немного похож на языки программирования и уже стал популярным
способом обмена данными между разными языками программирования и системами.
Подробнее о JSON вы узнаете в главе 12.
Программы, написанные на языке Python, могут преобразовывать текст формата
JSON в структуры данных (с которыми вы познакомитесь в следующих нескольких
главах), как если бы вы написали программу для их создания самостоятельно. Наша
небольшая программа выбирает лишь один фрагмент данных (URL старой веб-
страницы, хранящейся в архиве). И опять же это полноценная программа, которую
вы можете запустить самостоятельно. Мы почти не проверяли данные на ошибки,
чтобы пример оставался коротким. Номера строк не являются частью программы
и включены только для того, чтобы вам было проще следовать описанию, представ-
ленному после кода.

ǷȘȐȔȍȘDUFKLYHS\
ɨ‹’‘”–™‡„„”‘™•‡”
ɩ‹’‘”–Œ•‘
ɪˆ”‘—”ŽŽ‹„Ŝ”‡“—‡•–‹’‘”–—”Ž‘’‡
ɫ
ɬ’”‹–ſɑ‡–ɐ•ˆ‹†ƒ‘ކ™‡„•‹–‡Ŝɑƀ
ɭ•‹–‡ʰ‹’—–ſɑ›’‡ƒ™‡„•‹–‡śɑƀ
ɮ‡”ƒʰ‹’—–ſɑ›’‡ƒ›‡ƒ”ř‘–Šřƒ††ƒ›řŽ‹‡ɩɥɨɬɥɭɨɪśɑƀ
ɯ—”ŽʰɑŠ––’śŵŵƒ” Š‹˜‡Ŝ‘”‰ŵ™ƒ›„ƒ ŵƒ˜ƒ‹Žƒ„އţ—”Žʰʩ•ĺ–‹‡•–ƒ’ʰʩ•ɑʩſ•‹–‡ř‡”ƒƀ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ɰ”‡•’‘•‡ʰ—”Ž‘’‡ſ—”Žƀ
ɨɥ ‘–‡–•ʰ”‡•’‘•‡Ŝ”‡ƒ†ſƀ
ɨɨ–‡š–ʰ ‘–‡–•Ŝ†‡ ‘†‡ſɑ—–ˆŞɯɑƀ
ɨɩ†ƒ–ƒʰŒ•‘ŜŽ‘ƒ†•ſ–‡š–ƀ
ɨɪ–”›ś
ɨɫ‘ކɏ•‹–‡ʰ†ƒ–ƒƃɑƒ” Š‹˜‡†ɏ•ƒ’•Š‘–•ɑƄƃɑ Ž‘•‡•–ɑƄƃɑ—”ŽɑƄ
ɨɬ’”‹–ſɑ ‘—†–Š‹• ‘’›śɑř‘ކɏ•‹–‡ƀ
ɨɭ’”‹–ſɑ –•Š‘—ކƒ’’‡ƒ”‹›‘—”„”‘™•‡”‘™Ŝɑƀ
ɨɮ™‡„„”‘™•‡”Ŝ‘’‡ſ‘ކɏ•‹–‡ƀ
ɨɯ‡š ‡’–ś
ɨɰ’”‹–ſɑ‘””›ř‘Ž— ˆ‹†‹‰ɑř•‹–‡ƀ

Такая небольшая программа, написанная на языке Python, делает многое с по-


мощью всего нескольких строк. Не все термины вы уже знаете, однако сможете
познакомиться с ними в следующих главах.
1. Импортируем (делаем доступным для этой программы) весь код из модуля стан-
дартной библиотеки, который называется webbrowser.
2. Импортируем весь код из модуля стандартной библиотеки, который называется
Œ•‘.
3. Импортируем только функцию urlopen из модуля стандартной библиотеки
—”ŽŽ‹„Ŝ”‡“—‡•–.
4. Пустая строка (мы не хотим перегрузить восприятие).
5. Выводим на экран приветственный текст.
6. Выводим на экран вопрос об URL, считываем пользовательский ввод и сохраняем
это в переменной с именем site.
7. Выводим на экран еще один вопрос и на этот раз считываем год, месяц и день,
а затем сохраняем их в переменной с именем era.
8. Создаем строковую переменную с именем url, чтобы сайт Wayback Machine ис-
кал копию требуемого сайта по дате.
9. Соединяемся с сервером, расположенным по этому адресу, и запрашиваем опре-
деленный веб-сервис.
10. Получаем ответ и присваиваем его переменной ‘–‡–•.
11. Дешифруем содержимое переменной ‘–‡–• в текстовую строку формата JSON
и приписываем ее переменной –‡š–.
12. Преобразуем переменную –‡š– в †ƒ–ƒ — структуру данных языка Python, пред-
назначенную для работы с видео.
13. Проверяем на ошибки: помещаем следующие четыре строки в блок try и, если
находим ошибку, запускаем последнюю строку программы (она идет после
ключевого слова ‡š ‡’–).
14. Получив совпадение по сайту и дате, извлекаем нужное значение из трехуровне-
вого словаря Python. Обратите внимание на то, что в этой и двух последующих
строках используются отступы — тем самым Python легче понять, что данные
строки находятся в блоке try.
ǫȓȈȊȈ3\WKRQșȟȍȔȍȋȖȍȌȧȚ  

15. Выводим на экран полученный URL.


16. Сообщаем о том, что случится, когда выполнится следующая строка.
17. Отображаем полученный URL в браузере.
18. Если во время выполнения предыдущих строк что-то пошло не так, Python
перейдет сюда.
19. Если программа дала сбой, выводим сообщение и имя сайта, который мы искали.
Эта строка также имеет отступ, поскольку должна выполняться только в том
случае, если выполняется строка ‡š ‡’–.
Когда я сам запустил эту программу в окне терминала, то ввел URL сайта и дату
и получил следующий результат:
ɛpython [Link]
‡–ɐ•ˆ‹†ƒ‘ކ™‡„•‹–‡Ŝ
›’‡ƒ™‡„•‹–‡ś[Link]
›’‡ƒ›‡ƒ”ř‘–Šřƒ††ƒ›řŽ‹‡ɩɥɨɬɥɭɨɪś20151022
‘—†–Š‹• ‘’›śŠ––’śŵŵ™‡„Ŝƒ” Š‹˜‡Ŝ‘”‰ŵ™‡„ŵɩɥɨɬɨɨɥɩɥɬɬɰɪɯŵŠ––’śŵŵ™™™ŜŽ‘Ž ƒ–•Ŝ ‘ŵ
–•Š‘—ކƒ’’‡ƒ”‹›‘—”„”‘™•‡”‘™Ŝ

На рис. 1.3 показано то, что появилось в моем браузере.

ǸȐșǸȍȏțȓȤȚȈȚȖȉȘȈȡȍȕȐȧȒ:D\EDFN0DFKLQH

В предыдущем примере мы задействовали стандартные библиотечные моду-


ли (программы, включаемые в Python при установке), но совсем не обязательно
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ограничиваться только ими: на языке Python написано много отличного сторонне-


го ПО. В примере 1.5 показывается та же программа, получающая доступ к архиву
Интернета (Internet Archive), но в ней использован внешний пакет ПО для Python,
который называется requests.

ǷȘȐȔȍȘDUFKLYHS\
ɨ‹’‘”–™‡„„”‘™•‡”
ɩ‹’‘”–”‡“—‡•–•
ɪ
ɫ’”‹–ſɑ‡–ɐ•ˆ‹†ƒ‘ކ™‡„•‹–‡Ŝɑƀ
ɬ•‹–‡ʰ‹’—–ſɑ›’‡ƒ™‡„•‹–‡śɑƀ
ɭ‡”ƒʰ‹’—–ſɑ›’‡ƒ›‡ƒ”ř‘–Šřƒ††ƒ›řŽ‹‡ɩɥɨɬɥɭɨɪśɑƀ
ɮ—”ŽʰɑŠ––’śŵŵƒ” Š‹˜‡Ŝ‘”‰ŵ™ƒ›„ƒ ŵƒ˜ƒ‹Žƒ„އţ—”Žʰʩ•ĺ–‹‡•–ƒ’ʰʩ•ɑʩſ•‹–‡ř‡”ƒƀ
ɯ”‡•’‘•‡ʰ”‡“—‡•–•Ŝ‰‡–ſ—”Žƀ
ɰ†ƒ–ƒʰ”‡•’‘•‡ŜŒ•‘ſƀ
ɨɥ–”›ś
ɨɨ‘ކɏ•‹–‡ʰ†ƒ–ƒƃɑƒ” Š‹˜‡†ɏ•ƒ’•Š‘–•ɑƄƃɑ Ž‘•‡•–ɑƄƃɑ—”ŽɑƄ
ɨɩ’”‹–ſɑ ‘—†–Š‹• ‘’›śɑř‘ކɏ•‹–‡ƀ
ɨɪ’”‹–ſɑ –•Š‘—ކƒ’’‡ƒ”‹›‘—”„”‘™•‡”‘™Ŝɑƀ
ɨɫ™‡„„”‘™•‡”Ŝ‘’‡ſ‘ކɏ•‹–‡ƀ
ɨɬ‡š ‡’–ś
ɨɭ’”‹–ſɑ‘””›ř‘Ž— ˆ‹†‹‰ɑř•‹–‡ƀ

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

3\WKRQȊȘȍȈȓȤȕȖȔȔȐȘȍ
Стоит ли тратить время и силы на изучение Python? Язык программирования
Python существует примерно с 1991 года (он старше Java, но моложе С) и является
одним из пяти самых популярных языков программирования. Людям платят деньги
за написание программ на Python — очень важных и значимых, которыми мы поль-
зуемся каждый день: Google, YouTube, Instagram, Netflix и Hulu.
Я использовал Python для создания приложений в самых разных областях.
Python имеет репутацию высокопроизводительного языка программирования, и это
особенно нравится динамично развивающимся компаниям.
Python используется во многих компьютерных приложениях, таких как:
‰командная строка на мониторе или в окне терминала;
‰пользовательские интерфейсы (Graphical User Interface, GUI), включая сетевые;
‰веб-приложения, как клиентские, так и серверные;
‰бэкенд-серверы, поддерживающие крупные популярные сайты;
‰облака (серверы, управляемые сторонними организациями);
‰приложения для мобильных устройств;
‰приложения для встроенных устройств.
ǫȓȈȊȈ3\WKRQșȟȍȔȍȋȖȍȌȧȚ  

Программы, написанные на Python, могут быть как одноразовыми сценария-


ми — вы видели их ранее в этой главе, так и сложными системами, содержащими
миллионы строк.
В опросе The 2018 Python Developers’ Survey (KWWSVZZZMHWEUDLQVFRPUHVHDUFK
S\WKRQGHYHORSHUVVXUYH\) вы можете увидеть числа и графики, показывающие
текущее место языка Python в мире вычислительных машин.
Мы рассмотрим применение Python для создания сайтов, системного адми-
нистрирования и манипулирования данными. Рассмотрим также использование
Python в искусстве, науке и бизнесе.

3\WKRQȗȘȖȚȐȊȧȏȣȒȈșȗȓȈȕȍȚȣǽ
Насколько Python хорош по сравнению с другими языками программирования?
Где и когда следует использовать тот или иной язык? В этом разделе я покажу при-
меры кода, написанные на других языках, чтобы вы могли оценить, с чем конкури-
рует Python. Вы не обязаны понимать каждый из приведенных фрагментов, если
не работали с этими языками. (А когда увидите последний фрагмент, написанный
на Python, то почувствуете облегчение из-за того, что не работали с некоторыми
другими языками.) Если же вам интересен только Python — вы ничего не потеряете,
если не станете читать этот раздел.
Каждая программа должна напечатать число и немного рассказать о языке, на
котором она написана.
Если вы пользуетесь терминалом или терминальным окном, программа, кото-
рая читает то, что вы вводите, выполняет это и отображает результат, называется
программой-оболочкой. Оболочка операционной системы Windows называется
cmd (KWWSVUXZLNLSHGLDRUJZLNL&PGH[H), она выполняет пакетные файлы, имеющие
расширение Ŝ„ƒ–. Для Linux и других операционных систем семейства Unix (вклю-
чая macOS) существует множество программ-оболочек. Самая популярная из них
называется bash (KWWSVZZZJQXRUJVRIWZDUHEDVK) или sh. Оболочка обладает про-
стейшими возможностями вроде выполнения простой логики и разворачивания
символа-джокера наподобие * в полноценные имена файлов. Вы можете сохранять
команды в файлы, которые называются сценариями оболочки, и выполнять их позже.
Подобные программы могли быть в числе самых первых в вашей карьере программи-
ста. Проблема в том, что возможности для масштабирования у сценариев оболочки
ограничиваются несколькими сотнями строк, а сами сценарии выполняются гораздо
медленнее, чем программы, написанные на других языках. В следующем фрагменте
кода демонстрируется небольшая программа-оболочка:
ɤŠŵ„‹ŵ•Š
Žƒ‰—ƒ‰‡ʰɥ
‡ Š‘ɑƒ‰—ƒ‰‡ɛŽƒ‰—ƒ‰‡ś ƒ–Ї•Š‡ŽŽŜ‘–Ї”‡Ŝɑ

Если вы сохраните этот файл под именем –‡•–Ŝ•Š и запустите его с помощью
команды sh –‡•–Ŝ•Š, то на экране увидите следующее:
ƒ‰—ƒ‰‡ɥś ƒ–Ї•Š‡ŽŽŜ‘–Ї”‡Ŝ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Старые добрые С (KWWSVUXZLNLSHGLDRUJZLNLǹȐB ȧȏȣȒBȗȘȖȋȘȈȔȔȐȘȖȊȈȕȐȧ ) и С++


(KWWSVUXZLNLSHGLDRUJZLNL&) являются довольно низкоуровневыми языками про-
граммирования, которыми пользуются в том случае, когда важна скорость. Ваша опе-
рационная система и множество других программ (включая программу python на
вашем компьютере), скорее всего, написаны на C и C++.
Эти языки программирования труднее выучить и труднее поддерживать зна-
ния в актуальном состоянии. Вам придется отслеживать множество деталей, таких
как управление памятью, что может привести к падениям программы и пробле-
мам, которые трудно диагностировать. Так выглядит небольшая программа на
языке С:
ɤ‹ Ž—†‡ʳ•–†‹‘ŜŠʴ
‹–ƒ‹ſ‹–ƒ”‰ ř Šƒ”Ƌƒ”‰˜ƃƄƀƇ
‹–Žƒ‰—ƒ‰‡ʰɨŚ
’”‹–ˆſɑƒ‰—ƒ‰‡ʩ†ś ƒŠ‡‡ţ‹ŠɎɑřŽƒ‰—ƒ‰‡ƀŚ
”‡–—”ɥŚ
ƈ
С++ происходит из одного семейства с С, но имеет несколько отличительных
особенностей:
ɤ‹ Ž—†‡ʳ‹‘•–”‡ƒʴ
—•‹‰ƒ‡•’ƒ ‡•–†Ś
‹–ƒ‹ſƀƇ
‹–Žƒ‰—ƒ‰‡ʰɩŚ
 ‘—–ʳʳɑƒ‰—ƒ‰‡ɑʳʳŽƒ‰—ƒ‰‡ʳʳɎ
ɑś ƒʫʫŠƒ›‘ƒ––‡–‹‘›Ž‹––އ„”‘–Ї”ŠɑʳʳɎ
‡†ŽŚ
”‡–—”ſɥƀŚ
ƈ
Java (KWWSVZZZMDYDFRPUX) и C# (KWWSVGRFVPLFURVRIWFRPHQXVGRWQHWFVKDUS)
являются преемниками языков С и С++. Они избавлены от некоторых недостатков
предшественников (особенно в управлении памятью), но при этом могут быть не-
много избыточными. Следующий пример написан на Java:
’—„Ž‹  Žƒ••‡ †‘–‡Ƈ
’—„Ž‹ •–ƒ–‹ ˜‘‹†ƒ‹ſ–”‹‰ƃƄƒ”‰•ƀƇ
‹–Žƒ‰—ƒ‰‡ʰɪŚ
›•–‡Ŝ‘—–Ŝˆ‘”ƒ–ſɑƒ‰—ƒ‰‡ʩ†ś ƒ ƒ˜ƒŠ‘–Ї”‡ŠɎɑřŽƒ‰—ƒ‰‡ƀŚ
ƈ
ƈ
Если вы никогда не писали ни на одном из этих языков, у вас может возникнуть
вопрос, что все это такое? Ведь мы хотели всего лишь вывести на экран простую
строку — действительно, некоторые языки нагружены значительным синтаксиче-
ским багажом. Подробнее об этом вы узнаете из главы 2.
С, С++ и Java являются примерами статических языков. Они требуют, чтобы
вы указали компьютеру некоторые низкоуровневые детали, например типы дан-
ных. В приложении А говорится, что для разных типов данных выделяется разное
количество памяти и для них можно выполнять лишь заранее определенный набор
операций. Динамические языки (они также называются скриптовыми) — полная
ǫȓȈȊȈ3\WKRQșȟȍȔȍȋȖȍȌȧȚ  

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


перед тем, как ее использовать.
Многоцелевым динамическим языком многие годы был Perl (KWWSVZZZSHUORUJ),
очень мощный и с обширными библиотеками. Однако его синтаксис достаточно
труден для понимания, а сам язык теряет в популярности из-за появления языков
программирования Python и Ruby. Следующий пример побалует вас острым при-
вкусом Perl:
›ɛŽƒ‰—ƒ‰‡ʰɫŚ
’”‹–ɑƒ‰—ƒ‰‡ɛŽƒ‰—ƒ‰‡ś ƒ‡”Žř–Ї ƒ‡Ž‘ˆŽƒ‰—ƒ‰‡•ŜɎɑŚ

Язык программирования Ruby (KWWSZZZUXE\ODQJRUJHQ) появился немного


позже. Он отчасти позаимствовал функционал у языка Perl, а свою популярность
приобрел благодаря фреймворку для веб-разработки Ruby on Rails. Используется
Ruby примерно в тех же областях, что и Python, и, выбирая между этими языками,
вам придется руководствоваться в большей степени вкусом и доступностью библио-
тек. Следующий фрагмент кода написан на Ruby:
Žƒ‰—ƒ‰‡ʰɬ
’—–•ɑƒ‰—ƒ‰‡ɤƇŽƒ‰—ƒ‰‡ƈś ƒ—„›ř”‡ƒ†›ƒ†ƒ‰Ž‘™Ŝɑ

Язык программирования PHP (KWWSZZZSKSQHW) из следующего примера очень


популярен в области веб-разработок, поскольку позволяет довольно легко объеди-
нять HTML и код. Однако язык PHP имеет несколько подводных камней, и с ним
довольно трудно работать за пределами сферы веб-разработок. Вот так выглядит
программа, написанная на PHP:
ʳţ 
ɛŽƒ‰—ƒ‰‡ʰɭŚ
‡ Š‘ɑƒ‰—ƒ‰‡ɛŽƒ‰—ƒ‰‡ś ƒ řƒŽƒ‰—ƒ‰‡ƒ†’ƒŽ‹†”‘‡ŜɎɑŚ
ţʴ

Язык Go (KWWSVJRODQJRUJ) (в поисковике лучше искать Golang) появился от-


носительно недавно и пытается быть эффективным и быстрым:
’ƒ ƒ‰‡ƒ‹

‹’‘”–ɑˆ–ɑ

ˆ— ƒ‹ſƀƇ
Žƒ‰—ƒ‰‡śʰɮ
ˆ–Ŝ”‹–ˆſɑƒ‰—ƒ‰‡ʩ†ś ‡›řŠ‘řއ–ɐ• ‘ŠɎɑřŽƒ‰—ƒ‰‡ƀ
ƈ

Еще одной современной альтернативой языкам С и С++ является Rust (KWWSV


ZZZUXVWODQJRUJOHDUQ):
ˆƒ‹ſƀƇ
’”‹–ސŠſɑƒ‰—ƒ‰‡Ƈƈś—•–Ї”‡Šɑřɯƀ

Кто остался? Ах да, Python (KWWSVZZZS\WKRQRUJ):


Žƒ‰—ƒ‰‡ʰɰ
’”‹–ſˆɑƒ‰—ƒ‰‡ƇŽƒ‰—ƒ‰‡ƈś ƒ›–Š‘ŜŠƒ–ɐ•ˆ‘”•—’’‡”ţɑƀ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǷȖȟȍȔțȎȍ3\WKRQ"
Одной из причин, не обязательно самой важной, является популярность. Есть такие
факты:
‰Python — это наиболее быстро набирающий популярность основной язык про-
граммирования, как показано на рис. 1.4 (KWWSVVWDFNRYHUIORZEORJ
LQFUHGLEOHJURZWKS\WKRQ);
‰редакторы TIOBE Index (KWWSVZZZWLREHFRPWLREHLQGH[) в июне 2019 года за-
явили: «В этом месяце Python снова достиг высочайшей позиции в TIOBE Index,
его результат составил 8,5 %. Если Python удержит такой темп, то в течение бли-
жайших трех-четырех лет он сможет заменить С и Java, став самым популярным
языком программирования в мире»;
‰Python стал языком программирования 2018 года по версии TIOBE и занял
первые места в рейтингах IEEE Spectrum (KWWSVVSHFWUXPLHHHRUJDWZRUNLQQRYDWLRQ
WKHWRSSURJUDPPLQJODQJXDJHV) и PyPL (KWWSS\SOJLWKXELR3<3/KWPO);
‰Python является самым популярным языком программирования для курсов
введения в информатику в лучших американских колледжах (KWWSVFDFPDFPRUJ
EORJVEORJFDFPS\WKRQLVQRZWKHPRVWSRSXODULQWURGXFWRU\WHDFKLQJODQJXDJHDW
WRSXVXQLYHUVLWLHVIXOOWH[W);
‰Python официально используется для обучения во французских гимназиях.

ǸȐș3\WKRQȖȗȍȘȍȎȈȍȚȊȘȖșȚȍȖșȚȈȓȤȕȣȍȖșȕȖȊȕȣȍȧȏȣȒȐȗȘȖȋȘȈȔȔȐȘȖȊȈȕȐȧ
ǫȓȈȊȈ3\WKRQșȟȍȔȍȋȖȍȌȧȚ  

В последнее время Python стал чрезвычайно популярным языком программи-


рования в науке о данных и машинном обучении. Если вы хотите получить высо-
кооплачиваемую работу разработчика в интересной области, Python — хороший
выбор. А если вы занимаетесь набором персонала, имейте в виду, что пул опытных
разработчиков на Python постоянно растет.
Но почему Python так популярен? Ведь языки программирования не имеют ха-
ризмы. В чем же причина?
Python — многоцелевой высокоуровневый язык программирования. Его ди-
зайн позволяет писать хорошо читаемый код, что на самом деле гораздо важ-
нее, чем кажется на первый взгляд. Каждая компьютерная программа пишется
всего однажды, но впоследствии к ней обращаются множество раз. Благодаря
удобочитаемости программу легко запомнить, а также легко ее воспроизвести.
По сравнению с другими популярными языками программирования кривая об-
учения языку Python более гладкая, что позволяет ученику быстрее стать про-
дуктивным. Однако есть и сложные моменты, с которыми вы столкнетесь по мере
приобретения опыта.
Относительный лаконизм языка Python позволяет создавать гораздо более
короткие программы — аналогичная программа, но написанная на статическом
языке, будет намного длиннее. Исследования показали, что программисты пишут
примерно одинаковое количество строк кода каждый день независимо от языка,
поэтому Python может значительно повысить вашу продуктивность. Язык про-
граммирования Python — самое несекретное оружие многих компаний, которым
важна продуктивность работы сотрудников.
С помощью Python вы можете написать все, что хотите, и совершенно бесплатно
использовать это где угодно. Никто не скажет, прочитав вашу программу: «Ах, какая
милая программка! Будет жаль, если с ней что-нибудь случится».
Python запускается практически везде и имеет «встроенные батарейки» — огром-
ное количество разнообразного ПО в стандартных библиотеках. В этой книге
имеется множество примеров использования стандартной библиотеки и полезного
стороннего кода.
Но основная причина использования Python вам, возможно, покажется неожи-
данной: как правило, люди любят работать с этим языком, а не рассматривают его
как необходимое зло для решения задачи — он подходит их образу мышления. Часто
разработчики, когда им приходится программировать на другом языке, говорят, что
им не хватает какой-то возможности Python. И это выделяет Python на фоне всех
его «коллег».

DzȖȋȌȈȕȍșȚȖȐȚȐșȗȖȓȤȏȖȊȈȚȤ3\WKRQ
Python не всегда будет наилучшим выбором.
Он не установлен по умолчанию. В приложении Б показано, как установить
Python, если он еще не установлен на вашем компьютере.
Python достаточно быстрый для большинства приложений, но его скорости
может оказаться недостаточно для наиболее требовательных из них. Если ваша
программа проводит большую часть времени за вычислениями, что в технических
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

терминах называется «ограничена быстродействием процессора (CPU-bound)», то


языки С, С++, Java, Rust или Go справятся с задачей гораздо лучше, чем Python.
Но не всегда!
Учтите следующие обстоятельства.
‰Иногда более качественный алгоритм (пошаговое решение) в Python превосхо-
дит неэффективный алгоритм в С. Более высокая скорость разработки в Python
дает больше времени для экспериментов в поисках альтернативных решений.
‰Во многих приложениях (особенно в веб-приложениях) программа «бьет баклу-
ши» в ожидании ответа от сервера. Центральный процессор (компьютерный чип,
который делает все расчеты) обычно не задействован, поэтому время выполнения
статических и динамических программ будет примерно одинаковым.
‰Стандартный интерпретатор Python написан на С и может быть улучшен с по-
мощью дополнительного кода. Я рассмотрю этот вопрос в главе 19.
‰Интерпретаторы Python становятся быстрее. Java, когда только появился, был
чрезвычайно медленным, и на его ускорение ушло много времени и денег. Язы-
ком программирования Python не владеет ни одна корпорация, поэтому он
улучшается последовательно и более плавно. В подразделе «PyPy» на с. 465
я расскажу о проекте PyPy и его приложениях.
‰У вас в работе может быть очень сложное приложение, и тогда, независимо от
того, что вы делаете, Python не сможет удовлетворить все ваши требования.
Обычной альтернативой в таком случае являются языки программирования С,
С++ и Java. Вы также можете рассмотреть возможность использования языка Go
(KWWSJRODQJRUJ), который выглядит как Python, но работает как С, или языка
Rust.

3\WKRQȗȘȖȚȐȊ3\WKRQ
Вы можете столкнуться с проблемой выбора одной из двух версий Python. Python 2
существует давно и предустановлен на компьютерах с Linux и Apple. Это был отлич-
ный язык, но нет ничего идеального. В языках программирования, как и во многих
других сферах, бывают ошибки косметические и легко исправимые, а бывают —
сложные и требующие усилий. Исправления несовместимы: новые программы, на-
писанные с помощью исправленного языка, не будут работать на старых системах,
а старые программы не будут работать на новых.
Создатель языка Python Гвидо ван Россум (KWWSVZZZS\WKRQRUJaJXLGR) и дру-
гие разработчики решили собрать и объединить все исправления и в результате
в 2008 году представили миру Python 3. Python 2 — это прошлое, а Python 3 —
будущее. Финальная версия Python 2 имеет номер 2.7, и некоторое время она
еще будет поддерживаться, однако на ней род заканчивается; Python 2.8 никогда
не выйдет. Окончание поддержки языка Python 2 намечено на январь 2020 года.
Больше не будут исправляться проблемы (в том числе проблемы с безопасно-
стью), и многие весомые пакеты Python к этому моменту перестанут поддержи-
вать Python 2 (KWWSVS\WKRQVWDWHPHQWRUJ). В операционных системах также будет
ǫȓȈȊȈ3\WKRQșȟȍȔȍȋȖȍȌȧȚ  

отключен Python 2 и, скорее всего, подключен Python 3 в качестве нового языка,


используемого по умолчанию. Преобразование популярного ПО в Python 3 было
постепенным, но переломный момент уже произошел и новые разработки будут
вестись на Python 3.
Эта книга посвящена Python 3. Он выглядит практически так же, как и Python 2.
Самое очевидное изменение — это тот факт, что print в Python 3 является функцией,
поэтому вам нужно вызывать ее с помощью круглых скобок, в которых будут пере-
числены аргументы. А самое главное изменение — это обработка символов Unicode
(она рассматривается в главе 12). На протяжении всей книги я буду обращать ваше
внимание и на другие различия.

ǻșȚȈȕȖȊȒȈ3\WKRQ
Чтобы не загромождать текст, я вынес детали установки Python 3 в приложение Б.
Если у вас еще не установлен Python 3 или вы не до конца в этом уверены, обрати-
тесь к приложению и посмотрите, каковы должны быть ваши действия. Да, это может
быть хлопотно и трудоемко, но сделать это вам придется лишь однажды.

ǯȈȗțșȒ3\WKRQ
После установки рабочей копии Python 3 вы сможете использовать ее, чтобы запу-
скать как приведенные в этой книге программы, так и собственный код. Как же запу-
стить программу, написанную на языке Python? Существует два основных способа.
‰Встроенный в Python интерактивный интерпретатор (также он называется
оболочкой) предоставляет простой способ поэкспериментировать с небольшими
программами. Строка за строкой вы вводите команды и мгновенно видите ре-
зультат — такая тесная связь между набором текста и его просмотром позволяет
проводить эксперименты быстрее. Я буду использовать интерактивный интер-
претатор для демонстрации возможностей языка, а вы те же команды можете
вводить в собственном компьютере.
‰В остальных случаях сохраняйте программы в виде текстовых файлов с расши-
рением Ŝ’›, а затем запускайте их, введя python и имена этих файлов.
Попробуем воспользоваться обоими методами.

ǰȕȚȍȘȈȒȚȐȊȕȣȑȐȕȚȍȘȗȘȍȚȈȚȖȘ
Для большинства примеров кода в этой книге используется встроенный интерак-
тивный интерпретатор. Когда вы вводите команду из примера и получаете тот же
результаты, вы понимаете, что находитесь на правильном пути.
Интерпретатор запускается путем ввода имени основной программы Python
для вашего компьютера: python, ’›–Š‘ɪ или чего-то похожего. В дальнейшем мы
будем предполагать, что она называется python. Если ваша программа называется
по-другому, то для запуска вам следует ввести именно ее имя.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Интерактивный интерпретатор работает практически так же, как и интерпретатор


для файлов, за одним исключением: когда вы вводите обычное значение, интерактив-
ный интерпретатор автоматически выводит его на экран. Это не часть языка Python,
а всего лишь особенность интерпретатора, которая позволяет вам сэкономить не-
много времени, не набирая конструкцию ’”‹–ſƀ каждый раз. Например, если вы
запустите Python и введете в интерпретатор число ɩɮ, оно будет продублировано
в терминале (если в вашем файле есть строка ɩɮ, Python не расстроится, но при за-
пуске программы вы не увидите ничего):
ɛpython
›–Š‘ɪŜɮŜɩſ˜ɪŜɮŜɩśɰƒɪˆˆ ɥɫɰɩř‡ ɩɫɩɥɨɯřɥɩśɫɫśɫɪƀ
ƃŽƒ‰ɭŜɥſ Žƒ‰ŞɭɥɥŜɥŜɬɮƀƄ‘†ƒ”™‹
›’‡ɑЇޒɑřɑ ‘’›”‹‰Š–ɑřɑ ”‡†‹–•ɑ‘”ɑŽ‹ ‡•‡ɑˆ‘”‘”‡‹ˆ‘”ƒ–‹‘Ŝ
ʴʴʴ27
ɩɮ

Ǫ ȗȘȍȌȣȌțȡȍȔ ȗȘȐȔȍȘȍ șȐȔȊȖȓ  ² ȥȚȖ ȖȉȣȟȕȖȍ ȗȘȐȋȓȈȠȍȕȐȍ ȊȊȍșȚȐ ȒȖȔȈȕȌț


ȊȘȖȌȍ S\WKRQ Ȋ ȖȒȕȖ ȚȍȘȔȐȕȈȓȈ Ǵȣ ȉțȌȍȔ ȐșȗȖȓȤȏȖȊȈȚȤ ȍȍ Ȍȓȧ ȗȘȐȔȍȘȖȊ ȒȖȌȈ
ȊȥȚȖȑȒȕȐȋȍȖȌȕȈȒȖȊȈȠȍȗȘȐȋȓȈȠȍȕȐȍȔȖȎȍȚȖȚȓȐȟȈȚȤșȧ

Кстати, функция ’”‹–ſƀ также работает внутри интерпретатора, на случай если


вам понадобится вывести что-то на экран:
ʴʴʴ’”‹–ſɩɮƀ
ɩɮ

Если вы попробовали запустить эти примеры с помощью интерактивного интер-


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

ǼȈȑȓȣ3\WKRQ
Если вы запишете в файл число ɩɮ и запустите этот файл с помощью Python, он вы-
полнится, но на экране ничего не появится. В обычных неинтерактивных программах
для Python вам нужно вызывать функцию print, чтобы вывести что-то на экран, как
показано в следующем фрагменте кода:
’”‹–ſɩɮƀ

Создадим файл программы Python и запустим его.


1. Откройте текстовый редактор.
2. Введите в него строку ’”‹–ſɩɮƀ, как это показано здесь.
3. Сохраните этот файл с именем –‡•–Ŝ’›. Убедитесь, что вы сохранили его как
простой текст, а не в формате вроде RTF или DOC. Вы не обязаны использовать
расширение Ŝ’› для файлов программ Python, но оно поможет вам запомнить
предназначение файла.
ǫȓȈȊȈ3\WKRQșȟȍȔȍȋȖȍȌȧȚ  

4. Если вы пользуетесь графическим пользовательским интерфейсом — это касается


практически каждого, — откройте окно терминала1.
5. Запустите программу, введя следующую строку:
ɛpython [Link]

Вы должны увидеть такую строку:


ɩɮ

Сработало? Если да, то примите мои поздравления по поводу того, что вы за-
пустили свою первую автономную программу на Python!

ǿȚȖȌȈȓȤȠȍ"
Вы будете вводить команды в работающую систему Python, и они должны соответ-
ствовать синтаксису языка. Вместо того чтобы сваливать на вас все синтаксические
правила сразу, мы неторопливо пройдемся по ним в нескольких следующих главах.
Базовый способ разработки программы на Python — применение простого
текстового редактора и окна терминала. В рамках этой книги я использую именно
такие редакторы, иногда показывая интерактивные сессии работы с терминалом,
а иногда — фрагменты файлов. Вам следует знать, что существует множество
интегрированных сред разработки (integrated development environment, IDE) для
Python. Они могут предоставить вам графические пользовательские интерфейсы,
помогающие в редактировании текста, и экраны помощи. Более подробно об этом
вы прочитаете в главе 19.

ǴȖȔȍȕȚȗȘȖșȊȍȚȓȍȕȐȧ
Каждый язык программирования имеет свой стиль. Во введении я упомянул, что
существует характерный для Python способ выразить себя. В Python встроен не-
большой текст, который выражает его философию (насколько я знаю, Python —
это единственный язык программирования, содержащий подобную «пасхалку»).
Когда вам захочется ощутить момент просветления, просто введите ‹’‘”– this
в интерактивный интерпретатор, а затем нажмите клавишу (QWHU:
ʴʴʴ‹’‘”––Š‹•

ǪȤȔȥȜȖȢșȟȧȫȬșřȫșȠȧȤȢȘȟȜȖȢșŜ
ǿȖȡȢșȟȧȫȬșřȫșȠȡșȳȖȡȢșŜ
ǯȤȢȥȦȢșȟȧȫȬșřȫșȠȥȟȢȚȡȢșŜ
DZȟȢȚȡȢșȟȧȫȬșřȫșȠțȔȣȧȦȔȡȡȢșŜ
ǮȘȡȢȧȤȢȖȡșȖȢșȟȧȫȬșřȫșȠȖȟȢȚșȡȡȢșŜ
ǰȔțȤșȚșȡȡȢșȟȧȫȬșřȫșȠȣȟȢȦȡȢșŜ
ǷȜȦȔșȠȢȥȦȰȜȠșșȦțȡȔȫșȡȜșŜ
ǮȥȢȕȯșȥȟȧȫȔȜȡșȡȔȥȦȢȟȰȞȢȢȥȢȕȯșřȫȦȢȕȯȡȔȤȧȬȔȦȰȣȤȔȖȜȟȔŜ

1
Если вы не знаете, что это значит, откройте приложение Б, чтобы получить детальную
информацию для различных операционных систем.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǯȤȜȱȦȢȠȣȤȔȞȦȜȫȡȢȥȦȰȖȔȚȡșșȕșțȧȣȤșȫȡȢȥȦȜŜ
ǮȬȜȕȞȜȡȜȞȢȗȘȔȡșȘȢȟȚȡȯțȔȠȔȟȫȜȖȔȦȰȥȳŜ
ǥȥȟȜȡșțȔȠȔȟȫȜȖȔȲȦȥȳȳȖȡȢŜ
ǢȥȦȤșȦȜȖȘȖȧȥȠȯȥȟșȡȡȢȥȦȰřȢȦȕȤȢȥȰȜȥȞȧȬșȡȜșȧȗȔȘȔȦȰŜ
ǤȢȟȚșȡȥȧȭșȥȦȖȢȖȔȦȰȢȘȜȡŹȜȚșȟȔȦșȟȰȡȢȦȢȟȰȞȢȢȘȜȡŹȢȫșȖȜȘȡȯȝȥȣȢȥȢȕȥȘșȟȔȦȰȱȦȢŜ
ǵȢȦȳȣȢȡȔȫȔȟȧȢȡȠȢȚșȦȕȯȦȰȜȡșȢȫșȖȜȘșȡřșȥȟȜȖȯȡșȗȢȟȟȔȡȘșȪŜ
DZșȝȫȔȥȟȧȫȬșřȫșȠȡȜȞȢȗȘȔŜ
ǵȢȦȳȡȜȞȢȗȘȔțȔȫȔȥȦȧȲȟȧȫȬșřȫșȠȣȤȳȠȢȥșȝȫȔȥŜ
ǥȥȟȜȤșȔȟȜțȔȪȜȲȥȟȢȚȡȢȢȕȮȳȥȡȜȦȰŹȜȘșȳȣȟȢȩȔŜ
ǥȥȟȜȤșȔȟȜțȔȪȜȲȟșȗȞȢȢȕȮȳȥȡȜȦȰŹȜȘșȳřȖȢțȠȢȚȡȢřȩȢȤȢȬȔŜ
ǯȤȢȥȦȤȔȡȥȦȖȔȜȠșȡŹȢȦȟȜȫȡȔȳȬȦȧȞȔŠǡȧȘșȠȘșȟȔȦȰȜȩȣȢȕȢȟȰȬșŠ

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


утверждения.

ǿȐȚȈȑȚȍȌȈȓȍȍ
В следующей главе мы поговорим о типах данных и переменных в Python. Это под-
готовит вас к чтению тех глав, в которых подробно рассматриваются типы данных
и структуры кода Python.

ǻȗȘȈȎȕȍȕȐȧ
Эта глава была введением в язык программирования Python. Вы узнали, что язык
делает, как выглядит и где его можно применить. В конце каждой главы я буду пред-
лагать выполнить небольшие задания, которые помогут вам запомнить то, что вы
только что прочитали, и подготовят к следующим урокам.
1.1. Если вы еще не установили Python 3, сделайте это сейчас. Прочтите приложе-
ние Б, чтобы узнать детали.
1.2. Запустите интерактивный интерпретатор Python 3. Детали опять же вы найдете
в приложении Б. Интерпретатор должен вывести несколько строк о себе, а за-
тем строку, начинающуюся с символов ʴʴʴ. Перед вами приглашение для ввода
команд Python.
1.3. Немного поэкспериментируйте с интерпретатором. Используйте его как кальку-
лятор и наберите ɯ * 9. Нажмите клавишу (QWHU, чтобы увидеть результат. Python
должен вывести ɮɩ.
1.4. Теперь введите число ɫɮ и нажмите клавишу (QWHU. Появилось ли число ɫɮ в сле-
дующей строке?
1.5. Теперь введите ’”‹–ſɫɮƀ и нажмите клавишу (QWHU. Появилось ли снова число ɫɮ
в следующей строке?
ƋƓƈƊƈ
ǬȈȕȕȣȍȚȐȗȣȏȕȈȟȍȕȐȧ
ȗȍȘȍȔȍȕȕȣȍȐȐȔȍȕȈ

Доброе имя лучше большого богатства.

Притчи 22:1

Все, что хранится в компьютере, представляет собой лишь последовательность битов


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

Ǫ3\WKRQȌȈȕȕȣȍȧȊȓȧȦȚșȧȖȉȢȍȒȚȈȔȐ
Память вашего компьютера визуально можно представить в виде длинного ряда
полок. Каждый слот на этих полках имеет ширину 1 байт (8 бит). Слоты пронуме-
рованы от 0 (первая позиция) до самого конца. Современные компьютеры имеют
миллиарды байт памяти (гигабайт), поэтому полки могли бы заполнить огромный
воображаемый склад.
Программа Python получает доступ к определенной области памяти вашего
компьютера с помощью операционной системы. Эта память используется для кода
самой программы, а также для данных, которыми программа оперирует. Операци-
онная система гарантирует, что программа не может читать или записывать в другие
области памяти без соответствующего разрешения.
Программы следят за тем, где (область памяти) хранятся их биты и чем (тип
данных) они являются. С точки зрения вашего компьютера все биты одинаковы.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Одни и те же биты могут иметь разные значения в зависимости от того, какого они
типа. Один и тот же вариант расстановки битов может означать как число ɭɬ, так
и текстовый символ Ǡ.
Разные типы используют разное количество битов. Когда вы читаете о «64-бит-
ной машине», это означает, что целое число использует 64 бита (8 байт).
Некоторые языки хранят эти необработанные значения в памяти, отслеживая их
размеры и типы. Вместо непосредственной обработки таких данных Python упако-
вывает каждое значение — булевы значения, целые числа, числа с плавающей точкой,
строки и даже крупные структуры данных, функции и программы — в память как
объекты. Глава 10 этой книги посвящена созданию собственных объектов в Python,
но сейчас мы поговорим только об объектах, которые обрабатывают встроенные
типы данных.
Продолжая аналогию с полками: можно предста-
вить, что объекты — это коробки переменной длины,
занимающие место на этих полках так, как показано
на рис. 2.1. Python создает такие коробки, размещает
их на свободных местах и убирает, когда потребность
в них отпадает.
В Python объектом является фрагмент данных, в ко-
тором содержится как минимум следующее:
‰тип, определяющий, что объект может делать (по-
ǸȐșǷȖȝȖȎȐȑȕȈȒȖȘȖȉȒț
дробнее см. в следующем разделе); ȖȉȢȍȒȚ²ȞȍȓȖȍȟȐșȓȖ
‰уникальный идентификатор, позволяющий отли- șȖȏȕȈȟȍȕȐȍȔ
чить его от других объектов;
‰значение, соответствующее типу;
‰счетчик ссылок для отслеживания того, как часто объект используется.
Идентификатор представляет собой адрес места на полке. Тип похож на фа-
бричный штамп на коробке, который поясняет, что объект может делать. Если объ-
ект является целым числом, он имеет тип int и может (помимо всего прочего,
о чем вы узнаете из главы 3) быть добавлен к другому объекту с типом int .
Если мы представим, что коробка сделана из прозрачного пластика, то сможем
увидеть значение, находящееся внутри нее. О том, зачем нужен счетчик ссылок,
вы узнаете через несколько разделов, когда мы будем говорить о переменных
и именах.

ǺȐȗȣ
В табл. 2.1 представлены базовые типы данных в Python. Во втором столбце («Тип»)
содержится имя этого типа в Python. Третий столбец («Изменяемый?») указывает,
можно ли изменить значение переменной после ее создания (подробнее об этом
поговорим в следующем разделе). В столбце «Примеры» показываются один или
ǫȓȈȊȈǬȈȕȕȣȍȚȐȗȣȏȕȈȟȍȕȐȧȗȍȘȍȔȍȕȕȣȍȐȐȔȍȕȈ  

несколько примеров-литералов, соответствующих этому типу. И последний стол-


бец («Глава») указывает на главу этой книги с наиболее подробной информацией
о данном типе.
ǺȈȉȓȐȞȈǩȈȏȖȊȣȍȚȐȗȣȌȈȕȕȣȝȊ3\WKRQ

ǰȔȧ ǺȐȗ ǰȏȔȍȕȧȍȔȣȑ" ǷȘȐȔȍȘȣ ǫȓȈȊȈ


Булево значение bool Нет True, False Глава 3
Целое число int Нет 47, 25000, 25_000 Глава 3
Число с плавающей float Нет 3.14, 2.7e5 Глава 3
точкой
Комплексное число complex Нет 3j, 5 + 9j Глава 22
Текстовая строка str Нет 'alas', "alack", '''a verse attack''' Глава 5
Список list Да ['Winken', 'Blinken', 'Nod'] Глава 7
Кортеж tuple Нет (2, 4, 8) Глава 7
Байты bytes Нет b'ab\xff' Глава 12
Массив байтов bytearray Да bytearray(…) Глава 12
Множество set Да set([3, 5, 7]) Глава 8
Фиксированное frozenset Нет frozenset(['Elsa', 'Otto']) Глава 8
множество
Словарь dict Да {'game': 'bingo', 'dog': 'dingo', Глава 8
'drummer': 'Ringo'}

После глав, посвященных этим базовым типам, в главе 10 вы узнаете, как созда-
вать новые типы данных.

ǰȏȔȍȕȟȐȊȖșȚȤ
Изменчивость одна лишь неизменна.

Перси Шелли

Тип также определяет, можно ли значение, которое хранится в ящике, изме-


нить — тогда это будет изменяемое значение, или оно константно — неизменяемое
значение. Неизменяемый объект как будто находится в закрытом ящике с про-
зрачными стенками (см. рис. 2.1): увидеть значение вы можете, но не в силах его
изменить. По той же аналогии изменяемый объект похож на коробку с крышкой:
вы можете не только увидеть хранящееся там значение, но и изменить его, не из-
менив его тип.
Python является строго типизированным языком, а это означает, что тип объекта
не изменяется, даже если его значение изменяемо (рис. 2.2).
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǸȐșǹȚȘȖȋȈȧȚȐȗȐȏȈȞȐȧȕȍȖȏȕȈȟȈȍȚȟȚȖȒȓȈȊȐȠȐȕțȎȕȖȕȈȎȐȔȈȚȤșȐȓȤȕȍȍ

ǯȕȈȟȍȕȐȧȓȐȚȍȘȈȓȣ
Существует два вида определения данных в Python:
‰как литералы;
‰как переменные.
В следующих главах вы увидите, как указываются значения-литералы для разных
типов данных — целые числа представляют собой последовательность цифр, дроб-
ные числа содержат десятичную точку, текстовые строки заключаются в кавычки
и т. д. Но в примерах этой главы — чтобы избежать излишней сложности — мы
будем использовать лишь короткие целые числа из десятичной системы счисления
и один-два списка. Десятичные целые числа такие же, как числа в математике: они
представляют собой последовательность цифр от 0 до 9. В главе 3 мы рассмотрим
дополнительные детали работы с целыми числами (например, знаки и недесятичные
системы счисления).

ǷȍȘȍȔȍȕȕȣȍ
Вот мы и добрались до ключевого понятия языков программирования.
Python, как и большинство других компьютерных языков, позволяет вам опре-
делять переменные — имена для значений в памяти вашего компьютера, которые вы
далее будете использовать в программе.
ǫȓȈȊȈǬȈȕȕȣȍȚȐȗȣȏȕȈȟȍȕȐȧȗȍȘȍȔȍȕȕȣȍȐȐȔȍȕȈ  

Имена переменных в Python отвечают определенным правилам.


‰Они могут содержать только следующие символы:
y буквы в нижнем регистре (от a до z);
y буквы в верхнем регистре (от A до Z);
y цифры (от 0 до 9);
y нижнее подчеркивание (ɏ).
‰Они чувствительны к регистру: thing, Š‹‰ и   — это разные имена.
‰Они должны начинаться с буквы или нижнего подчеркивания, но не с цифры.
‰Python особо обрабатывает имена, которые начинаются с нижнего подчеркивания
(об этом вы сможете прочитать в главе 9).
‰Они не могут совпадать с зарезервированными словами Python (их также назы-
вают ключевыми).
Перед вами список зарезервированных1 слов:
ƒŽ•‡ƒ™ƒ‹–‡Ž•‡‹’‘”–’ƒ••
‘‡„”‡ƒ‡š ‡’–‹”ƒ‹•‡
”—‡ Žƒ••ˆ‹ƒŽŽ›‹•”‡–—”
ƒ† ‘–‹—‡ˆ‘”Žƒ„†ƒ–”›
ƒ•†‡ˆˆ”‘‘Ž‘ ƒŽ™Š‹Ž‡
ƒ••‡”–†‡Ž‰Ž‘„ƒŽ‘–™‹–Š
ƒ•› ‡Ž‹ˆ‹ˆ‘”›‹‡Ž†
Внутри программы Python увидеть список зарезервированных слов можно с по-
мощью команд:
ʴʴʴЇޒſɑ‡›™‘”†•ɑƀ
или:
ʴʴʴ‹’‘”–‡›™‘”†
ʴʴʴ‡›™‘”†Ŝ™Ž‹•–
Корректными являются такие имена:
‰a;
‰ƒɨ;
‰ƒɏ„ɏ ɏɏɏɰɬ;
‰ɏƒ„ ;
‰ɏɨƒ.
А следующие имена некорректны:
‰ɨ;
‰ɨƒ;
‰ɨɏ;
‰ƒ‡Š;
‰ƒ‘–Ї”ސƒ‡.

1
async и await появились в Python 3.7.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǷȘȐșȊȈȐȊȈȕȐȍ
В Python символ ʰ применяется для присваивания значения переменной.

ǪȠȒȖȓȍȕȈșțȟȐȓȐȟȚȖșȐȔȊȖȓ ȖȏȕȈȟȈȍȚ©ȘȈȊȕȖªǷȖȟȍȔțȎȍȊȖȔȕȖȋȐȝȧȏȣȒȈȝ
ȗȘȖȋȘȈȔȔȐȘȖȊȈȕȐȧȊȒȓȦȟȈȧ3\WKRQȥȚȖȚșȐȔȊȖȓȐșȗȖȓȤȏțȍȚșȧȌȓȧȖȉȖȏȕȈȟȍȕȐȧ
ȗȘȐșȊȈȐȊȈȕȐȧ"ǶȌȕȈȐȏȗȘȐȟȐȕ²ȕȈșȚȈȕȌȈȘȚȕȖȑȒȓȈȊȐȈȚțȘȍȖȚșțȚșȚȊțȦȚȓȖȋȐȟȍ
șȒȐȍȈȓȤȚȍȘȕȈȚȐȊȣȊȘȖȌȍșȚȘȍȓȒȐȊȓȍȊȖȈșȐȔȊȖȓ ȕȍșȓȐȠȒȖȔșȉȐȊȈȍȚșȚȖȓȒț
DzȘȖȔȍȚȖȋȖȊȒȖȔȗȤȦȚȍȘȕȣȝȗȘȖȋȘȈȔȔȈȝȗȘȐșȊȈȐȊȈȕȐȍȐșȗȖȓȤȏțȍȚșȧȟȈȡȍȟȍȔ
ȗȘȖȊȍȘȒȈȕȈȘȈȊȍȕșȚȊȖ

Программы непохожи на алгебру. В школе мы имели дело с подобными уравне-


ниями:
›ʰšʫɨɩ

Решить уравнение можно, подставив значение для š. Если вы зададите для š


значение ɬ, то, поскольку ɬ ʫ ɨɩ равно ɨɮ, значение y будет равно ɨɮ. Подставьте
значение 6, и y будет равен ɨɯ. И так далее.
Строки компьютерной программы могут выглядеть как уравнения, но означают
они при этом нечто иное. В Python и других компьютерных языках š и y являются
переменными. Python знает, что цифра или простая последовательность цифр вро-
де ɨɩ или ɬ является числовым литералом. Рассмотрим небольшую программу на
Python, которая схожа с этим уравнением, — она выводит на экран значение y:
ʴʴʴšʰɬ
ʴʴʴ›ʰšʫɨɩ
ʴʴʴ›
ɨɮ

Здесь мы видим большое различие между математикой и программами: в мате-


матике знак ʰ означает равенство обеих сторон, а в программировании он означает
присваивание: переменной слева мы присваиваем значение с правой стороны.
В программировании также принято, что все находящееся справа от знака ʰ
должно иметь значение (это называется инициализацией). Справа вы можете уви-
деть значение-литерал, переменную, которой было присвоено значение, или их
комбинацию. Python знает, что ɬ и ɨɩ — это числовые литералы. В первой строке
целочисленное значение ɬ присваивается переменной ȩ. Теперь мы можем исполь-
зовать переменную ȩ в следующей строке. Когда Python читает выражение y ʰ š ʫ ɨɩ,
он делает следующее:
‰видит знак ʰ в середине;
‰понимает, что это оператор присваивания;
‰вычисляет значение с правой стороны (получает значение объекта, на который
ссылается переменная ȩ, и добавляет его к ɨɩ);
‰присваивает этот результат переменной слева — y.
ǫȓȈȊȈǬȈȕȕȣȍȚȐȗȣȏȕȈȟȍȕȐȧȗȍȘȍȔȍȕȕȣȍȐȐȔȍȕȈ  

Теперь, введя имя ȧ в интерактивном интерпретаторе, можно увидеть его новое


значение.
Если вы начнете программу со строки y ʰ š ʫ ɨɩ, Python сгенерирует исключение
(ошибку), поскольку переменная ȩ еще не имеет значения:
ʴʴʴ›ʰšʫɨɩ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
ƒ‡””‘”śƒ‡ɐšɐ‹•‘–†‡ˆ‹‡†

Более подробно об исключениях можно прочитать в главе 9. На компьютерном


языке мы скажем, что переменная ȩ не была инициализирована.
В алгебре вы могли бы сделать все наоборот — присвоить значение ȧ , чтобы
подсчитать значение ȩ. Для того, чтобы сделать это в Python, вам нужно получить
значения-литералы и инициализированные переменные с правой стороны оператора
присваивания до того, как присвоить значение переменной ȩ:
ʴʴʴ›ʰɬ
ʴʴʴšʰɨɩŞ›
ʴʴʴš
7

ǷȍȘȍȔȍȕȕȣȍ²ȥȚȖȐȔȍȕȈȈȕȍȓȖȒȈȞȐȐ
Пришло время сделать важное утверждение о переменных в Python: переменные —
всего лишь имена, и в этом заключается отличие Python от других языков програм-
мирования. Об этом важно помнить, особенно при работе с такими изменяемыми
объектами, как списки. Операция присваивания не копирует значение, а только
лишь прикрепляет имя к объекту, содержащему нужные данные. Имя — это ссылка
на объект, а не сам объект. Можно представить, что имя — это этикетка, прикле-
енная на коробку с объектом, которая размещается где-то в памяти компьютера
(рис. 2.3).
В других языках программирования переменные сами по себе имеют тип и при-
вязываются к локации в памяти. Вы можете изменить значение в этой локации,
но оно должно быть того же типа. Именно поэтому в статических языках нужно
объявлять тип переменных. В Python этого делать не требуется, поскольку имя
может ссылаться на все что угодно: значение и тип мы получаем, идя по цепочке
к самому объекту с данными. Такой подход экономит время, но при этом имеет
свои недостатки.
‰Вы можете неверно написать имя переменной и получить исключение, поскольку
она ни на что не ссылается, Python не выполняет такую проверку автоматически
в отличие от статических языков. В главе 19 показывается способ предваритель-
ной проверки переменных.
‰В сравнении с такими языками, как С, у Python скорость работы ниже. Ведь он
заставляет компьютер выполнять больше работы, для того чтобы вам не при-
шлось выполнять ее самостоятельно.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Попробуйте сделать следующее с помощью интерактивного интерпретатора


(рис. 2.4).
1. Как и раньше, присвойте значение 7 имени a. Это создаст объект-«ящик», со-
держащий целочисленное значение 7.
2. Выведите на экран Ȕ.
3. Присвойте имя Ȕ переменной b, заставив b прикрепиться к объекту-«ящику»,
содержащему значение 7.
4. Выведите b.
ʴʴʴƒʰɮ
ʴʴʴ’”‹–ſƒƀ
7
ʴʴʴ„ʰƒ
ʴʴʴ’”‹–ſ„ƀ
7

ǸȐșǰȔȍȕȈțȒȈȏȣȊȈȦȚȕȈȖȉȢȍȒȚȣ ǸȐșDzȖȗȐȘȖȊȈȕȐȍȐȔȍȕȐ ȚȍȗȍȘȤ


ȗȍȘȍȔȍȕȕȈȧțȒȈȏȣȊȈȍȚȕȈȞȍȓȖȟȐșȓȍȕȕȣȑ ȗȍȘȍȔȍȕȕȈȧEțȒȈȏȣȊȈȍȚȕȈȚȖȚȎȍ
ȖȉȢȍȒȚșȖȏȕȈȟȍȕȐȍȔ ȞȍȓȖȟȐșȓȍȕȕȣȑȖȉȢȍȒȚ

В Python, если нужно узнать тип какого-либо объекта (переменной или значе-
ния), можно использовать конструкцию type(ȢȕȮșȞȦƀ. –›’‡ſƀ — одна из встроенных
в Python функций. Чтобы проверить, указывает ли переменная на объект опреде-
ленного типа, используйте конструкцию ‹•‹•–ƒ ‡ſtypeƀ:
ʴʴʴ–›’‡ſɮƀ
ʳ Žƒ••ɐ‹–ɐʴ
ʴʴʴ–›’‡ſɮƀʰʰ‹–
”—‡
ʴʴʴ‹•‹•–ƒ ‡ſɮř‹–ƀ
”—‡
ǫȓȈȊȈǬȈȕȕȣȍȚȐȗȣȏȕȈȟȍȕȐȧȗȍȘȍȔȍȕȕȣȍȐȐȔȍȕȈ  

DzȖȋȌȈ ȧ țȗȖȔȐȕȈȦ ȜțȕȒȞȐȦ ȚȖ ȗȖșȓȍ ȍȍ ȐȔȍȕȐ ȘȈȏȔȍȡȈȦ ȒȘțȋȓȣȍ șȒȖȉȒȐ 
Ȑ ȚȈȒȐȔ ȖȉȘȈȏȖȔ ȗȖȌȟȍȘȒȐȊȈȦ ȟȚȖ ȥȚȖ ȐȔȍȕȕȖ ȜțȕȒȞȐȧ Ȉ ȕȍ ȐȔȧ ȗȍȘȍȔȍȕȕȖȑ
ȐȓȐȟȚȖȓȐȉȖȍȡȍ

Попробуем проделать это с разными значениями (ɬɯ, ɰɰŜɰ, ɐƒ„ ɐ) и перемен-


ными (a, b):
ʴʴʴƒʰɮ
ʴʴʴ„ʰƒ
ʴʴʴ–›’‡ſƒƀ
ʳ Žƒ••ɐ‹–ɐʴ
ʴʴʴ–›’‡ſ„ƀ
ʳ Žƒ••ɐ‹–ɐʴ
ʴʴʴ–›’‡ſɬɯƀ
ʳ Žƒ••ɐ‹–ɐʴ
ʴʴʴ–›’‡ſɰɰŜɰƀ
ʳ Žƒ••ɐˆŽ‘ƒ–ɐʴ
ʴʴʴ–›’‡ſɐƒ„ ɐƀ
ʳ Žƒ••ɐ•–”ɐʴ

Класс — это определение объекта (классы детально рассматриваются в главе 10).


В Python значения терминов «класс» и «тип» примерно одинаковы.
Как вы могли заметить, при упоминании имени переменной Python ищет объект,
на который она ссылается. Неявно Python выполняет большое количество действий
и часто создает временные объекты, которые будут удалены спустя одну-две строки.
Снова рассмотрим пример, показанный ранее:
ʴʴʴ›ʰɬ
ʴʴʴšʰɨɩŞ›
ʴʴʴš
7

В этом фрагменте кода Python сделал следующее:


‰создал целочисленный объект со значением ɬ;
‰создал переменную ȧ, которая указывает на этот объект;
‰нарастил счетчик ссылок для объекта, содержащего значение ɬ;
‰создал еще один целочисленный объект со значением ɨɩ;
‰вычел значение объекта, на который указывает переменная ȧ (ɬ), из значения ɨɩ,
содержащегося в анонимном объекте;
‰присвоил результат (7) новому (пока еще безымянному) целочисленному объекту;
‰заставил переменную ȩ указывать на этот новый объект;
‰нарастил счетчик ссылок для объекта, на который указывает переменная ȩ;
‰нашел значение объекта, на который ссылается переменная ȩ (7), и вывел его на
экран.
Когда количество ссылок на объект становится равным нулю, это означает,
что ни одно имя на него больше не ссылается, поэтому хранить такой объект нет
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

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


использовать память, занятую уже ненужными на данный момент объектами: пред-
ставьте себе, будто кто-то следит за этими полками с памятью и забирает ненужные
коробки на переработку.
В нашем случае объекты со значениями ɬ, ɨɩ и 7, а также переменные š и y боль-
ше не нужны. Сборщик мусора Python может или отправить их в небесный рай для
объектов1, или сохранить, исходя из соображений производительности, так как не-
большие целые числа используются довольно часто.

ǷȘȐșȊȈȐȊȈȕȐȍȕȍșȒȖȓȤȒȐȔȐȔȍȕȈȔ
Вы можете присвоить значение сразу нескольким переменным одновременно:
ʴʴʴ–™‘ʰ†‡—šʰœ™‡‹ʰɩ
ʴʴʴ–™‘
ɩ
ʴʴʴ†‡—š
ɩ
ʴʴʴœ™‡‹
ɩ

ǷȍȘȍȕȈȏȕȈȟȍȕȐȍȐȔȍȕȐ
Поскольку имена указывают на объекты, если изменить значение, присвоенное
имени, оно начнет указывать на другой объект. Счетчик ссылок старого объекта
уменьшится на 1, а счетчик ссылок нового увеличится на ту же величину.

DzȖȗȐȘȖȊȈȕȐȍ
Как вы видели на рис. 2.4, присваивание существующей переменной Ȕ новой пере-
менной b заставит b указывать на тот же объект, что и a. Если вы выберете этикетку a
или b и обратитесь к объекту, на который они указывают, вы получите одинаковый
результат.
Если объект неизменяем (например, целое число), его значение нельзя изменить,
поэтому по умолчанию оба имени являются доступными только для чтения. Попро-
буйте выполнить следующий код:
ʴʴʴšʰɬ
ʴʴʴš
ɬ
ʴʴʴ›ʰš
ʴʴʴ›
ɬ
ʴʴʴšʰɩɰ
ʴʴʴš

1
Или на Остров забытых объектов.
ǫȓȈȊȈǬȈȕȕȣȍȚȐȗȣȏȕȈȟȍȕȐȧȗȍȘȍȔȍȕȕȣȍȐȐȔȍȕȈ  

ɩɰ
ʴʴʴ›
ɬ

Когда мы присваиваем переменную š переменной y , переменная y начинает


указывать на целочисленный объект со значением ɬ, на который также указывает
и переменная š . Далее мы изменяем переменную š так, чтобы она указывала на
целочисленный объект со значением ɩɰ. Объект со значением ɬ, на который все еще
указывает переменная y, не изменился.
В случае, когда оба имени указывают на изменяемый объект, вы можете изменить
значение объекта с помощью любого имени. Если вы этого еще не знали, такая осо-
бенность может вас удивить.
Список представляет собой изменяемый массив значений (в главе 7 этот тип
данных описывается более подробно). В нашем примере a и b указывают на список,
содержащий три целочисленных объекта:
ʴʴʴƒʰƃɩřɫřɭƄ
ʴʴʴ„ʰƒ
ʴʴʴƒ
ƃɩřɫřɭƄ
ʴʴʴ„
ƃɩřɫřɭƄ

Эти элементы списка (ƒƃɥƄ, ƒƃɨƄ и ƒƃɩƄ) сами по себе являются именами, ука-
зывающими на целочисленные объекты со значениями ɩ, ɫ и 6. Список хранит
элементы в заданном порядке.
Теперь давайте изменим первый элемент списка с помощью имени Ȕ и убедимся,
что список b также изменился:
ʴʴʴƒƃɥƄʰɰɰ
ʴʴʴƒ
ƃɰɰřɫřɭƄ
ʴʴʴ„
ƃɰɰřɫřɭƄ

Когда первый элемент списка изменяется, он больше не указывает на объект со


значением ɩ. Теперь он указывает на объект со значением 99. Список все еще имеет
тип list, но его значения (элементы списка и их порядок) можно изменить.

ǪȣȉȐȘȈȍȔȝȖȘȖȠȍȍȐȔȧȗȍȘȍȔȍȕȕȖȑ
Он говорил правильные вещи, но называл их
неверными именами.

Элизабет Барретт Браунинг

Удивительно, но выбор соответствующих имен для переменных очень важен.


Во многих примерах кода, которые мы успели рассмотреть, я использовал про-
стейшие имена вроде a и š. В реальных программах вам будет нужно отслеживать
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

гораздо больше переменных одновременно и придется балансировать между крат-


костью и понятностью. Например, имя —ɏŽ‘‘• можно напечатать быстрее, чем
—„‡”ɏ‘ˆɏŽ‘‘• или ‰ƒ˜‹‹†ƒ‡ɏ‹˜‡–‘”›, однако они более понятны, чем имя n.

ǿȐȚȈȑȚȍȌȈȓȍȍ
Числа! Они такие увлекательные! Хотя вы, наверное, даже не предполагали насколь-
ко1. Вы увидите, как использовать Python в качестве калькулятора, а также узнаете,
как кот помог создать систему счисления.

ǻȗȘȈȎȕȍȕȐȧ
2.1. Присвойте целочисленное значение 99 переменной ’”‹ ‡ и выведите ее на
экран.
2.2. Какого типа значение ɬ?
2.3. Какого типа значение ɩŜɥ?
2.4. Какого типа выражение ɬ ʫ ɩŜɥ?

1
Цифра 8 похожа на снеговика!
ƋƓƈƊƈ
ǿȐșȓȈ

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

Фрэнсис Хатчесон

В этой главе мы начнем рассматривать простейшие типы данных, используемые


в Python:
‰булевы значения (они могут быть равны ”—‡ или ƒŽ•‡);
‰целые числа (например, ɫɩ или ɨɥɥɥɥɥɥɥɥ);
‰числа с плавающей точкой (числа с десятичной точкой вроде ɪŜɨɫɨɬɰ , а ино-
гда и экспоненты вроде ɨŜɥșɯ , что означает десять в восьмой степени, или
ɨɥɥɥɥɥɥɥɥŜɥ).
В каком-то смысле они похожи на атомы. В этой главе мы будем использовать
их по отдельности, а впоследствии вы узнаете, как объединить данные простейших
типов в более крупные «молекулы», такие как списки и словари.
Для каждого типа определены свои правила использования и обработки компью-
тером. Я также покажу вам, как использовать литералы (например, 97 или ɪŜɨɫɨɭ)
и переменные, которые упоминались в главе 2.
Примеры кода, показанные в этой главе, написаны корректно, но являются всего
лишь фрагментами. Мы будем вводить эти фрагменты в интерактивный интерпре-
татор Python и сразу получать результат. Попробуйте запустить их самостоятельно
на своем компьютере (такие примеры вы узнаете по подсказке ʴʴʴ).

ǩțȓȍȊȣȏȕȈȟȍȕȐȧ
В Python объекты булева (логического) типа данных могут иметь только два значе-
ния — ”—‡ или ƒŽ•‡. Иногда вы будете использовать их напрямую, а иногда оце-
нивать «истинность» других типов по их значениям. Специальная функция „‘‘Žſƀ
может преобразовать любой тип данных Python в булев.
Функции мы рассмотрим в главе 9, сейчас же вам нужно знать только то,
что функция имеет имя, от нуля и более входных аргументов, взятых в скобки
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

и разделенных запятыми, а также от нуля и более возвращаемых значений. Функ-


ция „‘‘Žſƀ в качестве аргумента принимает любое значение и возвращает его булев
эквивалент.
Для ненулевых чисел эта функция вернет значение ”—‡:
ʴʴʴ„‘‘Žſ”—‡ƀ
”—‡
ʴʴʴ„‘‘Žſɨƀ
”—‡
ʴʴʴ„‘‘Žſɫɬƀ
”—‡
ʴʴʴ„‘‘ŽſŞɫɬƀ
”—‡

Нулевые значения преобразуются в значение ƒŽ•‡:


ʴʴʴ„‘‘Žſ ƒŽ•‡ƀ
ƒŽ•‡
ʴʴʴ„‘‘Žſɥƀ
ƒŽ•‡
ʴʴʴ„‘‘ŽſɥŜɥƀ
ƒŽ•‡

Чем полезны булевы значения, вы узнаете в главе 4. В последующих главах мы


поговорим о том, при каких обстоятельствах списки, словари и другие типы данных
могут преобразовываться как ”—‡ или ƒŽ•‡.

ǾȍȓȣȍȟȐșȓȈ
Целые числа — это целые числа без дробей и десятичной точки, ничего особенного.
Кроме, возможно, знака и системы счисления (если вы хотите выразить числа в дру-
гих системах, а не в десятичной).

ǿȐșȓȈȓȐȚȍȘȈȓȣ
Любая последовательность цифр в Python представляет собой число-литерал:
ʴʴʴɬ
ɬ

Можно использовать и простой ноль (ɥ):


ʴʴʴɥ
ɥ

Но не ставьте его перед другими цифрами:


ʴʴʴɥɬ
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨ
ɥɬ
ɋ
›–ƒš””‘”ś‹˜ƒŽ‹†–‘‡
ǫȓȈȊȈǿȐșȓȈ  

ǰșȒȓȦȟȍȕȐȍȗȘȍȌțȗȘȍȎȌȈȍȚȊȈșȖȚȖȔȟȚȖȊȣȊȊȍȓȐȒȖȌȒȖȚȖȘȣȑȕȈȘțȠȈȍȚȗȘȈȊȐȓȈ
3\WKRQǿȚȖȥȚȖȏȕȈȟȐȚȧȖȉȢȧșȕȦȊȗȖȌȘȈȏȌȍȓȍ©ǹȐșȚȍȔȣșȟȐșȓȍȕȐȧªǪȒȕȐȋȍ
ȊȣțȊȐȌȐȚȍȍȡȍȔȕȖȋȖȗȘȐȔȍȘȖȊȐșȒȓȦȟȍȕȐȑȗȖșȒȖȓȤȒțȖȕȐȧȊȓȧȦȚșȧȖșȕȖȊȕȣȔ
ȔȍȝȈȕȐȏȔȖȔȖȉȘȈȉȖȚȒȐȖȠȐȉȖȒȊ3\WKRQ

Запись целого числа вы можете начать с конструкций ɥ„, ɥ‘ или ɥš. См. подраздел
«Системы счисления» далее в этой главе.
Последовательность цифр указывает на целое число. Если вы поместите знак ʫ
перед цифрами, число останется прежним:
ʴʴʴɨɩɪ
ɨɩɪ
ʴʴʴʫɨɩɪ
ɨɩɪ

Чтобы указать на отрицательное число, вставьте перед цифрами знак Ş:


ʴʴʴŞɨɩɪ
Şɨɩɪ

При записи целого числа нельзя использовать запятые:


ʴʴʴɨřɥɥɥřɥɥɥ
ſɨřɥřɥƀ

Вместо числа «миллион» вы получите кортеж с тремя значениями (более по-


дробная информация о кортежах находится в главе 7). Однако в качестве раздели-
теля вы можете использовать символ «нижнее подчеркивание»1.
ʴʴʴ‹ŽŽ‹‘ʰɨɏɥɥɥɏɥɥɥ
ʴʴʴ‹ŽŽ‹‘
ɨɥɥɥɥɥɥ

Нижние подчеркивания, которые будут просто проигнорированы, по вашему


желанию ставятся на любую позицию после первой цифры:
ʴʴʴɨɏɩɏɪ
ɨɩɪ

ǶȗȍȘȈȞȐȐșȞȍȓȣȔȐȟȐșȓȈȔȐ
На нескольких следующих страницах вы увидите примеры использования Python
в качестве простого калькулятора. Можно выполнять обычные арифметические опе-
рации с помощью Python, используя математические операторы из этой таблицы.
ǶȗȍȘȈȚȖȘ ǶȗȐșȈȕȐȍ ǷȘȐȔȍȘ ǸȍȏțȓȤȚȈȚ
+ Сложение 5+8 13
– Вычитание 90 – 10 80

Продолжение ®

1
В версиях Python 3.6 и выше.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

(Продолжение)

ǶȗȍȘȈȚȖȘ ǶȗȐșȈȕȐȍ ǷȘȐȔȍȘ ǸȍȏțȓȤȚȈȚ


* Умножение 4*7 28
/ Деление с плавающей точкой 7/2 3.5
// Целочисленное деление 7 // 2 3
% Вычисление остатка 7%3 1
** Возведение в степень 3 ** 4 81

Сложение и вычитание будут работать так, как вы и ожидаете:


ʴʴʴɬʫɰ
ɨɫ
ʴʴʴɨɥɥŞɮ
ɰɪ
ʴʴʴɫŞɨɥ
Şɭ

Вы можете работать с любым количеством чисел и операторов:


ʴʴʴɬʫɰʫɪ
ɨɮ
ʴʴʴɫʫɪŹɩŹɨʫɭ
ɨɥ
Обратите внимание на то, что вставлять пробел между числом и оператором
не обязательно:
ʴʴʴɬʫɰʫɪ
ɨɮ
Такой формат выглядит лучше стилистически и проще читается.
Умножение тоже довольно привычно:
ʴʴʴɭƋɮ
ɫɩ
ʴʴʴɮƋɭ
ɫɩ
ʴʴʴɭƋɮƋɩƋɪ
ɩɬɩ

Операция деления чуть более интересна, поскольку существует два ее вида:


‰с помощью оператора ŵ выполняется деление с плавающей точкой (десятичное
деление);
‰с помощью оператора ŵŵ выполняется целочисленное деление (деление с остат-
ком).
Даже если вы делите целое число на целое число, оператор ŵ даст результат с пла-
вающей точкой (они рассматриваются далее в этой главе):
ʴʴʴɰŵɬ
ɨŜɯ
ǫȓȈȊȈǿȐșȓȈ  

Целочисленное деление вернет вам целочисленный ответ и отбросит остаток:


ʴʴʴɰŵŵɬ
ɨ

Вместо того чтобы проделать дыру в пространственно-временном континууме,


деление на ноль с помощью любого оператора сгенерирует исключение:
ʴʴʴɬŵɥ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
‡”‘‹˜‹•‹‘””‘”ś†‹˜‹•‹‘„›œ‡”‘
ʴʴʴɮŵŵɥ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
‡”‘‹˜‹•‹‘””‘”ś‹–‡‰‡”†‹˜‹•‹‘‘”‘†—Ž‘„›œ

ǾȍȓȣȍȟȐșȓȈȐȗȍȘȍȔȍȕȕȣȍ
Во всех предыдущих примерах использовались непосредственно целочисленные
значения, но можно смешивать целочисленные значения и переменные, которым
было присвоено целочисленное значение:
ʴʴʴƒʰɰɬ
ʴʴʴƒ
ɰɬ
ʴʴʴƒŹɪ
ɰɩ

Как вы узнали во второй главе, Ȕ — это имя, которое указывает на целочисленный


объект. Когда мы выполнили операцию a – ɪ, мы не присвоили результат перемен-
ной a, поэтому ее значение не изменилось:
ʴʴʴƒ
ɰɬ

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


ʴʴʴƒʰƒŞɪ
ʴʴʴƒ
ɰɩ
Опять же эта операция некорректна с точки зрения математики, но именно так
вы выполняете повторное присваивание значения переменной в Python. В Python
выражение, стоящее справа от знака ʰ, вычисляется первым и только затем присва-
ивается переменной с левой стороны.
Проще думать об этом так.
1. Вычитаем ɪ из Ȕ.
2. Присваиваем результат этого вычитания временной переменной.
3. Присваиваем Ȕ значение временной переменной:
ʴʴʴƒʰɰɬ
ʴʴʴ–‡’ʰƒŞɪ
ʴʴʴƒʰ–‡’
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Поэтому, когда вы говорите:


ʴʴʴƒʰƒŷɪ

Python рассчитывает результат операции вычитания с правой стороны от знака ʰ,


запоминает результат, а затем присваивает его переменной Ȕ, которая находится
с левой стороны от знака ʰ. Это гораздо быстрее и лучше на вид, чем использование
временной переменной.
Вы можете совместить арифметические операторы с присваиванием, поставив
оператор перед знаком ʰ. В этом примере выражение Ȕ Şʰ ɪ аналогично выражению
Ȕ ʰ Ȕ Ş ɪ:
ʴʴʴƒʰɰɬ
ʴʴʴƒŞʰɪ
ʴʴʴƒ
ɰɩ

А это выражение аналогично выражению Ȕ ʰ Ȕ ʫ ɯ:


ʴʴʴȔʰɰɩ
ʴʴʴƒʫʰɯ
ʴʴʴƒ
ɨɥɥ

Это — выражению Ȕ ʰ Ȕ * ɩ:
ʴʴʴȔʰɨɥɥ
ʴʴʴƒƋʰɩ
ʴʴʴƒ
ɩɥɥ

Здесь представлен пример деления с плавающей точкой, Ȕ ʰ Ȕ ŵ ɪ:


ʴʴʴȔʰɩɥɥ
ʴʴʴƒŵʰɪ
ʴʴʴƒ
ɭɭŜɭɭɭɭɭɭɭɭɭɭɭɭɭɮ

Теперь попробуем использовать сокращенный вариант Ȕ ʰ Ȕ ŵŵ ɫ (целочисленное


деление):
ʴʴʴƒʰɨɪ
ʴʴʴƒŵŵʰɫ
ʴʴʴƒ
ɪ

Символ ʩ в Python имеет несколько разных применений. Когда он находится


между двух чисел, с его помощью вычисляется остаток от деления первого числа
на второе:
ʴʴʴɰʩɬ
ɫ

Вот так можно получить частное и остаток одновременно:


ʴʴʴ†‹˜‘†ſɰřɬƀ
ſɨřɫƀ
ǫȓȈȊȈǿȐșȓȈ  

В противном случае вам пришлось бы считать их по отдельности:


ʴʴʴɰŵŵɬ
ɨ
ʴʴʴɰʩɬ
ɫ

Только что вы увидели нечто новое — функцию с именем †‹˜‘†: она получает
целые числа 9 и ɬ, а возвращает двухэлементный кортеж. Как я уже говорил, с кор-
тежами вы познакомитесь в главе 7, а с функциями — в главе 9.
Рассмотрим последнюю математическую функцию, которая также позволяет
работать одновременно с целыми числами и с числами с плавающей точкой — воз-
ведение в степень с помощью оператора **:
ʴʴʴɩƋƋɪ
ɯ
ʴʴʴɩŜɥƋƋɪ
ɯŜɥ
ʴʴʴɩƋƋɪŜɥ
ɯŜɥ
ʴʴʴɥƋƋɪ
ɥ

ǷȘȐȖȘȐȚȍȚȖȗȍȘȈȞȐȑ
Рассмотрим, что получится, если ввести следующее:
ʴʴʴɩʫɪƋɫ

Если выполнить сложение первым, ɩ ʫ ɪ равно ɬ, а ɬ * ɫ равно ɩɥ. Но если вы-


полнить первым умножение, ɪ * ɫ равно ɨɩ, а ɩ ʫ ɨɩ равно ɨɫ. В Python, как и в боль-
шинстве других языков, умножение имеет более высокий приоритет, чем сложение,
поэтому вы увидите ответ, совпадающий со второй версией:
ʴʴʴɩʫɪƋɫ
ɨɫ

Как узнать приоритет той или иной операции? В приложении Д есть большая
таблица со всеми правилами. Однако на практике я и сам никогда в нее не смотрю,
потому что гораздо проще добавить пару скобок, чтобы сгруппировать код и вы-
числения нужным образом:
ʴʴʴɩʫſɪƋɫƀ
ɨɫ

Этот пример возведения в степень:


ʴʴʴŞɬƋƋɩ
Şɩɬ

аналогичен следующей конструкции:


ʴʴʴŞſɬƋƋɩƀ
Şɩɬ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Возможно, и это еще не то, чего бы вам хотелось. Скобки помогут сделать кон-
струкцию понятнее:
ʴʴʴſŞɬƀƋƋɩ
ɩɬ

Таким образом, любому человеку, читающему код, не придется угадывать его


предназначение и вспоминать правила приоритета.

ǹȐșȚȍȔȣșȟȐșȓȍȕȐȧ
Предполагается, что целые числа указываются в десятичной системе счисления,
если только вы не укажете какую-либо другую. Вам может никогда не понадобиться
использовать другие системы счисления, но иногда они будут встречаться в коде.
Как правило, у нас десять пальцев на руках и ногах, поэтому мы считаем: 0, 1, 2,
3, 4, 5, 6, 7, 8, 9. После этого у нас заканчиваются цифры, и мы переносим единицу
на место десятки и ноль — на место единицы: 10 означает «одна десятка и ноль еди-
ниц». В отличие от римских цифр в арабских цифрах нет одного символа, который
представлял бы собой 10. Далее мы считаем: 11, 12… 19, переносим единицу, чтобы
сделать 20 (две десятки и ноль единиц), и т. д.
Система счисления указывает, сколько цифр вы используете до того, как пере-
несете единицу. В двоичной (бинарной) системе счисления единственными цифрами
являются 0 и 1. Такие значения может иметь и знаменитый бит. Двоичные 0 и 1
точно такие же, как и десятичные. Однако, если в этой системе сложить 1 и 1, вы
получите 10 (одна десятичная двойка плюс ноль десятичных единиц).
В Python, помимо десятичной, вы можете выразить числа еще в трех системах
счисления, используя следующие префиксы для целых чисел:
‰0b или 0B для двоичной системы (основание 2);
‰0o или 0O для восьмеричной системы (основание 8);
‰0x или 0X для шестнадцатеричной системы (основание 16).
Основаниями здесь являются степени двойки. В некоторых случаях использова-
ние этих систем счисления может быть полезным, однако вполне вероятно, что вам
никогда не понадобится ни одна другая система счисления, кроме старой доброй
десятичной.
Интерпретатор выведет эти числа как десятичные. Попробуем воспользоваться
каждой из систем счисления. Первой выберем старое доброе десятичное число 10,
которое означает «одна десятка и ноль единиц»:
ʴʴʴɨɥ
ɨɥ

Теперь возьмем двоичное (основание 2) число 0b10, что означает «одна (деся-
тичная) двойка и ноль единиц»:
ʴʴʴɥ„ɨɥ
ɩ
ǫȓȈȊȈǿȐșȓȈ  

Восьмеричное (основание 8) число 0o10 означает «одна (десятичная) восьмерка


и ноль единиц»:
ʴʴʴɥ‘ɨɥ
ɯ

Шестнадцатеричное (основание 16) число 0x10 означает «одно (десятичное) 16


и ноль единиц»:
ʴʴʴɥšɨɥ
ɨɭ

Вы можете пойти и в обратном направлении, преобразовав целое число в строку


с любой из этих систем счисления:
ʴʴʴ˜ƒŽ—‡ʰɭɬ
ʴʴʴ„‹ſ˜ƒŽ—‡ƀ
ɐɥ„ɨɥɥɥɥɥɨɐ
ʴʴʴ‘ –ſ˜ƒŽ—‡ƀ
ɐɥ‘ɨɥɨɐ
ʴʴʴЇšſ˜ƒŽ—‡ƀ
ɐɥšɫɨɐ

Функция Š”ſƀ преобразует целое число в его строковый эквивалент, состоящий


из одного символа:
ʴʴʴ Š”ſɭɬƀ
ɐɐ

Функция ‘”†ſƀ выполняет противоположную задачу:


ʴʴʴ‘”†ſɐɐƀ
ɭɬ

Если вам интересно, какие «цифры» использует шестнадцатеричная систе-


ма счисления, то вот они: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e и f. 0ха — это десятич-
ное число 10, а 0xf — десятичное 15. Добавьте 1 к 0xf и получите 0х10 (десятич-
ное 16).
Зачем использовать системы счисления, отличные от десятичной? Они удобны
для битовых операций, которые описаны в главе 12. Там же можно найти и деталь-
ную информацию о переводе чисел из одной системы счисления в другую.
У котов, как правило, есть по пять пальцев на передних лапах и по четыре на
задних — всего 18. Если вы когда-нибудь встретите котов-ученых в лабораторных
халатах, они, скорее всего, будут обсуждать арифметику восемнадцатеричной
системы счисления. Мой кот Честер, которого вы можете увидеть на рис. 3.1, поли-
дакт — у него целых 22 пальца (или около того — их сложно различить). Если бы он
захотел подсчитать все кусочки корма, разбросанные вокруг его миски, он, вполне
вероятно, воспользовался бы 22-ричной системой счисления (далее по тексту —
честеричной системой счисления), в которой использовались бы цифры от 0 до 9
и символы от a до l.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǸȐșǿȍșȚȍȘ²ȗȘȍȒȘȈșȕȣȑȗțȠȐșȚȣȑȗȈȘȍȕȤ
ȐȏȖȉȘȍȚȈȚȍȓȤȟȍșȚȍȘȐȟȕȖȑșȐșȚȍȔȣșȟȐșȓȍȕȐȧ

ǷȘȍȖȉȘȈȏȖȊȈȕȐȧȚȐȗȖȊ
Чтобы изменить тип данных на целочисленный, воспользуйтесь функцией ‹–ſƀ.
Функция ‹–ſƀ принимает один входной аргумент и возвращает одно значение —
преобразованный в целое число эквивалент входного аргумента. При этом она со-
храняет целую часть числа и отбрасывает любой остаток.
Как было сказано в начале главы, простейший тип данных в Python — булев,
переменные этого типа могут иметь только значения ”—‡ и ƒŽ•‡. После преобра-
зования в целые числа они представляют собой значения ɨ и ɥ:
ʴʴʴ‹–ſ”—‡ƀ
ɨ
ʴʴʴ‹–ſ ƒŽ•‡ƀ
ɥ

В свою очередь, функция „‘‘Žſƀ возвращает булев эквивалент целого числа:


ʴʴʴ„‘‘Žſɨƀ
”—‡
ʴʴʴ„‘‘Žſɥƀ
ƒŽ•‡
ǫȓȈȊȈǿȐșȓȈ  

При преобразовании числа с плавающей точкой в целое число просто отсекается


все, что находится после десятичной точки:
ʴʴʴ‹–ſɰɯŜɭƀ
ɰɯ
ʴʴʴ‹–ſɨŜɥ‡ɫƀ
ɨɥɥɥɥ

Преобразование числа с плавающей точкой в булево значение не должно вас


удивить:
ʴʴʴ„‘‘ŽſɨŜɥƀ
”—‡
ʴʴʴ„‘‘ŽſɥŜɥƀ
ƒŽ•‡

Наконец, рассмотрим пример получения целочисленного значения из текстовой


строки (глава 5), которая содержит только цифры и, возможно, разделители ɏ или
знаки ʫ и Ş:
ʴʴʴ‹–ſɐɰɰɐƀ
99
ʴʴʴ‹–ſɐŞɩɪɐƀ
Şɩɪ
ʴʴʴ‹–ſɐʫɨɩɐƀ
ɨɩ
ʴʴʴ‹–ſɐɨɏɥɥɥɏɥɥɥɐƀ
ɨɥɥɥɥɥɥ

Если число в строке представлено не в десятичной системе счисления, а в какой-


то иной, вы можете включить основание этой системы:
ʴʴʴ‹–ſɐɨɥɐřɩƀɤȘȖȢȜȫȡȔȳ
ɩ
ʴʴʴ‹–ſɐɨɥɐřɯƀɤȖȢȥȰȠșȤȜȫȡȔȳ
ɯ
ʴʴʴ‹–ſɐɨɥɐřɨɭƀɤȬșȥȦȡȔȘȪȔȦșȤȜȫȡȔȳ
ɨɭ
ʴʴʴ‹–ſɐɨɥɐřɩɩƀɤȫșȥȦșȤȜȫȡȔȳ
ɩɩ

Преобразование целого числа в целое число ничего не изменит, но и не на-


вредит:
ʴʴʴ‹–ſɨɩɪɫɬƀ
ɨɩɪɫɬ

Если вы попробуете преобразовать что-то непохожее на число, сгенерируется


исключение:
ʴʴʴ‹–ſɐɰɰ„‘––އ•‘ˆ„‡‡”‘–Ї™ƒŽŽɐƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
ƒŽ—‡””‘”ś‹˜ƒŽ‹†Ž‹–‡”ƒŽˆ‘”‹–ſƀ™‹–Š„ƒ•‡ɨɥśɐɰɰ„‘––އ•‘ˆ„‡‡”
‘–Ї™ƒŽŽɐ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ʴʴʴ‹–ſɐɐƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
ƒŽ—‡””‘”ś‹˜ƒŽ‹†Ž‹–‡”ƒŽˆ‘”‹–ſƀ™‹–Š„ƒ•‡ɨɥśɐɐ

Текстовая строка в этом примере начинается с корректных символов-цифр (99),


но продолжается символами, которые функция ‹–ſƀ обработать не может.
Функция ‹–ſƀ будет преобразовывать в целые числа строки, состоящие из цифр
и чисел с плавающей точкой, но не будет обрабатывать строки, содержащие деся-
тичные точки или экспоненты:
ʴʴʴ‹–ſɐɰɯŜɭɐƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
ƒŽ—‡””‘”ś‹˜ƒŽ‹†Ž‹–‡”ƒŽˆ‘”‹–ſƀ™‹–Š„ƒ•‡ɨɥśɐɰɯŜɭɐ
ʴʴʴ‹–ſɐɨŜɥ‡ɫɐƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
ƒŽ—‡””‘”ś‹˜ƒŽ‹†Ž‹–‡”ƒŽˆ‘”‹–ſƀ™‹–Š„ƒ•‡ɨɥśɐɨŜɥ‡ɫɐ

Если вы смешаете численные значения, Python попытается автоматически их


преобразовать:
ʴʴʴɫʫɮŜɥ
ɨɨŜɥ

Булево значение ƒŽ•‡ рассматривается как ɥ или ɥŜɥ, когда смешивается с це-
лыми числами или числами с плавающей точкой, а ”—‡ — как ɨ или ɨŜɥ:
ʴʴʴ”—‡ʫɩ
ɪ
ʴʴʴ ƒŽ•‡ʫɬŜɥ
ɬŜɥ

ǵȈșȒȖȓȤȒȖȖȉȢȍȔȍȕȚȐȗLQW
В Python 2 размер переменной типа int имел ограничение в 32 или в 64 бита, в за-
висимости от вашего процессора. В 32 битах можно было хранить любое целое число
в диапазоне от –2 147 483 648 до 2 147 483 647.
Для переменных типа long выделялось 64 бита, что позволяло хранить значения
в диапазоне от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807. В Python 3
тип long отсутствует, а переменная типа int может быть любого размера — даже
больше 64 бит. Есть возможность поиграть и с такими большими числами, как гугол
(это единица со ста последующими нулями), имя которому придумал девятилетний
мальчик в 1920 году (KWWSVUXZLNLSHGLDRUJZLNLǫțȋȖȓ):
ʴʴʴ
ʴʴʴ‰‘‘‰‘ŽʰɨɥƋƋɨɥɥ
ʴʴʴ‰‘‘‰‘Ž
ɨɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥ
ɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥ
ǫȓȈȊȈǿȐșȓȈ  

ʴʴʴ‰‘‘‰‘ŽƋ‰‘‘‰‘Ž
ɨɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥ
ɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥ
ɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥ

Гуголплекс — число, равное ɨɥƋƋ‰‘‘‰‘Ž (если вы хотите записать его самостоя-


тельно, то подскажу, что оно содержит тысячу нулей). Сначала именно так хотела
назвать себя компания Google (KWWSVZZZTXRUDFRP+RZGLG*RRJOHJHWLWVQDPH), но
все же остановилась на варианте «гугол». При этом правописание перед регистрацией
доменного имени ‰‘‘‰Ž‡Ŝ ‘ никто не проверил.
Во многих других языках программирования такое число вызовет переполнение
целочисленного значения и различные нежелательные последствия, так как компью-
тер не сможет предоставить все необходимое место. Python обрабатывает огромные
целые числа порядка гугола без всяких проблем.

ǿȐșȓȈșȗȓȈȊȈȦȡȍȑȚȖȟȒȖȑ
Значениями целочисленного типа являются целые числа, но числа с плавающей
точкой (в Python они называются float) имеют десятичную точку:
ʴʴʴɬŜ
ɬŜɥ
ʴʴʴɬŜɥ
ɬŜɥ
ʴʴʴɥɬŜɥ
ɬŜɥ

Числа с плавающей точкой могут содержать десятичную целочисленную экспо-


ненту после буквы e:
ʴʴʴɬ‡ɥ
ɬŜɥ
ʴʴʴɬ‡ɨ
ɬɥŜɥ
ʴʴʴɬŜɥ‡ɨ
ɬɥŜɥ
ʴʴʴɬŜɥƋſɨɥƋƋɨƀ
ɬɥŜɥ

Для разделения цифр можно использовать символ «нижнее подчеркивание» (ɏ),


как и в случае с целыми числами:
ʴʴʴ‹ŽŽ‹‘ʰɨɏɥɥɥɏɥɥɥŜɥ
ʴʴʴ‹ŽŽ‹‘
ɨɥɥɥɥɥɥŜɥ
ʴʴʴɨŜɥɏɥɏɨ
ɨŜɥɥɨ

Числа с плавающей точкой обрабатываются так же, как и целые: вы можете ис-
пользовать операторы ʫ, ʬ, *, ŵ, ŵŵ, **, ʩ и функцию †‹˜‘†ſƀ.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Для того чтобы преобразовать другие типы в тип float, следует использовать
функцию ˆŽ‘ƒ–ſƀ. Булевы значения по-прежнему обрабатываются как небольшие
числа:
ʴʴʴˆŽ‘ƒ–ſ”—‡ƀ
ɨŜɥ
ʴʴʴˆŽ‘ƒ–ſ ƒŽ•‡ƀ
ɥŜɥ

При преобразовании целого числа типа int в число типа float просто добавля-
ется десятичная точка:
ʴʴʴˆŽ‘ƒ–ſɰɯƀ
ɰɯŜɥ
ʴʴʴˆŽ‘ƒ–ſɐɰɰɐƀ
ɰɰŜɥ

Можно конвертировать и строку с символами, представляющими собой кор-


ректные числа с плавающей точкой, — цифры, знаки, десятичную точку и знак ș
с показателем степени:
ʴʴʴˆŽ‘ƒ–ſɐɰɯŜɭɐƀ
ɰɯŜɭ
ʴʴʴˆŽ‘ƒ–ſɐŞɨŜɬɐƀ
ŞɨŜɬ
ʴʴʴˆŽ‘ƒ–ſɐɨŜɥ‡ɫɐƀ
ɨɥɥɥɥŜɥ

Когда вы работаете с целыми числами и числами с плавающей точкой, Python


автоматически преобразует целочисленные значения в значения с плавающей
точкой:
ʴʴʴɫɪʫɩŜ
ɫɬŜɥ

Python также может преобразовывать булевы значения в целые числа и числа


с плавающей точкой:
ʴʴʴ ƒŽ•‡ʫɥ
ɥ
ʴʴʴ ƒŽ•‡ʫɥŜ
ɥŜɥ
ʴʴʴ”—‡ʫɥ
ɨ
ʴʴʴ”—‡ʫɥŜ
ɨŜɥ

ǴȈȚȍȔȈȚȐȟȍșȒȐȍȜțȕȒȞȐȐ
Python поддерживает комплексные числа и имеет привычный набор математических
функций, таких как квадратный корень, косинус и т. д. Их рассмотрение отложим
до главы 22, в которой также обсудим применение Python в науке.
ǫȓȈȊȈǿȐșȓȈ  

ǿȐȚȈȑȚȍȌȈȓȍȍ
В следующей главе мы наконец попрощаемся с однострочными примерами кода.
Вы научитесь принимать решения в коде с помощью утверждения if.

ǻȗȘȈȎȕȍȕȐȧ
В этой главе мы рассмотрели атомы Python: числа, строки и переменные. Выполним
с ними несколько небольших упражнений в интерактивном интерпретаторе.
3.1. Сколько секунд в часе? Используйте интерактивный интерпретатор как кальку-
лятор и умножьте количество секунд в минуте (60) на количество минут в часе
(тоже 60).
3.2. Присвойте результат вычисления предыдущего задания (секунды в часе) пере-
менной, которая называется •‡ ‘†•ɏ’‡”ɏŠ‘—”.
3.3. Сколько секунд в сутках? Используйте переменную •‡ ‘†•ɏ’‡”ɏŠ‘—”.
3.4. Снова посчитайте количество секунд в сутках, но на этот раз сохраните резуль-
тат в переменной •‡ ‘†•ɏ’‡”ɏ†ƒ›.
3.5. Разделите значение переменной •‡ ‘†•ɏ’‡”ɏ†ƒ› на значение переменной
•‡ ‘†•ɏ’‡”ɏŠ‘—”, используя деление с плавающей точкой (ŵ).
3.6. Разделите значение переменной •‡ ‘†•ɏ’‡”ɏ†ƒ› на значение переменной
•‡ ‘†•ɏ’‡”ɏŠ‘—”, используя целочисленное деление (ŵŵ). Совпадает ли по-
лученный результат с ответом из предыдущего пункта без учета символов Ŝɥ
в конце?
ƋƓƈƊƈ
ǪȣȉȐȘȈȍȔșȗȖȔȖȡȤȦ
ȖȗȍȘȈȚȖȘȈLI

О, если ты спокоен, не растерян,


Когда теряют головы вокруг…

Редьярд Киплинг. Если

В предыдущих главах вам встречались самые разные данные, но с ними вы прак-


тически не работали. В большинстве примеров использовался интерактивный
интерпретатор, а сами они были достаточно короткими. Теперь вы увидите, как
структурировать код Python, а не только данные.
В большинстве языков программирования такие символы, как фигурные скобки
(Ƈ и ƈ) и ключевые слова (например, begin и ‡†), применяются для разбивки кода на
разделы. В этих языках хорошим тоном является использование отбивки пробелами
с целью сделать программу более легкочитаемой для себя и других. Существуют
даже специальные инструменты, которые помогают красиво выстраивать код.
Гвидо ван Россум, разрабатывая Python, решил, что выделения пробелами доста-
точно для определения структуры программы, и отказался от ввода разнообразных
скобок. Python отличается от других языков тем, что пробелы в нем используются
для того, чтобы задать структуру программы. Этот аспект новички замечают одним
из первых, а тем, кто уже работал с другими языками программирования, такой под-
ход может даже показаться странным. Однако с течением времени все становится на
свои места и кажется абсолютно естественным. Вам даже понравится, что вы делаете
больше, набирая меньше текста.
Наши первые примеры кода состояли из одной строки. А теперь посмотрим, как
создавать комментарии и команды длиной несколько строк.

DzȖȔȔȍȕȚȐȘțȍȔșȗȖȔȖȡȤȦșȐȔȊȖȓȈ
Комментарий — это фрагмент текста в вашей программе, который будет проигно-
рирован интерпретатором Python. Вы можете использовать комментарии, чтобы
давать пояснение кода, делать какие-то пометки для себя или для чего-либо еще.
Комментарий помечается символом #: все, что после # и до конца текущей строки,
ǫȓȈȊȈǪȣȉȐȘȈȍȔșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈLI  

является комментарием. Обычно комментарий располагается на отдельной строке,


как показано здесь:
ʴʴʴɤɭɥȥŵȠȜȡƋɭɥȠȜȡŵȫƋɩɫȫŵȘșȡȰ
ʴʴʴ•‡ ‘†•ɏ’‡”ɏ†ƒ›ʰɯɭɫɥɥ

Или на той же строке, что и код, который нужно пояснить:


ʴʴʴ•‡ ‘†•ɏ’‡”ɏ†ƒ›ʰɯɭɫɥɥɤɭɥȥŵȠȜȡƋɭɥȠȜȡŵȫƋɩɫȫŵȘșȡȰ

Символ # имеет много имен: хеш, шарп, фунт или устрашающее октоторп.
Как бы вы его ни назвали, эффект # действует только до конца строки, на которой
он располагается.
Python не дает возможности написать многострочный комментарий. Каждую
строку или раздел комментария следует начинать с символа #:
ʴʴʴɤǿȠȢȗȧȥȞȔțȔȦȰțȘșȥȰȖȥșřȘȔȚșșȥȟȜ›–Š‘ȱȦȢȡșȡȤȔȖȜȦȥȳř
ŜŜŜɤȣȢȥȞȢȟȰȞȧȳțȔȭȜȭșȡȞȤȧȦȯȠ
ŜŜŜɤȢȞȦȢȦȢȤȣȢȠŜ
ŜŜŜ
ʴʴʴ

Однако если октоторп находится внутри текстовой строки, он становится про-


стым символом #:
ʴʴʴ’”‹–ſɑ‘ ‘‡–ś“—‘–‡•ƒ‡–ЇɤŠƒ”Ž‡••Ŝɑƀ
‘ ‘‡–ś“—‘–‡•ƒ‡–ЇɤŠƒ”Ž‡••Ŝ

ǷȘȖȌȓȍȊȈȍȔșȚȘȖȒȐșȗȖȔȖȡȤȦșȐȔȊȖȓȈ?
Любая программа становится более удобочитаемой, если ее строки сравнительно
короткие. Рекомендуемая (но не обязательная) максимальная длина строки рав-
на 80 символам. Если вы не можете выразить свою мысль в рамках 80 символов,
воспользуйтесь символом продолжения Ɏ — просто поместите его в конце строки,
и дальше Python будет действовать так, как будто это все та же строка.
Например, если бы я хотел создать длинную строку из нескольких коротких,
я мог бы сделать это пошагово:
ʴʴʴ•—ʰɥ
ʴʴʴ•—ʫʰɨ
ʴʴʴ•—ʫʰɩ
ʴʴʴ•—ʫʰɪ
ʴʴʴ•—ʫʰɫ
ʴʴʴ•—
ɨɥ

Но мог бы сделать и в одно действие, используя символ продолжения:


ʴʴʴ•—ʰɨʫɎ
ŜŜŜɩʫɎ
ŜŜŜɪʫɎ
ŜŜŜɫ
ʴʴʴ•—
ɨɥ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Если мы оставим обратный слеш в середине выражения, будет сгенерировано


исключение:
ʴʴʴ•—ʰɨʫ
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨ
•—ʰɨʫ
ɋ
›–ƒš””‘”ś‹˜ƒŽ‹†•›–ƒš

Есть небольшая хитрость: если использовать парные круглые (а также квадратные


или фигурные) скобки, Python не будет жаловаться на некорректное окончание строк:
ʴʴʴ•—ʰſ
ŜŜŜɨʫ
ŜŜŜɩʫ
ŜŜŜɪʫ
ŜŜŜɫƀ
ʴʴʴ
ʴʴʴ•—
ɨɥ

В главе 5 вы также увидите, как парные тройные кавычки позволяют создавать


многострочные выражения.

ǹȘȈȊȕȐȊȈȍȔșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȖȊLIHOLIȐHOVH
И вот мы готовы сделать первый шаг к структурам кода, которые вводят данные
в программы. В качестве первого примера рассмотрим небольшую программу,
которая проверяет значение булевой переменной †‹•ƒ•–‡” и выводит подходящий
комментарий:
ʴʴʴ†‹•ƒ•–‡”ʰ”—‡
ʴʴʴ‹ˆ†‹•ƒ•–‡”ś
ŜŜŜ’”‹–ſɑ‘‡Šɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑЇ‡Šɑƀ
ŜŜŜ
‘‡Š
ʴʴʴ

Строки if и else в Python выступают операторами, которые проверяют, явля-


ется ли значение выражения (в данном случае переменной †‹•ƒ•–‡”) равным ”—‡.
Помните, ’”‹–ſƀ — это встроенная в Python функция для вывода информации, как
правило, на экран.

ǭșȓȐȘȈȕȍȍȊȣȘȈȉȖȚȈȓȐșȌȘțȋȐȔȐȧȏȣȒȈȔȐȗȘȖȋȘȈȔȔȐȘȖȊȈȕȐȧȖȉȘȈȚȐȚȍȊȕȐȔȈ
ȕȐȍȕȈȚȖȟȚȖȏȌȍșȤȗȘȐȗȘȖȊȍȘȒȍLIșȚȈȊȐȚȤșȒȖȉȒȐȕȍȕțȎȕȖǵȈȗȘȐȔȍȘȕȍȕȈȌȖ
ȗȐșȈȚȤȟȚȖȚȖȊȘȖȌȍLI GLVDVWHU 7UXH ǪȒȖȕȞȍșȚȘȖȒȐșȓȍȌțȍȚȗȖșȚȈȊȐȚȤȌȊȖȍ
ȚȖȟȐȍ  ǭșȓȐȊȣȒȈȒȐȕȖȋȌȈȐȧȏȈȉțȌȍȚȍȗȖșȚȈȊȐȚȤȌȊȖȍȚȖȟȐȍ3\WKRQȊȣȊȍȌȍȚ
șȖȖȉȡȍȕȐȍȖȉȖȠȐȉȒȍ
ǫȓȈȊȈǪȣȉȐȘȈȍȔșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈLI  

Каждая строка ’”‹–ſƀ имеет отступ под соответствующей проверкой. Я исполь-


зовал отступ в четыре пробела для того, чтобы выделять подразделы. Вы можете ис-
пользовать любое количество пробелов, однако Python ожидает, что внутри одного
раздела будет применяться одинаковое количество пробелов. Рекомендованный
стиль — PEP-8 (KWWSELWO\SHS) — предписывает использовать четыре пробела.
Не применяйте табуляцию или сочетание табуляций и пробелов — это мешает
считать отступы.
Все выполненные в этом примере действия позже я объясню более детально.
‰Булево значение ”—‡ присваивается переменной †‹•ƒ•–‡”.
‰Производится условное сравнение при помощи операторов if и else с выполне-
нием разных фрагментов кода в зависимости от значений переменной †‹•ƒ•–‡”.
‰Вызывается функция ’”‹–ſƀ для вывода текста на экран.
Вы можете организовать проверку в проверке столько раз, сколько посчитаете
нужным:
ʴʴʴˆ—””›ʰ”—‡
ʴʴʴŽƒ”‰‡ʰ”—‡
ʴʴʴ‹ˆˆ—””›ś
ŜŜŜ‹ˆŽƒ”‰‡ś
ŜŜŜ’”‹–ſɑ –ɐ•ƒ›‡–‹Ŝɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ –ɐ•ƒ ƒ–Šɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ‹ˆŽƒ”‰‡ś
ŜŜŜ’”‹–ſɑ –ɐ•ƒ™ŠƒŽ‡Šɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ –ɐ•ƒŠ—ƒŜ”ƒŠƒ‹”އ•• ƒ–Ŝɑƀ
ŜŜŜ
–ɐ•ƒ›‡–‹Ŝ

В Python отступы определяют, какие разделы if и else объединены в пару. Наша


первая проверка обращалась к переменной furry. Поскольку ее значение равно ”—‡,
Python переходит к выделенной таким же количеством пробелов проверке if large.
Поскольку мы указали значение переменной large равным ”—‡, проверка вернет
результат ”—‡ , а следующая строка else будет проигнорирована. Это заставит
Python запустить строку, размещенную под конструкцией if large, и вывести на
экран строку –ɐ• a yeti.
Если нужно проверить больше двух вариантов, используйте оператор if для
первого варианта, elif (это значит else if — «иначе если») для промежуточных
и else для последнего:
ʴʴʴ ‘Ž‘”ʰɑƒ—˜‡ɑ
ʴʴʴ‹ˆ ‘Ž‘”ʰʰɑ”‡†ɑś
ŜŜŜ’”‹–ſɑ –ɐ•ƒ–‘ƒ–‘ɑƀ
ŜŜŜ‡Ž‹ˆ ‘Ž‘”ʰʰɑ‰”‡‡ɑś
ŜŜŜ’”‹–ſɑ –ɐ•ƒ‰”‡‡’‡’’‡”ɑƀ
ŜŜŜ‡Ž‹ˆ ‘Ž‘”ʰʰɑ„‡‡’—”’އɑś
ŜŜŜ’”‹–ſɑ †‘ɐ–‘™™Šƒ–‹–‹•ř„—–‘Ž›„‡‡• ƒ•‡‡‹–ɑƀ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ ɐ˜‡‡˜‡”Їƒ”†‘ˆ–Ї ‘Ž‘”ɑř ‘Ž‘”ƀ
ŜŜŜ
ɐ˜‡‡˜‡”Їƒ”†‘ˆ–Ї ‘Ž‘”ƒ—˜‡

В предыдущем примере мы проверяли равенство с помощью оператора ʰʰ .


В Python используются следующие операторы сравнения:
‰равенство (ʰʰ);
‰неравенство (Šʰ);
‰меньше (ʳ);
‰меньше или равно (ʳʰ);
‰больше (ʴ);
‰больше или равно (ʴʰ).
Эти операторы возвращают булевы значения ”—‡ или ƒŽ•‡. Посмотрим на то,
как они работают, но сначала присвоим значение переменной š:
ʴʴʴšʰɮ

Теперь выполним несколько проверок:


ʴʴʴšʰʰɬ
ƒŽ•‡
ʴʴʴšʰʰɮ
”—‡
ʴʴʴɬʳš
”—‡
ʴʴʴšʳɨɥ
”—‡

Обратите внимание на то, что для проверки на равенство используются два зна-
ка «равно» (ʰʰ). Помните, что один знак «равно» применяется для присваивания
значения переменной.
Если нужно выполнить несколько сравнений одновременно, можно использо-
вать логические (или булевы) операторы ƒ†, or и not для определения итогового
логического результата.
Булевы операторы имеют более низкий приоритет по сравнению с фрагментами
кода, которые они сравнивают. Это значит, что результаты фрагментов сначала вы-
числяются, а затем сравниваются. Поскольку в данном примере мы устанавливаем
значение ȩ равным 7, проверка ɬ ʳ ȩ возвращает значение ”—‡, проверка ȩ ʳ ɨɥ также
возвращает ”—‡, поэтому наше выражение преобразуется в ”—‡ ƒ† ”—‡:
ʴʴʴɬʳšandšʳɨɥ
”—‡

Как указывается в подразделе «Приоритет операций» на с. 73, самый простой


способ избежать путаницы — использовать круглые скобки:
ʴʴʴſɬʳšƀandſšʳɨɥƀ
”—‡
ǫȓȈȊȈǪȣȉȐȘȈȍȔșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈLI  

Рассмотрим некоторые другие проверки:


ʴʴʴɬʳšoršʳɨɥ
”—‡
ʴʴʴɬʳšandšʴɨɥ
ƒŽ•‡
ʴʴʴɬʳšandnotšʴɨɥ
”—‡

Если вы используете оператор ƒ† для того, чтобы объединить несколько про-
верок, Python позволит вам сделать следующее:
ʴʴʴɬʳšʳɨɥ
”—‡

Это выражение аналогично проверкам ɬ ʳ š и š ʳ ɨɥ. Вы также можете писать


более длинные сравнения:
ʴʴʴɬʳšʳɨɥʳɰɰɰ
”—‡

ǿȚȖȍșȚȤȐșȚȐȕȈ"
Что, если элемент, который мы проверяем, не является булевым? Чем Python счи-
тает ”—‡ и ƒŽ•‡?
Значение false не обязательно должно быть явно логическим ƒŽ•‡. Например,
к ƒŽ•‡ приравниваются следующие значения:
‰булева переменная ƒŽ•‡;
‰значение ‘‡;
‰целое число ɥ;
‰число с плавающей точкой ɥŜɥ;
‰пустая строка (ɐ ɐ);
‰пустой список (ƃƄ);
‰пустой кортеж (ſƀ);
‰пустой словарь (Ƈƈ);
‰пустое множество (•‡–ſƀ).
Все остальные значения приравниваются к ”—‡. Программы, написанные на
Python, используют это определение истинности или ложности, чтобы выполнять
проверку на пустоту структуры данных наряду с проверкой на равенство непосред-
ственно значению ƒŽ•‡:
ʴʴʴ•‘‡ɏŽ‹•–ʰƃƄ
ʴʴʴ‹ˆ•‘‡ɏŽ‹•–ś
ŜŜŜ’”‹–ſɑЇ”‡ɐ••‘‡–Š‹‰‹Ї”‡ɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ ‡›ř‹–ɐ•‡’–›Šɑƀ
ŜŜŜ
‡›ř‹–ɐ•‡’–›Š
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

При проверке выражения, а не простой переменной Python оценивает его значе-


ние и возвращает булев результат. Поэтому, если вы введете следующее:
‹ˆ ‘Ž‘”ʰʰɑ”‡†ɑś

Python оценит выражение ‘Ž‘” ʰʰ ɑ”‡†ɑ. В нашем примере мы присвоили пере-


менной ‘Ž‘” значение ɑƒ—˜‡ɑ, поэтому значение выражения ‘Ž‘” ʰʰ ɑ”‡†ɑ равно
ƒŽ•‡ и Python перейдет к следующей проверке:
‡Ž‹ˆ ‘Ž‘”ʰʰɑ‰”‡‡ɑś

ǪȣȗȖȓȕȧȍȔȕȍșȒȖȓȤȒȖșȘȈȊȕȍȕȐȑ
șȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈLQ
Предположим, что у вас есть буква и вы хотите узнать, является ли она гласной.
Одним из вариантов решения может быть создание длинного утверждения if:
ʴʴʴއ––‡”ʰɐ‘ɐ
ʴʴʴ‹ˆއ––‡”ʰʰɐƒɐorއ––‡”ʰʰɐ‡ɐorއ––‡”ʰʰɐ‹ɐɎ
ŜŜŜorއ––‡”ʰʰɐ‘ɐorއ––‡”ʰʰɐ—ɐś
ŜŜŜ’”‹–ſއ––‡”řɐ‹•ƒ˜‘™‡Žɐƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſއ––‡”řɐ‹•‘–ƒ˜‘™‡Žɐƀ
ŜŜŜ
‘‹•ƒ˜‘™‡Ž
ʴʴʴ

Каждый раз, когда вам нужно выполнить множество подобных сравнений, раз-
деленных ключевым словом or, используйте оператор членства in. В следующем
примере мы проверяем, является ли буква гласной, более «питонским» способом,
используя строку, состоящую целиком из гласных:
ʴʴʴ˜‘™‡Ž•ʰɐƒ‡‹‘—ɐ
ʴʴʴއ––‡”ʰɐ‘ɐ
ʴʴʴއ––‡”in˜‘™‡Ž•
”—‡
ʴʴʴ‹ˆއ––‡”in˜‘™‡Ž•ś
ŜŜŜ’”‹–ſއ––‡”řɐ‹•ƒ˜‘™‡Žɐƀ
ŜŜŜ
‘‹•ƒ˜‘™‡Ž

Рассмотрим также небольшой пример того, как можно использовать оператор in


для некоторых типов данных, о которых более подробно мы поговорим в нескольких
следующих главах:
ʴʴʴއ––‡”ʰɐ‘ɐ
ʴʴʴ˜‘™‡Žɏ•‡–ʰƇɐƒɐřɐ‡ɐřɐ‹ɐřɐ‘ɐřɐ—ɐƈ
ʴʴʴއ––‡”in˜‘™‡Žɏ•‡–
”—‡
ʴʴʴ˜‘™‡ŽɏŽ‹•–ʰƃɐƒɐřɐ‡ɐřɐ‹ɐřɐ‘ɐřɐ—ɐƄ
ǫȓȈȊȈǪȣȉȐȘȈȍȔșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈLI  

ʴʴʴއ––‡”in˜‘™‡ŽɏŽ‹•–
”—‡
ʴʴʴ˜‘™‡Žɏ–—’އʰſɐƒɐřɐ‡ɐřɐ‹ɐřɐ‘ɐřɐ—ɐƀ
ʴʴʴއ––‡”in˜‘™‡Žɏ–—’އ
”—‡
ʴʴʴ˜‘™‡Žɏ†‹ –ʰƇɐƒɐśɐƒ’’އɐřɐ‡ɐśɐ‡Ž‡’Šƒ–ɐř
ŜŜŜɐ‹ɐśɐ‹’ƒŽƒɐřɐ‘ɐśɐ‘ ‡Ž‘–ɐřɐ—ɐśɐ—‹ ‘”ɐƈ
ʴʴʴއ––‡”in˜‘™‡Žɏ†‹ –
”—‡
ʴʴʴ˜‘™‡Žɏ•–”‹‰ʰɑƒ‡‹‘—ɑ
ʴʴʴއ––‡”in˜‘™‡Žɏ•–”‹‰
”—‡

В случае со словарем оператор in проверяет ключи (они находятся слева от двое-


точия), а не значения.

ǵȖȊȖȍ,$PWKH:DOUXV
В Python 3.8 появился оператор-морж, который выглядит следующим образом:
ȜȠȳśʰȖȯȤȔȚșȡȜș

Заметили моржа? (Он похож на смайлик с бивнями.)


Как правило, для присваивания и проверки нужно выполнить два шага:
ʴʴʴ–™‡‡–ɏŽ‹‹–ʰɩɯɥ
ʴʴʴ–™‡‡–ɏ•–”‹‰ʰɑŽƒŠɑƋɬɥ
ʴʴʴ†‹ˆˆʰ–™‡‡–ɏŽ‹‹–Şއſ–™‡‡–ɏ•–”‹‰ƀ
ʴʴʴ‹ˆ†‹ˆˆʴʰɥś
ŜŜŜ’”‹–ſɑˆ‹––‹‰–™‡‡–ɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ‡–‘˜‡”„›ɑřƒ„•ſ†‹ˆˆƀƀ
ŜŜŜ
ˆ‹––‹‰–™‡‡–

С помощью новой силы клыков (операторов присваивания) мы можем два шага


объединить в один:
ʴʴʴ–™‡‡–ɏŽ‹‹–ʰɩɯɥ
ʴʴʴ–™‡‡–ɏ•–”‹‰ʰɑŽƒŠɑƋɬɥ
ʴʴʴ‹ˆ†‹ˆˆśʰ–™‡‡–ɏŽ‹‹–Şއſ–™‡‡–ɏ•–”‹‰ƀʴʰɥŚ
ŜŜŜ’”‹–ſɑˆ‹––‹‰–™‡‡–ɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ‡–‘˜‡”„›ɑřƒ„•ſ†‹ˆˆƀƀ
ŜŜŜ
ˆ‹––‹‰–™‡‡–

Оператор-морж также может использоваться в циклах for и while, которые мы


рассмотрим в главе 6.

1
Название песни группы The Beatles. — Примеч. пер.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǿȐȚȈȑȚȍȌȈȓȍȍ
Поговорим о строках и рассмотрим знаковые символы.

ǻȗȘȈȎȕȍȕȐȧ
4.1. Выберите число от 1 до 10 и присвойте его переменной •‡ ”‡–. Выберите еще
одно число от 1 до 10 и присвойте его переменной guess. Далее напишите услов-
ные проверки (if, else и elif), чтобы вывести строку ɐ–‘‘ Ž‘™ɐ, если значение
переменной guess меньше 7, ɐ–‘‘ Š‹‰Šɐ, если оно больше 7, и ɐŒ—•– ”‹‰Š–ɐ, если
равно •‡ ”‡–.
4.2. Присвойте значения ”—‡ или ƒŽ•‡ переменным •ƒŽŽ и green. Напишите не-
сколько утверждений if/else, которые выведут на экран информацию о том,
соответствуют ли заданным условиям следующие растения: вишня, горошек,
арбуз, тыква.
ƋƓƈƊƈ
ǺȍȒșȚȖȊȣȍșȚȘȖȒȐ

Мне всегда нравились странные персонажи.


Тим Бёртон

Благодаря книгам о компьютерах может сложиться впечатление, что программиро-


вание — это чистая математика. На самом деле большинство программистов гораздо
чаще работают с текстовыми строками, а не с числами. В таком случае логическое
(и креативное!) мышление бывает гораздо важнее математических навыков.
Строки являются первым примером последовательностей в Python. В частно-
сти, они представляют собой последовательности символов. Но что такое символ?
Это наименьшая единица письменной системы, которая может быть буквой, цифрой,
специальным символом, знаком препинания и даже пробелом или директивой вроде
linefeeds. Символ определяется своим значением (тем, как он используется), а не
тем, как он выглядит. У него может быть более одного визуального представления
(в разных шрифтах), и, в свою очередь, одинаковое представление могут иметь не-
сколько символов (например, символ ǭ в латинском алфавите обозначает звук «х»,
а в кириллическом — «н»).
В этой главе рассматривается создание и форматирование простых текстовых
строк на примере базового набора символов ASCII. Две важные темы, касающиеся
текстов, обсуждаются в главе 12: символы Unicode (к этой теме относится ситуация
с символом ǭ, о которой я только что упомянул) и регулярные выражения (сравнение
с шаблоном).
В отличие от других языков в Python строки являются неизменяемыми. Вы не мо-
жете изменить саму строку, но можете скопировать части строк в другую строку,
чтобы добиться подобного эффекта. Скоро вы узнаете, как это делается.

ǹȖȏȌȈȍȔșȚȘȖȒȐșȗȖȔȖȡȤȦȒȈȊȣȟȍȒ
Строка в Python создается заключением символов в парные одинарные или двойные
кавычки:
ʴʴʴɐƒ’ɐ
ɐƒ’ɐ
ʴʴʴɑ”ƒ Ž‡ɑ
ɐ”ƒ Ž‡ɐ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Интерактивный интерпретатор выводит на экран строки в одинарных кавычках,


но все они обрабатываются одинаково.

Ǫ3\WKRQșțȡȍșȚȊțȍȚȕȍșȒȖȓȤȒȖȖșȖȉȣȝȚȐȗȖȊșȚȘȖȒȖȗȘȍȌȍȓȧȍȔȣȝȉțȒȊȖȑșȚȖȧȡȍȑ
ȗȍȘȍȌȗȍȘȊȖȑȒȈȊȣȟȒȖȑǹȉțȒȊȣIȐȓȐ)ȕȈȟȐȕȈȍȚșȧIșȚȘȖȒȈȒȖȚȖȘȈȧȐșȗȖȓȤȏțȍȚșȧ
ȌȓȧȜȖȘȔȈȚȐȘȖȊȈȕȐȧȖȕȈȖȗȐșȈȕȈȊȒȖȕȞȍȋȓȈȊȣǹȉțȒȊȣUȐȓȐ5ȕȈȟȐȕȈȍȚșȧȕȍȖȉ
ȘȈȉȖȚȈȕȕȈȧșȚȘȖȒȈ²ȖȕȈȐșȗȖȓȤȏțȍȚșȧȌȓȧȗȘȍȌȖȚȊȘȈȡȍȕȐȧșȖȏȌȈȕȐȧțȗȘȈȊȓȧȦȡȐȝ
șȐȔȊȖȓȖȊȊșȚȘȖȒȍ șȔȘȈȏȌȍȓ©ǹȖȏȌȈȍȔHVFDSHȗȖșȓȍȌȖȊȈȚȍȓȤȕȖșȚȐșȗȖȔȖȡȤȦ
șȐȔȊȖȓȈ?ªȕȈșȐȋȓȈȊțȊȒȖȚȖȘȖȑȘȈșșȒȈȏȣȊȈȍȚșȧȖȉȐȝȐșȗȖȓȤȏȖȊȈȕȐȐȗȘȐ
ȗȘȖȊȍȘȒȍȕȈșȖȖȚȊȍȚșȚȊȐȍȠȈȉȓȖȕț ǪȖȏȔȖȎȕȈȐȒȖȔȉȐȕȈȞȐȧIU ȈȚȈȒȎȍ)5)UȐȓȐ
I5 șȒȖȚȖȘȖȑȕȈȟȐȕȈȍȚșȧȕȍȖȉȘȈȉȖȚȈȕȕȈȧIșȚȘȖȒȈǩțȒȊȖȑXȏȈȗțșȒȈȍȚșȧșȚȘȖȒȈ
ȐȏșȐȔȊȖȓȖȊ8QLFRGHȈȕȈȓȖȋȐȟȕȈȧȗȘȖșȚȖȑșȚȘȖȒȍǹȉțȒȊȣEȕȈȟȐȕȈȍȚșȧȏȕȈȟȍȕȐȍ
ȖȉȢȍȒȚȈȚȐȗȈE\WHV șȔȋȓȈȊț ǭșȓȐȧȕȍțȗȖȔȐȕȈȦȖȌȐȕȐȏȥȚȐȝȖșȖȉȣȝȚȐȗȖȊ
ȏȕȈȟȐȚȘȍȟȤȐȌȍȚȖșȚȈȘȖȑȌȖȉȘȖȑȚȍȒșȚȖȊȖȑșȚȘȖȒȍșȖȌȍȘȎȈȡȍȑșȐȔȊȖȓȣ8QLFRGH

Зачем нужны два вида кавычек? Основная идея заключается в том, чтобы по-
зволить программисту создавать строки, содержащие символы кавычек. Вы можете
пользоваться одинарными кавычками внутри строк, созданных с помощью двойных
кавычек, и наоборот:
ʴʴʴɑɐƒ›řɐ•ƒ‹†–Їƒ›•ƒ›‡”Ŝɐ‡‹‰Šţɐ•ƒ‹†–ЇŠ‘”•‡Ŝɑ
ɑɐƒ›řɐ•ƒ‹†–Їƒ›•ƒ›‡”Ŝɐ‡‹‰Šţɐ•ƒ‹†–ЇŠ‘”•‡Ŝɑ
ʴʴʴɐЇ”ƒ”‡†‘—„އ“—‘–‡‹ ƒ’–‹˜‹–›śɑŜɐ
ɐЇ”ƒ”‡†‘—„އ“—‘–‡‹ ƒ’–‹˜‹–›śɑŜɐ
ʴʴʴɐɑ–™‘„›ˆ‘—”ɑ‹•ƒ –—ƒŽŽ›ɨɨŵɩɑʮɪɨŵɩɑŜɐ
ɐɑ–™‘„›ˆ‘—”‹•ɑƒ –—ƒŽŽ›ɨɨŵɩɑʮɪɨŵɩɑŜɐ
ʴʴʴɑɐЇ”‡ɐ•–Їƒ–Šƒ–•Š‘–›’ƒ™Šɐ ”‹‡†–ЇŽ‹’‹‰Š‘—†Ŝɑ
ɑɐЇ”‡ɐ•–Їƒ–Šƒ–•Š‘–›’ƒ™Šɐ ”‹‡†–ЇŽ‹’‹‰Š‘—†Ŝɑ

Допускается также использование трех одинарных (ɐɐɐ) или трех двойных ка-
вычек ("""):
ʴʴʴɐɐɐ‘‘Šɐɐɐ
ɐ‘‘ɐ
ʴʴʴɑɑɑ‡Šɑɑɑ
ɐ‡Šɐ

Тройные кавычки не очень подходят для таких коротких строк. Обычно они ис-
пользуются для того, чтобы создавать многострочный текст наподобие следующего
классического стихотворения Эдварда Лира:
ʴʴʴ’‘‡ʰɐɐɐЇ”‡™ƒ•ƒ‘—‰ƒ†›‘ˆ‘”™ƒ›ř
ŜŜŜŠ‘ ƒ•—ƒŽŽ›•ƒ–‹ƒ†‘‘”™ƒ›Ś
ŜŜŜЇ–Ї†‘‘”•“—‡‡œ‡†Ї”ˆŽƒ–ř
ŜŜŜЇ‡š Žƒ‹‡†řɑŠƒ–‘ˆ–Šƒ–ţɑ
ŜŜŜŠ‹• ‘—”ƒ‰‡‘—•‘—‰ƒ†›‘ˆ‘”™ƒ›Ŝɐɐɐ
ʴʴʴ

(Это стихотворение было введено в интерактивный интерпретатор, кото-


рый поприветствовал нас символами ʴʴʴ в первой строке и выводил пригла-
ǫȓȈȊȈǺȍȒșȚȖȊȣȍșȚȘȖȒȐ  

шения … до тех пор, пока мы не ввели последние тройные кавычки и не перешли


к следующей строке.)
Если вы попытаетесь создать стихотворение без тройных кавычек, Python начнет
волноваться, когда вы перейдете к следующей строке:
ʴʴʴ’‘‡ʰɐЇ”‡™ƒ•ƒ›‘—‰Žƒ†›‘ˆ‘”™ƒ›ř
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨ
’‘‡ʰɐЇ”‡™ƒ•ƒ›‘—‰Žƒ†›‘ˆ‘”™ƒ›ř
ɋ
›–ƒš””‘”ś™Š‹Ž‡• ƒ‹‰•–”‹‰Ž‹–‡”ƒŽ
ʴʴʴ

Если внутри тройных кавычек располагается несколько строк, символы конца


строки будут сохранены в строке. Если есть начальные или конечные пробелы, они
также будут сохранены:
ʴʴʴ’‘‡ɩʰɐɐɐ †‘‘–Ž‹‡–Ї‡ř‘ –‘” ‡ŽŽŜ
ŜŜŜЇ”‡ƒ•‘™Š›ř  ƒ‘––‡ŽŽŜ
ŜŜŜ—––Š‹• ‘™řƒ†‘™ˆ—ŽŽ™‡ŽŽś
ŜŜŜ †‘‘–Ž‹‡–Ї‡ř‘ –‘” ‡ŽŽŜ
ŜŜŜɐɐɐ
ʴʴʴ’”‹–ſ’‘‡ɩƀ
†‘‘–Ž‹‡–Ї‡ř‘ –‘” ‡ŽŽŜ
Ї”‡ƒ•‘™Š›ř  ƒ‘––‡ŽŽŜ
—––Š‹• ‘™řƒ†‘™ˆ—ŽŽ™‡ŽŽś
 †‘‘–Ž‹‡–Ї‡ř‘ –‘” ‡ŽŽŜ
ʴʴʴ

Кстати, существует разница между выводом на экран с помощью функции


’”‹–ſƀ и автоматическим выводом на экран с помощью интерактивного интер-
претатора:
ʴʴʴ’‘‡ɩ
ɐ †‘‘–Ž‹‡–Ї‡ř‘ –‘” ‡ŽŽŜɎЇ”‡ƒ•‘™Š›ř  ƒ‘––‡ŽŽŜɎ—–
–Š‹• ‘™řƒ†‘™ˆ—ŽŽ™‡ŽŽśɎ †‘‘–Ž‹‡–Ї‡ř‘ –‘” ‡ŽŽŜɎɐ

Функция ’”‹–ſƀ выводит на экран содержимое строк и при этом удаляет из


них кавычки. Она предназначена для удобства пользователя — услужливо добав-
ляет пробел между каждым выводимым объектом, а также символ новой строки
в конце:
ʴʴʴ’”‹–ſɐ ‹˜‡ɐřɑ—•ɑřɐɐɐ•‘‡ɐɐɐřɑɑɑ•’ƒ ‡ɑɑɑƀ
‹˜‡—••‘‡•’ƒ ‡

Если вам не нужны пробелы или переход на новую строку, в главе 14 вы узнаете,
как от них избавиться.
Интерактивный интерпретатор выводит строку с одинарными кавычками
и управляющими символами, такими как Ɏ: это объясняется в разделе «Создаем
escape-последовательности с помощью символа \» далее в этой главе.
ʴʴʴɑɑɑɐ —–‡‘”‰‡ř‡‹ ‡””Šɐ
ŜŜŜ•ƒ‹†ƒ†‹‰—†™‹‰–‘Š‹•™‹‰Ŝɑɑɑ
ɑɐ —–‡‘”‰‡ř‡‹ ‡””ŠɐɎ•ƒ‹†ƒ†‹‰—†™‹‰–‘Š‹•™‹‰Ŝɑ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

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

ǹȖȏȌȈȍȔșȚȘȖȒȐșȗȖȔȖȡȤȦȜțȕȒȞȐȐVWU
Создать строку из другого типа данных можно с помощью функции •–”ſƀ:
ʴʴʴ•–”ſɰɯŜɭƀ
ɐɰɯŜɭɐ
ʴʴʴ•–”ſɨŜɥ‡ɫƀ
ɐɨɥɥɥɥŜɥɐ
ʴʴʴ•–”ſ”—‡ƀ
ɐ”—‡ɐ

В Python функция •–”ſƀ используется также для внутренних нужд: например,


при вызове функции ’”‹–ſƀ для объектов, которые не являются строками, и при
форматировании строк, о чем мы поговорим далее в этой главе.

ǹȖȏȌȈȍȔHVFDSHȗȖșȓȍȌȖȊȈȚȍȓȤȕȖșȚȐ
șȗȖȔȖȡȤȦșȐȔȊȖȓȈ?
Python позволяет использовать escape-последовательности внутри строк, чтобы
добиться эффекта, который по-другому выразить было бы трудно. Символ с раз-
мещенным перед ним обратным слешем (Ɏ) получает особое значение. Наиболее
распространена последовательность Ɏ, которая означает переход на новую строку.
С ее помощью можно создавать многострочные строки из однострочных:
ʴʴʴ’ƒŽ‹†”‘‡ʰɐƒř\n’Žƒř\n ƒƒŽś\nƒƒƒŜɐ
ʴʴʴ’”‹–ſ’ƒŽ‹†”‘‡ƀ
ƒř
’Žƒř
 ƒƒŽś
ƒƒƒŜ

Последовательность Ɏ– (табуляция) используется для выравнивания текста:


ʴʴʴ’”‹–ſɐ\tƒ„ ɐƀ
ƒ„
ǫȓȈȊȈǺȍȒșȚȖȊȣȍșȚȘȖȒȐ  

ʴʴʴ’”‹–ſɐƒ\t„ ɐƀ
ƒ„
ʴʴʴ’”‹–ſɐƒ„\t ɐƀ
ƒ„
ʴʴʴ’”‹–ſɐƒ„ \tɐƀ
ƒ„

(В последней строке табуляция стоит в конце, но увидеть ее вы, конечно,


не можете.)
Кроме того, вам могут понадобиться последовательности Ɏɐ или Ɏɑ , чтобы
поместить одинарные или двойные кавычки в строку, заключенную в такие же
символы:
ʴʴʴ–‡•–‹‘›ʰɑ\" †‹†‘–Š‹‰Š\"Ї•ƒ‹†Ŝ\"”–Šƒ–‘–Ї”–Š‹‰Ŝ\""
ʴʴʴ–‡•–‹‘›
ɐɑ †‹†‘–Š‹‰ŠɑЇ•ƒ‹†Ŝɑ”–Šƒ–‘–Ї”–Š‹‰Ŝɑɐ
ʴʴʴ’”‹–ſ–‡•–‹‘›ƀ
ɑ †‹†‘–Š‹‰ŠɑЇ•ƒ‹†Ŝɑ”–Šƒ–‘–Ї”–Š‹‰Ŝɑ

ʴʴʴˆƒ –ʰɑЇ™‘”ކɐ•Žƒ”‰‡•–”—„„‡”†— ™ƒ•ɬɫɐɩ\"„›ɭɬɐɮ\"„›ɨɥɬɐɑ


ʴʴʴ’”‹–ſˆƒ –ƀ
Ї™‘”ކɐ•Žƒ”‰‡•–”—„„‡”†— ™ƒ•ɬɫɐɩɑ„›ɭɬɐɮɑ„›ɨɥɬɐ

А если вам нужен обратный слеш, просто напечатайте два (первый из них экра-
нирует второй):
ʴʴʴ•’‡‡ ŠʰɐЇ„ƒ •Žƒ•Šſ\\ƀ„‡†•‘˜‡”„ƒ ™ƒ”†•–‘’އƒ•‡›‘—Ŝɐ
ʴʴʴ’”‹–ſ•’‡‡ Šƀ
Ї„ƒ •Žƒ•ŠſɎƀ„‡†•‘˜‡”„ƒ ™ƒ”†•–‘’އƒ•‡›‘—Ŝ
ʴʴʴ

Как я упоминал ранее в этой главе, в необработанной строке escape-символы


не работают:
ʴʴʴ‹ˆ‘ʰ”ɐ›’‡ƒɎ–‘‰‡–ƒ‡™Ž‹‡‹ƒ‘”ƒŽ•–”‹‰ɐ
ʴʴʴ‹ˆ‘
ɐ›’‡ƒɎɎ–‘‰‡–ƒ‡™Ž‹‡‹ƒ‘”ƒŽ•–”‹‰ɐ
ʴʴʴ’”‹–ſ‹ˆ‘ƀ
›’‡ƒɎ–‘‰‡–ƒ‡™Ž‹‡‹ƒ‘”ƒŽ•–”‹‰

(Интерактивный интерпретатор добавил дополнительный обратный слеш при


первом отображении значения переменной info.)
В необработанных строках работают все реальные (а не выполненные с помощью
последовательности ɐɎɐ) переходы на новую строку:
ʴʴʴ’‘‡ʰ”ɐɐɐ‘›•ƒ†‰‹”Ž•ř ‘‡‘—––‘’Žƒ›Ŝ
ŜŜŜЇ‘‘†‘–ЕЋ‡ƒ•„”‹‰Š–ƒ•†ƒ›Ŝɐɐɐ
ʴʴʴ’‘‡
ɐ‘›•ƒ†‰‹”Ž•ř ‘‡‘—––‘’Žƒ›ŜɎЇ‘‘†‘–ЕЋ‡ƒ•„”‹‰Š–ƒ•†ƒ›Ŝɐ
ʴʴʴ’”‹–ſ’‘‡ƀ
‘›•ƒ†‰‹”Ž•ř ‘‡‘—––‘’Žƒ›Ŝ
Ї‘‘†‘–ЕЋ‡ƒ•„”‹‰Š–ƒ•†ƒ›Ŝ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǶȉȢȍȌȐȕȧȍȔșȚȘȖȒȐșȐșȗȖȓȤȏȖȊȈȕȐȍȔșȐȔȊȖȓȈ
В Python вы можете объединить строки или строковые переменные с помощью
оператора ʫ, как показано далее:
ʴʴʴɐ‡Ž‡ƒ•‡–Ї”ƒ‡Šɐʫɐ‘ř™ƒ‹–Šɐ
ɐ‡Ž‡ƒ•‡–Ї”ƒ‡Šɐ‘ř™ƒ‹–Šɐ

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


другой:
ʴʴʴɑ›™‘”†Šɑɑ‰‡–އƒ ƒŽŽ‡”Šɑ
ɐ›™‘”†Š‰‡–އƒ ƒŽŽ‡”Šɐ
ʴʴʴɑŽƒ•ŠɑɑЇ”ƒ‡Šɑ
ɐŽƒ•ŠЇ”ƒ‡Šɐ

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


можно, заключив строки в скобки:
ʴʴʴ˜‘™‡Ž•ʰſɐƒɐ
ŜŜŜɑ‡ɑɐɐɐ‹ɐɐɐ
ŜŜŜɐ‘ɐɑɑɑ—ɑɑɑ
ŜŜŜƀ
ʴʴʴ˜‘™‡Ž•
ɐƒ‡‹‘—ɐ

Python сам не добавляет пробелы при конкатенации строк, поэтому в более ран-
них примерах нам нужно было явно проставлять пробелы. Python добавляет пробел
между каждым аргументом выражения ’”‹–ſƀ и символом новой строки в конце:
ʴʴʴƒʰɐ— Ŝɐ
ʴʴʴ„ʰƒ
ʴʴʴ ʰɐ ”‡›— Šɐ
ʴʴʴƒʫ„ʫ
ɐ— Ŝ— Ŝ ”‡›— Šɐ
ʴʴʴ’”‹–ſƒř„ř ƀ
— Ŝ— Ŝ ”‡›— Š

ǸȈȏȔȕȖȎȈȍȔșȚȘȖȒȐșȗȖȔȖȡȤȦșȐȔȊȖȓȈ
Оператор * можно использовать для того, чтобы размножить строку. Попробуйте
ввести в интерактивный интерпретатор следующие строки и посмотрите, что полу-
чится:
ʴʴʴ•–ƒ”–ʰɐƒɐƋɫʫɐɎɐ
ʴʴʴ‹††Ž‡ʰɐ ‡›ɐƋɪʫɐɎɐ
ʴʴʴ‡†ʰɐ ‘‘†„›‡Ŝɐ
ʴʴʴ’”‹–ſ•–ƒ”–ʫ•–ƒ”–ʫ‹††Ž‡ʫ‡†ƀ

Обратите внимание на то, что оператор * имеет более высокий приоритет, чем ʫ,
поэтому строка будет размножена до того, как к ней добавится символ перехода на
новую строку.
ǫȓȈȊȈǺȍȒșȚȖȊȣȍșȚȘȖȒȐ  

ǰȏȊȓȍȒȈȍȔșȐȔȊȖȓșȗȖȔȖȡȤȦșȐȔȊȖȓȖȊ>@
Для получения одного символа из строки укажите его смещение в квадратных
скобках после имени строки. Смещение первого (крайнего слева) символа равно 0,
следующего — 1 и т. д. Чтобы не считать, смещение последнего (крайнего справа)
символа можно указать как –1. В таком случае смещение последующих символов
будет равно –2, –3 и т. д.:
ʴʴʴއ––‡”•ʰɐƒ„ †‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œɐ
ʴʴʴއ––‡”•ƃɥƄ
ɐƒɐ
ʴʴʴއ––‡”•ƃɨƄ
ɐ„ɐ
ʴʴʴއ––‡”•ƃŞɨƄ
ɐœɐ
ʴʴʴއ––‡”•ƃŞɩƄ
ɐ›ɐ
ʴʴʴއ––‡”•ƃɩɬƄ
ɐœɐ
ʴʴʴއ––‡”•ƃɬƄ
ɐˆɐ

Если вы укажете смещение, равное длине строки или больше (помните, смещения
идут от 0 к длине –1), сгенерируется исключение:
ʴʴʴއ––‡”•ƃɨɥɥƄ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
†‡š””‘”ś•–”‹‰‹†‡š‘—–‘ˆ”ƒ‰‡

Индексирование работает и для других типов последовательностей (списков


и кортежей), которые я рассмотрю в главе 7.
Поскольку строки неизменяемы, вы не можете вставить символ непосредственно
в строку или изменить символ по заданному индексу. Попробуем изменить слово
‡› на слово ‡› и посмотрим, что произойдет:
ʴʴʴƒ‡ʰɐ ‡›ɐ
ʴʴʴƒ‡ƃɥƄʰɐɐ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
›’‡””‘”śɐ•–”ɐ‘„Œ‡ –†‘‡•‘–•—’’‘”–‹–‡ƒ••‹‰‡–

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


всем скоро вы ее увидите), таких как ”‡’Žƒ ‡ſƀ или •Ž‹ ‡:
ʴʴʴƒ‡ʰɐ ‡›ɐ
ʴʴʴƒ‡Ŝ”‡’Žƒ ‡ſɐ ɐřɐɐƀ
ɐ‡›ɐ
ʴʴʴɐɐʫƒ‡ƃɨśƄ
ɐ‡›ɐ

Мы не изменили значение переменной ƒ‡. Интерактивный интерпретатор про-


сто вывел на экран результат замены.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǰȏȊȓȍȒȈȍȔȗȖȌșȚȘȖȒȐ
ȐșȗȖȓȤȏțȧȘȈȏȌȍȓȍȕȐȍ
Из строки можно извлечь подстроку (часть строки) с помощью разделения.
Вы задаете разделение с помощью квадратных скобок, смещения начала подстро-
ки ȡȔȫȔȟȢ и смещения конца подстроки ȞȢȡșȪ, а также опционального размера шага
между ними ȬȔȗ. Некоторые из этих параметров могут быть пропущены. В подстроку
будут включены символы, расположенные от точки, на которую указывает смещение
ȡȔȫȔȟȢ, до точки, на которую указывает смещение ȞȢȡșȪ.
‰Оператор ƃśƄ извлекает всю последовательность от начала до конца.
‰Оператор ƃȡȔȫȔȟȢ śƄ извлекает последовательность с точки, на которую указы-
вает смещение ȡȔȫȔȟȢ, до конца.
‰Оператор ƃś ȞȢȡșȪƄ извлекает последовательность от начала до точки, на которую
указывает смещение ȞȢȡșȪ минус 1.
‰Оператор ƃȡȔȫȔȟȢ ś ȞȢȡșȪƄ извлекает последовательность с точки, на которую
указывает смещение ȡȔȫȔȟȢ, до точки, на которую указывает смещение ȞȢȡșȪ
минус 1.
‰Оператор ƃȡȔȫȔȟȢ ś ȞȢȡșȪ ś ȬȔȗƄ извлекает последовательность с точки, на кото-
рую указывает смещение ȡȔȫȔȟȢ, до точки, на которую указывает смещение ȞȢȡșȪ
минус 1, опуская символы, чье смещение внутри подстроки кратно ȬȔȗ.
Как и ранее, смещение слева направо определяется как 0, 1 и т. д., а справа на-
лево — как –1, –2 и т. д. Если вы не укажете смещение ȡȔȫȔȟȢ, функция будет ис-
пользовать в качестве его значения ɥ (начало строки). Если не укажете смещение
ȞȢȡșȪ, его значением будет считаться конец строки.
Создадим строку, содержащую английские буквы в нижнем регистре:
ʴʴʴއ––‡”•ʰɐƒ„ †‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œɐ

Использование простого двоеточия аналогично использованию последователь-


ности ɥ: (целая строка):
ʴʴʴއ––‡”•ƃśƄ
ɐƒ„ †‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œɐ
Вот так можно получить все символы, начиная с 20-го и заканчивая послед-
ним:
ʴʴʴއ––‡”•ƃɩɥśƄ
ɐ—˜™š›œɐ
Так — начиная с 10-го и заканчивая последним:
ʴʴʴއ––‡”•ƃɨɥśƄ
ɐŽ‘’“”•–—˜™š›œɐ
А теперь получим символы с 12-го по 14-й. Python не включает в разделение
конечное смещение. Стартовое смещение включено, а конечное — не включено:
ʴʴʴއ––‡”•ƃɨɩśɨɬƄ
ɐ‘ɐ
ǫȓȈȊȈǺȍȒșȚȖȊȣȍșȚȘȖȒȐ  

Последние три символа:


ʴʴʴއ––‡”•ƃŞɪśƄ
ɐš›œɐ
В следующем примере мы начинаем со смещения 18 и идем до четвертого с конца
символа. Обратите внимание, как этот пример отличается от предыдущего, в котором
старт с позиции –3 приводил к букве х. В этом примере конец диапазона –3 означает,
что последней будет буква со смещением –4 — w:
ʴʴʴއ––‡”•ƃɨɯśŞɪƄ
ɐ•–—˜™ɐ
В этом примере мы получаем символы, начиная с шестого с конца и заканчивая
третьим с конца:
ʴʴʴއ––‡”•ƃŞɭśŞɩƄ
ɐ—˜™šɐ
Если вы хотите увеличить шаг, укажите его после второго двоеточия, как пока-
зано в нескольких следующих примерах.
Каждый седьмой символ с начала до конца:
ʴʴʴއ––‡”•ƃśśɮƄ
ɐƒŠ‘˜ɐ
Каждый третий символ, начиная со смещения 4 и заканчивая 19-м символом:
ʴʴʴއ––‡”•ƃɫśɩɥśɪƄ
ɐ‡Š“–ɐ
Каждый четвертый символ, начиная с 19-го:
ʴʴʴއ––‡”•ƃɨɰśśɫƄ
ɐ–šɐ
Каждый пятый символ от начала до 20-го:
ʴʴʴއ––‡”•ƃśɩɨśɬƄ
ɐƒˆ’—ɐ
(Опять же значение ȞȢȡșȪ должно быть на единицу больше, чем реальное смещение.)
И это еще не все! Если задать отрицательный шаг, удобный разделитель Python
дает возможность двигаться в обратную сторону. В следующем примере движение
начинается с конца и заканчивается в начале (ни один символ не пропущен):
ʴʴʴއ––‡”•ƃŞɨśśŞɨƄ
ɐœ›š™˜—–•”“’‘ŽŒ‹Š‰ˆ‡† „ƒɐ
Оказывается, тот же результат можно получить и другим способом:
ʴʴʴއ––‡”•ƃśśŞɨƄ
ɐœ›š™˜—–•”“’‘ŽŒ‹Š‰ˆ‡† „ƒɐ
Операция разделения более лояльно относится к некорректно указанным смеще-
ниям, чем поиск по индексу с помощью символов ƃƄ. Если указать смещение мень-
шее, чем начало строки, оно будет обрабатываться как 0, а если указать смещение
большее, чем конец строки, оно будет обработано как –1. Это показано в следующих
примерах.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Начиная с –50-го символа и до конца:


ʴʴʴއ––‡”•ƃŞɬɥśƄ
ɐƒ„ †‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œɐ
Начиная с –51-го символа и заканчивая –50-м:
ʴʴʴއ––‡”•ƃŞɬɨśŞɬɥƄ
ɐɐ
От начала до 69-го символа:
ʴʴʴއ––‡”•ƃśɮɥƄ
ɐƒ„ †‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œɐ
Начиная с 70-го символа и заканчивая 70-м:
ʴʴʴއ––‡”•ƃɮɥśɮɨƄ
ɐɐ

ǰȏȔȍȘȧȍȔȌȓȐȕțșȚȘȖȒȐșȗȖȔȖȡȤȦȜțȕȒȞȐȐOHQ
До этого момента мы использовали специальные знаки, такие как ʫ, для работы
со строками. Но их не так уж и много. Теперь начнем использовать некоторые из
встроенных функций Python: именованные фрагменты кода, которые выполняют
определенные операции.
Функция އſƀ подсчитывает количество символов в строке:
ʴʴʴއſއ––‡”•ƀ
ɩɭ
ʴʴʴ‡’–›ʰɑɑ
ʴʴʴއſ‡’–›ƀ
ɥ
Функцию އſƀ можно использовать и для других типов последовательностей,
о чем мы поговорим в главе 7.

ǸȈȏȌȍȓȧȍȔșȚȘȖȒțșȗȖȔȖȡȤȦȜțȕȒȞȐȐVSOLW
В отличие от އſƀ, некоторые функции применимы только к строкам. Для того чтобы
использовать строковую функцию, следует ввести имя строки, точку, имя функции
и аргументы, которые нужны функции: ȥȦȤȢȞȔŜȨȧȡȞȪȜȳſȔȤȗȧȠșȡȦȯƀ. Более подробно
об этом поговорим в главе 9.
Встроенная функция •’Ž‹–ſƀ позволяет разбить строку на список строк меньшего
размера с использованием разделителя. Со списками вы познакомитесь в следующей
главе. Список — это последовательность значений, разделенных запятыми и заклю-
ченных в квадратные скобки:
ʴʴʴ–ƒ••ʰɐ‰‡–‰Ž‘˜‡•ř‰‡–ƒ•ř‰‹˜‡ ƒ–˜‹–ƒ‹•ř ƒŽŽƒ„—Žƒ ‡ɐ
ʴʴʴ–ƒ••Ŝ•’Ž‹–ſɐřɐƀ
ƃɐ‰‡–‰Ž‘˜‡•ɐřɐ‰‡–ƒ•ɐřɐ‰‹˜‡ ƒ–˜‹–ƒ‹•ɐřɐ ƒŽŽƒ„—Žƒ ‡ɐƄ
В предыдущем примере строка имела имя –ƒ••, а строковая функция называлась
•’Ž‹–ſƀ и имела один аргумент-разделитель ɐřɐ. Если вы не укажете разделитель,
ǫȓȈȊȈǺȍȒșȚȖȊȣȍșȚȘȖȒȐ  

функция •’Ž‹–ſƀ будет использовать любую последовательность пробелов, а также


символы новой строки и табуляцию:
ʴʴʴ–ƒ••Ŝ•’Ž‹–ſƀ
ƃɐ‰‡–ɐřɐ‰Ž‘˜‡•ř‰‡–ɐřɐƒ•ř‰‹˜‡ɐřɐ ƒ–ɐřɐ˜‹–ƒ‹•ř ƒŽŽɐřɐƒ„—Žƒ ‡ɐƄ

При вызове функции split без аргументов круглые скобки все равно надо ста-
вить — именно так Python понимает, что вы вызываете функцию.

ǶȉȢȍȌȐȕȧȍȔșȚȘȖȒȐșȗȖȔȖȡȤȦȜțȕȒȞȐȐMRLQ
Легко догадаться, что функция Œ‘‹ſƀ является противоположностью функции
•’Ž‹–ſƀ : она объединяет список строк в одну строку. Вызов функции выглядит
немного запутанно, поскольку сначала вы указываете строку, которая объединяет
остальные, а затем — список строк для объединения: •–”‹‰ŜŒ‘‹ſŽ‹•–ƀ. Таким об-
разом, чтобы объединить строки списка lines, разделенные символами новой строки,
вам нужно написать ɐɎɐŜŒ‘‹ſŽ‹‡•ƀ. В следующем примере мы объединим в спи-
сок несколько имен, разделив их запятыми и пробелами:
ʴʴʴ ”›’–‘ɏŽ‹•–ʰƃɐ‡–‹ɐřɐ‹‰ˆ‘‘–ɐřɐ‘ Ї••‘•–‡”ɐƄ
ʴʴʴ ”›’–‘ɏ•–”‹‰ʰɐřɐŜŒ‘‹ſ ”›’–‘ɏŽ‹•–ƀ
ʴʴʴ’”‹–ſɐ ‘—†ƒ†•‹‰‹‰„‘‘†‡ƒŽ•śɐř ”›’–‘ɏ•–”‹‰ƀ
‘—†ƒ†•‹‰‹‰„‘‘†‡ƒŽ•ś‡–‹ř‹‰ˆ‘‘–ř‘ Ї••‘•–‡”

ǯȈȔȍȕȧȍȔșȐȔȊȖȓȣșȐșȗȖȓȤȏȖȊȈȕȐȍȔ
ȜțȕȒȞȐȐUHSODFH
Функция ”‡’Žƒ ‡ſƀ предназначена для замены одной подстроки другой. Вы ука-
зываете старую подстроку, новую подстроку и то, сколько экземпляров старой
подстроки нужно заменить. Если вы пропустите последний аргумент, функция за-
менит все экземпляры. В этом примере только одна строка (ɐ†— ɐ) сопоставляется
и заменяется:
ʴʴʴ•‡–—’ʰɑƒ†— ‰‘‡•‹–‘ƒ„ƒ”ŜŜŜɑ
ʴʴʴ•‡–—’Ŝ”‡’Žƒ ‡ſɐ†— ɐřɐƒ”‘•‡–ɐƀ
ɐƒƒ”‘•‡–‰‘‡•‹–‘ƒ„ƒ”ŜŜŜɐ
ʴʴʴ•‡–—’
ɐƒ†— ‰‘‡•‹–‘ƒ„ƒ”ŜŜŜɐ

Здесь заменим до 100 экземпляров:


ʴʴʴ•‡–—’Ŝ”‡’Žƒ ‡ſɐƒɐřɐƒˆƒ‘—•ɐřɨɥɥƀ
ɐƒˆƒ‘—•†— ‰‘‡•‹–‘ƒˆƒ‘—•„ƒ”ŜŜŜɐ

Если вы точно знаете, какую подстроку или подстроки хотите заменить, функ-
ция ”‡’Žƒ ‡ſƀ окажется для вас хорошим выбором. Но будьте осторожны: если бы
во втором примере вы заменили строку из одного символа ɐȔɐ, а не строку из двух
символов ɐȔ ɐ (после Ȕ идет пробел), символы ɐȔɐ заменились бы и в середине слов:
ʴʴʴ•‡–—’Ŝ”‡’Žƒ ‡ſɐƒɐřɐƒˆƒ‘—•ɐřɨɥɥƀ
ɐƒˆƒ‘—•†— ‰‘‡•‹–‘ƒˆƒ‘—•„ƒˆƒ‘—•”ŜŜŜɐ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Иногда вам нужно убедиться в том, что подстрока является целым словом, на-
чалом слова и т. п. В такой ситуации понадобятся регулярные выражения. Они под-
робно описаны в главе 12.

ǻșȚȘȈȕȧȍȔșȐȔȊȖȓȣ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐVWULS
Нередко требуется убрать из строки начальные или конечные символы отступа, чаще
всего пробелы. Представленная здесь функция •–”‹’ſƀ подразумевает, что вы хотите
избавиться от символов-пробелов (ɐ ɐ, ɐɎ–ɐ, ɐɎɐ), если только вы не предоставите
ей аргумент. Функция •–”‹’ſƀ удаляет символы с обоих концов строки, Ž•–”‹’ſƀ —
только в начале, а ”•–”‹’ſƀ — только в конце. Давайте представим, что строковая
переменная ™‘”ކ содержит строку earth, окруженную пробелами:
ʴʴʴ™‘”ކʰɑ‡ƒ”–Šɑ
ʴʴʴ™‘”ކŜ•–”‹’ſƀ
ɐ‡ƒ”–Šɐ
ʴʴʴ™‘”ކŜ•–”‹’ſɐɐƀ
ɐ‡ƒ”–Šɐ
ʴʴʴ™‘”ކŜŽ•–”‹’ſƀ
ɐ‡ƒ”–Šɐ
ʴʴʴ™‘”ކŜ”•–”‹’ſƀ
ɐ‡ƒ”–Šɐ

Если искомого символа в строке нет, ничего не происходит:


ʴʴʴ™‘”ކŜ•–”‹’ſɐŠɐƀ
ɐ‡ƒ”–Šɐ

Кроме отсутствия аргумента (когда подразумевается, что нужно найти пробелы)


или отдельного символа, возможна и ситуация, когда функция •–”‹’ſƀ удалит все
символы из последовательности:
ʴʴʴ„Ž—”–ʰɑŠƒ––ЇŜŜŜŠŠţɑ
ʴʴʴ„Ž—”–Ŝ•–”‹’ſɐŜţŠɐƀ
ɐŠƒ––Їɐ

В приложении Д представлены отдельные определения групп символов, которые


можно использовать для передачи в функцию •–”‹’ſƀ:
ʴʴʴ‹’‘”–•–”‹‰
ʴʴʴ•–”‹‰Ŝ™Š‹–‡•’ƒ ‡
ɐɎ–ɎɎ”Ɏšɥ„Ɏšɥ ɐ
ʴʴʴ•–”‹‰Ŝ’— –—ƒ–‹‘
ɐŠɑɤɛʩĺɎɐſƀƋʫřŞŜŵśŚʳʰʴţɒƃɎɎƄɋɏļƇŶƈɌɐ
ʴʴʴ„Ž—”–ʰɑŠƒ––ЇŜŜŜŠŠţɑ
ʴʴʴ„Ž—”–Ŝ•–”‹’ſ•–”‹‰Ŝ’— –—ƒ–‹‘ƀ
ɐŠƒ––Їɐ
ʴʴʴ’”‘•’‡ –‘”ʰɑŠƒ–‹–ƒ”ƒ–‹‘ŜŜŜţţŠŠɑ
ʴʴʴ’”‘•’‡ –‘”Ŝ•–”‹’ſ•–”‹‰Ŝ™Š‹–‡•’ƒ ‡ʫ•–”‹‰Ŝ’— –—ƒ–‹‘ƀ
ɐŠƒ–‹–ƒ”ƒ–‹‘ɐ
ǫȓȈȊȈǺȍȒșȚȖȊȣȍșȚȘȖȒȐ  

ǷȖȐșȒȐȊȣȉȖȘ
Python содержит большой набор функций для работы со строками. Рассмотрим
принцип работы самых распространенных из них. Тестовым объектом станет сле-
дующая строка, содержащая текст бессмертного стихотворения «What Is Liquid?»
Маргарет Кавендиш, герцогини Ньюкасл:
ʴʴʴ’‘‡ʰɐɐɐŽŽ–Šƒ–†‘–ŠˆŽ‘™™‡ ƒ‘–Ž‹“—‹†ƒ‡
”‡Ž•‡™‘—ކˆ‹”‡ƒ†™ƒ–‡”„‡–Ї•ƒ‡Ś
—––Šƒ–‹•Ž‹“—‹†™Š‹ Š‹•‘‹•–ƒ†™‡–
‹”‡–Šƒ–’”‘’‡”–› ƒ‡˜‡”‰‡–Ŝ
Їɐ–‹•‘– ‘ކ–Šƒ–†‘–Š–Їˆ‹”‡’—–‘—–
—–ɐ–‹•–Ї™‡––Šƒ–ƒ‡•‹–†‹‡ř‘†‘—„–Ŝɐɐɐ
Вдохновляет!
Для начала получим первые 13 символов (их смещения лежат в диапазоне
от 0 до 12):
ʴʴʴ’‘‡ƃśɨɪƄ
ɐŽŽ–Šƒ–†‘–Šɐ
Сколько символов содержит это стихотворение? (Пробелы и символы новой
строки учитываются.)
ʴʴʴއſ’‘‡ƀ
ɩɬɥ
Начинается ли стихотворение с All?
ʴʴʴ’‘‡Ŝ•–ƒ”–•™‹–ŠſɐŽŽɐƀ
”—‡
Заканчивается ли оно фразой That’s all, folks!?
ʴʴʴ’‘‡Ŝ‡†•™‹–ŠſɐŠƒ–Ɏɐ•ƒŽŽřˆ‘Ž•Šɐƀ
ƒŽ•‡
В Python есть два метода поиска смещения подстроки — ˆ‹†ſƀ и ‹†‡šſƀ. У каж-
дого метода имеется возможность начинать поиск или с начала, или с конца. В случае
если подстрока присутствует в строке, они работают одинаково. Если подстрока
не найдена, метод ˆ‹†ſƀ возвращает ʬɨ, а метод ‹†‡šſƀ генерирует исключение.
Найдем смещение первого появления в стихотворении слова the:
ʴʴʴ™‘”†ʰɐ–Їɐ
ʴʴʴ’‘‡Ŝˆ‹†ſ™‘”†ƀ
ɮɪ
ʴʴʴ’‘‡Ŝ‹†‡šſ™‘”†ƀ
ɮɪ

А теперь — последнего:
ʴʴʴ™‘”†ʰɐ–Їɐ
ʴʴʴ’‘‡Ŝ”ˆ‹†ſ™‘”†ƀ
ɩɨɫ
ʴʴʴ’‘‡Ŝ”‹†‡šſ™‘”†ƀ
ɩɨɫ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Но что, если подстроки нет?


ʴʴʴ™‘”†ʰɑ†— ɑ
ʴʴʴ’‘‡Ŝˆ‹†ſ™‘”†ƀ
Şɨ
ʴʴʴ’‘‡Ŝ”ˆ‹†ſ™‘”†ƀ
Şɨ
ʴʴʴ’‘‡Ŝ‹†‡šſ™‘”†ƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
ƒŽ—‡””‘”ś•—„•–”‹‰‘–ˆ‘—†
ʴʴʴ’‘‡Ŝ”ˆ‹†ſ™‘”†ƀ
Şɨ
ʴʴʴ’‘‡Ŝ”‹†‡šſ™‘”†ƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
ƒŽ—‡””‘”ś•—„•–”‹‰‘–ˆ‘—†

Сколько раз встречается трехбуквенное сочетание the?


ʴʴʴ™‘”†ʰɐ–Їɐ
ʴʴʴ’‘‡Ŝ ‘—–ſ™‘”†ƀ
ɪ

Являются ли все символы в стихотворении буквами или цифрами?


ʴʴʴ’‘‡Ŝ‹•ƒŽ—ſƀ
ƒŽ•‡

Нет, в стихотворении имеются еще и знаки препинания.

ǸȍȋȐșȚȘ
В этом разделе мы рассмотрим еще несколько примеров использования встроенных
функций. В качестве тестовой выберем следующую строку:
ʴʴʴ•‡–—’ʰɐƒ†— ‰‘‡•‹–‘ƒ„ƒ”ŜŜŜɐ

Удалим символ Ŝ с обоих концов строки:


ʴʴʴ•‡–—’Ŝ•–”‹’ſɐŜɐƀ
ɐƒ†— ‰‘‡•‹–‘ƒ„ƒ”ɐ

ǷȖșȒȖȓȤȒțșȚȘȖȒȐȕȍȐȏȔȍȕȧȍȔȣȕȐȊȖȌȕȖȔȐȏȥȚȐȝȗȘȐȔȍȘȖȊșȚȘȖȒȈVHWXSȕȈ
șȈȔȖȔȌȍȓȍȕȍȐȏȔȍȕȧȍȚșȧǷȘȖșȚȖȉȍȘȍȚșȧȏȕȈȟȍȕȐȍȗȍȘȍȔȍȕȕȖȑVHWXSȕȈȌȕȐȔ
ȊȣȗȖȓȕȧȍȚșȧȕȍȒȖȚȖȘȖȍȌȍȑșȚȊȐȍȈȏȈȚȍȔȘȍȏțȓȤȚȈȚȊȖȏȊȘȈȡȈȍȚșȧȊȊȐȌȍȕȖȊȖȑ
șȚȘȖȒȐ

Напишем первое слово с большой буквы:


ʴʴʴ•‡–—’Ŝ ƒ’‹–ƒŽ‹œ‡ſƀ
ɐ†— ‰‘‡•‹–‘ƒ„ƒ”ŜŜŜɐ
ǫȓȈȊȈǺȍȒșȚȖȊȣȍșȚȘȖȒȐ  

Напишем все слова с большой буквы:


ʴʴʴ•‡–—’Ŝ–‹–އſƀ
ɐ—  ‘‡• –‘ƒ”ŜŜŜɐ

Запишем все слова большими буквами:


ʴʴʴ•‡–—’Ŝ—’’‡”ſƀ
ɐ  ŜŜŜɐ

Запишем все слова строчными буквами:


ʴʴʴ•‡–—’ŜŽ‘™‡”ſƀ
ɐƒ†— ‰‘‡•‹–‘ƒ„ƒ”ŜŜŜɐ

Сменим регистры букв на противоположные:


ʴʴʴ•‡–—’Ŝ•™ƒ’ ƒ•‡ſƀ
ɐƒ  ŜŜŜɐ

ǪȣȘȈȊȕȐȊȈȕȐȍ
Теперь поработаем с функциями выравнивания. Строка выравнивается в пределах
указанного общего количества пробелов (в данном примере 30).
Отцентрируем строку в промежутке из 30 пробелов:
ʴʴʴ•‡–—’Ŝ ‡–‡”ſɪɥƀ
ɐƒ†— ‰‘‡•‹–‘ƒ„ƒ”ŜŜŜɐ

Выровняем ее по левому краю:


ʴʴʴ•‡–—’ŜŽŒ—•–ſɪɥƀ
ɐƒ†— ‰‘‡•‹–‘ƒ„ƒ”ŜŜŜɐ

А теперь по правому:
ʴʴʴ•‡–—’Ŝ”Œ—•–ſɪɥƀ
ɐƒ†— ‰‘‡•‹–‘ƒ„ƒ”ŜŜŜɐ

Далее рассмотрим другие способы выравнивания строки.

ǼȖȘȔȈȚȐȘȖȊȈȕȐȍ
Вы уже видели, как можно конкатенировать строки с помощью оператора ʫ .
А теперь узнаете, как интерполировать данные в строки, используя разные форматы.
Этим приемом можно пользоваться, чтобы создавать отчеты и другие документы,
для которых важен определенный внешний вид.
Помимо функций, рассмотренных в предыдущем разделе, Python имеет три
способа форматирования строк:
‰старый стиль (поддерживается в Python 2 и 3);
‰новый стиль (Python 2.6 и выше);
‰f-строки (Python 3.6 и выше).
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǹȚȈȘȣȑșȚȐȓȤ
Старый стиль форматирования строк имеет форму ȥȦȤȢȞȔ % ȘȔȡȡȯș. Внутри строки
находятся интерполяционные последовательности. В табл. 5.1 показано, что самая
простая последовательность — это символ ʩ и буква. Буква указывает на тип данных,
которые должны быть отформатированы.
ǺȈȉȓȐȞȈǺȐȗȣȗȘȍȖȉȘȈȏȖȊȈȕȐȧ

V ǹȚȘȖȒȈ
%d Целое число в десятичной системе счисления
%x Целое число в шестнадцатеричной системе счисления
%o Целое число в восьмеричной системе счисления
%f Число с плавающей точкой в десятичной системе счисления
%e Число с плавающей точкой в шестнадцатеричной системе счисления
%g Число с плавающей точкой в восьмеричной системе счисления
%% Символ %

Вы можете использовать последовательность ʩ• для любого типа данных —


Python отформатирует их как строку без дополнительных пробелов.
Рассмотрим несколько примеров. Сначала целое число:
ʴʴʴɐʩ•ɐʩɫɩ
ɐɫɩɐ
ʴʴʴɐʩ†ɐʩɫɩ
ɐɫɩɐ
ʴʴʴɐʩšɐʩɫɩ
ɐɩƒɐ
ʴʴʴɐʩ‘ɐʩɫɩ
ɐɬɩɐ

Число с плавающей точкой:


ʴʴʴɐʩ•ɐʩɮŜɥɪ
ɐɮŜɥɪɐ
ʴʴʴɐʩˆɐʩɮŜɥɪ
ɐɮŜɥɪɥɥɥɥɐ
ʴʴʴɐʩ‡ɐʩɮŜɥɪ
ɐɮŜɥɪɥɥɥɥ‡ʫɥɥɐ
ʴʴʴɐʩ‰ɐʩɮŜɥɪ
ɐɮŜɥɪɐ

Целое число и символ ʩ:


ʴʴʴɐʩ†ʩʩɐʩɨɥɥ
ɐɨɥɥʩɐ

Интерполяция некоторых строк и целых чисел:


ʴʴʴƒ –‘”ʰɐ‹ Šƒ”† ‡”‡ɐ
ʴʴʴ ƒ–ʰɐЇ•–‡”ɐ
ʴʴʴ™‡‹‰Š–ʰɩɯ
ǫȓȈȊȈǺȍȒșȚȖȊȣȍșȚȘȖȒȐ  

ʴʴʴɑ›™‹ˆ‡ɐ•ˆƒ˜‘”‹–‡ƒ –‘”‹•ʩ•ɑʩƒ –‘”


ɑ›™‹ˆ‡ɐ•ˆƒ˜‘”‹–‡ƒ –‘”‹•‹ Šƒ”† ‡”‡ɑ

ʴʴʴɑ—” ƒ–ʩ•™‡‹‰Š•ʩ•’‘—†•ɑʩſ ƒ–ř™‡‹‰Š–ƀ


ɐ—” ƒ–Ї•–‡”™‡‹‰Š•ɩɯ’‘—†•ɐ

Последовательность ʩ• внутри строки означает, что нужно интерполировать


строку. Количество использованных символов ʩ должно совпадать с количеством
объектов, расположенных после ʩ. Один элемент, такой как ƒ –‘”, располагается
сразу после символа ʩ. Если таких объектов несколько, они должны быть сгруппиро-
ваны в кортеж (читайте подробнее в главе 7), то есть их нужно заключить в скобки,
разделив запятыми. Например, ſ ƒ–ř ™‡‹‰Š–ƀ.
Несмотря на то что переменная weight целочисленная, последовательность ʩ•
внутри строки преобразует ее в строку.
Вы можете добавить другие значения между ʩ и определением типа, чтобы ука-
зать минимальную и максимальную ширину, а также выравнивание и заполнение
символами. Эти конструкции похожи на своего рода небольшой язык, достаточно
ограниченный по сравнению с тем, который будет представлен в следующих двух
подразделах. Какие это значения:
‰в начале располагается символ ɐʩɐ;
‰опциональный символ выравнивания: ничего или ɐʫɐ означают выравнивание по
правому краю, а ɐʬɐ — по левому;
‰опциональное поле ȠȜȡɕȬȜȤȜȡȔ, в котором указывается длина строки;
‰опциональный символ ɐŜɐ, разделяющий поля ȠȜȡɕȬȜȤȜȡȔ и ȠȔȞȥɕȥȜȠȖȢȟȯ;
‰опциональное поле ȠȔȞȥɕȥȜȠȖȢȟȯ (используется в том случае, если тип преобра-
зования s), в котором указывается, сколько символов значения нужно вывести
на экран. Если тип преобразования f, в этом поле указывается точность (сколько
символов выводится после десятичной точки);
‰символ, определяющий тип преобразования, из табл. 5.1.
Выглядит запутанно. Рассмотрим примеры для строки:
ʴʴʴ–Š‹‰ʰɐ™‘‘† Š— ɐ
ʴʴʴɐʩ•ɐʩ–Š‹‰
ɐ™‘‘† Š— ɐ
ʴʴʴɐʩɨɩ•ɐʩ–Š‹‰
ɐ™‘‘† Š— ɐ
ʴʴʴɐʩʫɨɩ•ɐʩ–Š‹‰
ɐ™‘‘† Š— ɐ
ʴʴʴɐʩŞɨɩ•ɐʩ–Š‹‰
ɐ™‘‘† Š— ɐ
ʴʴʴɐʩŜɪ•ɐʩ–Š‹‰
ɐ™‘‘ɐ
ʴʴʴɐʩɨɩŜɪ•ɐʩ–Š‹‰
ɐ™‘‘ɐ
ʴʴʴɐʩŞɨɩŜɪ•ɐʩ–Š‹‰
ɐ™‘‘ɐ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Теперь рассмотрим примеры для чисел с плавающей точкой (ʩˆ):


ʴʴʴ–Š‹‰ʰɰɯŜɭ
ʴʴʴɐʩˆɐʩ–Š‹‰
ɐɰɯŜɭɥɥɥɥɥɐ
ʴʴʴɐʩɨɩˆɐʩ–Š‹‰
ɐɰɯŜɭɥɥɥɥɥɐ
ʴʴʴɐʩʫɨɩˆɐʩ–Š‹‰
ɐʫɰɯŜɭɥɥɥɥɥɐ
ʴʴʴɐʩŞɨɩˆɐʩ–Š‹‰
ɐɰɯŜɭɥɥɥɥɥɐ
ʴʴʴɐʩŜɪˆɐʩ–Š‹‰
ɐɰɯŜɭɥɥɐ
ʴʴʴɐʩɨɩŜɪˆɐʩ–Š‹‰
ɐɰɯŜɭɥɥɐ
ʴʴʴɐʩŞɨɩŜɪˆɐʩ–Š‹‰
ɐɰɯŜɭɥɥɐ
А теперь — для целых чисел (ʩ†):
ʴʴʴ–Š‹‰ʰɰɯɮɭ
ʴʴʴɐʩ†ɐʩ–Š‹‰
ɐɰɯɮɭɐ
ʴʴʴɐʩɨɩ†ɐʩ–Š‹‰
ɐɰɯɮɭɐ
ʴʴʴɐʩʫɨɩ†ɐʩ–Š‹‰
ɐʫɰɯɮɭɐ
ʴʴʴɐʩŞɨɩ†ɐʩ–Š‹‰
ɐɰɯɮɭɐ
ʴʴʴɐʩŜɪ†ɐʩ–Š‹‰
ɐɰɯɮɭɐ
ʴʴʴɐʩɨɩŜɪ†ɐʩ–Š‹‰
ɐɰɯɮɭɐ
ʴʴʴɐʩŞɨɩŜɪ†ɐʩ–Š‹‰
ɐɰɯɮɭɐ
Для целых чисел конструкция ʩʫɨɩ† заставляет вывести знак числа, при этом
строки формата, содержащие конструкцию Ŝɪ, ни на что не влияют, поскольку пред-
назначены для чисел с плавающей точкой.

ǵȖȊȣȑșȚȐȓȤȐșȗȖȓȤȏțȍȔșȐȔȊȖȓȣ^`ȐȜțȕȒȞȐȦIRUPDW
Старый стиль форматирования все еще поддерживается, и в Python 2, который
остановился на версии 2.7, он будет поддерживаться всегда. В Python 3 применяется
новый стиль форматирования. Если у вас установлен Python 3.6 или выше, реко-
мендую воспользоваться f-строками (см. подраздел «Самый новый стиль: f-строки»
далее в этой главе).
Новый стиль форматирования имеет вид ȥȦȤȢȞȔŜˆ‘”ƒ–ſȘȔȡȡȯșƀ.
Строка формата выглядит немного иначе, чем в предыдущем подразделе. Про-
стейший пример использования этого стиля показан здесь:
ʴʴʴ–Š‹‰ʰɐ™‘‘† Š— ɐ
ʴʴʴɐƇƈɐŜˆ‘”ƒ–ſ–Š‹‰ƀ
ɐ™‘‘† Š— ɐ
ǫȓȈȊȈǺȍȒșȚȖȊȣȍșȚȘȖȒȐ  

Аргументы функции ˆ‘”ƒ–ſƀ должны идти в том порядке, в котором расставле-


ны заполнители Ƈƈ в строке формата:
ʴʴʴ–Š‹‰ʰɐ™‘‘† Š— ɐ
ʴʴʴ’Žƒ ‡ʰɐŽƒ‡ɐ
ʴʴʴɐЇƇƈ‹•‹–ЇƇƈŜɐŜˆ‘”ƒ–ſ–Š‹‰ř’ŽȞƒ ‡ƀ
ɐЇ™‘‘† Š— ‹•‹–ЇŽƒ‡Ŝɐ

В новом стиле форматирования вы также можете указать позицию аргументов


следующим образом:
ʴʴʴɐЇƇɨƈ‹•‹–ЇƇɥƈŜɐŜˆ‘”ƒ–ſ’Žƒ ‡ř–Š‹‰ƀ
ɐЇ™‘‘† Š— ‹•‹–ЇŽƒ‡Ŝɐ

Значение ɥ относится к первому аргументу ’Žƒ ‡, а ɨ — к thing.


Аргументы функции ˆ‘”ƒ–ſƀ могут быть именованными:
ʴʴʴɐЇƇ–Š‹‰ƈ‹•‹–ЇƇ’Žƒ ‡ƈɐŜˆ‘”ƒ–ſ–Š‹‰ʰɐ†— ɐř’Žƒ ‡ʰɐ„ƒ–Š–—„ɐƀ
ɐЇ†— ‹•‹–Ї„ƒ–Š–—„ɐ

Они также могут быть словарями:


ʴʴʴ†ʰƇɐ–Š‹‰ɐśɐ†— ɐřɐ’Žƒ ‡ɐśɐ„ƒ–Š–—„ɐƈ

В следующем примере Ƈɥƈ — это первый аргумент функции ˆ‘”ƒ–ſƀ (словарь †):
ʴʴʴɐЇƇɥƃ–Š‹‰Ƅƈ‹•‹–ЇƇɥƃ’Žƒ ‡ƄƈŜɐŜˆ‘”ƒ–ſ†ƀ
ɐЇ†— ‹•‹–Ї„ƒ–Š–—„Ŝɐ

В этих примерах аргументы выводились в формате, установленном по умолча-


нию. В новом стиле форматирования строка формата несколько отличается от той,
которая использовалась в старом стиле. Ее отличия:
‰начальное двоеточие (ɐśɐ);
‰опциональный символ-заполнитель (по умолчанию ɐ ɐ), которым заполняется
строка, если ее длина меньше, чем ȠȜȡɕȬȜȤȜȡȔ;
‰опциональный символ выравнивания. В этот раз вариантом по умолчанию является
выравнивание по левому краю. Символ ɐʳɐ означает выравнивание по левому краю,
символ ɐʴɐ — по правому, а символ ɐɋɐ означает выравнивание по центру;
‰опциональный знак для чисел. Отсутствие значения приведет к тому, что знак будет
отображаться только для отрицательных чисел. Символ ɐ ɐ означает, что для от-
рицательных чисел будет добавляться знак Ş, а для положительных — пробел (ɐ ɐ);
‰необязательное поле ȠȜȡɕȬȜȤȜȡȔ. Необязательный символ (ɐŜɐ) используется для
отделения значений полей ȠȜȡɕȬȜȤȜȡȔ и ȠȔȞȥɕȥȜȠȖȢȟȯ;
‰необязательное поле ȠȔȞȥɕȥȜȠȖȢȟȯ;
‰тип преобразования.
ʴʴʴ–Š‹‰ʰɐ™”ƒ‹–Šɐ
ʴʴʴ’Žƒ ‡ʰɐ™‹†‘™ɐ
ʴʴʴɐЇƇƈ‹•ƒ––ЇƇƈɐŜˆ‘”ƒ–ſ–Š‹‰ř’Žƒ ‡ƀ
ɐЇ™”ƒ‹–Š‹•ƒ––Ї™‹†‘™ɐ
ʴʴʴɐЇƇśɨɥ•ƈ‹•ƒ––ЇƇśɨɥ•ƈɐŜˆ‘”ƒ–ſ–Š‹‰ř’Žƒ ‡ƀ
ɐЇ™”ƒ‹–Š‹•ƒ––Ї™‹†‘™ɐ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ʴʴʴɐЇƇśʳɨɥ•ƈ‹•ƒ––ЇƇśʳɨɥ•ƈɐŜˆ‘”ƒ–ſ–Š‹‰ř’Žƒ ‡ƀ
ɐЇ™”ƒ‹–Š‹•ƒ––Ї™‹†‘™ɐ
ʴʴʴɐЇƇśɋɨɥ•ƈ‹•ƒ––ЇƇśɋɨɥ•ƈɐŜˆ‘”ƒ–ſ–Š‹‰ř’Žƒ ‡ƀ
ɐЇ™”ƒ‹–Š‹•ƒ––Ї™‹†‘™ɐ
ʴʴʴɐЇƇśʴɨɥ•ƈ‹•ƒ––ЇƇśʴɨɥ•ƈɐŜˆ‘”ƒ–ſ–Š‹‰ř’Žƒ ‡ƀ
ɐЇ™”ƒ‹–Š‹•ƒ––Ї™‹†‘™ɐ
ʴʴʴɐЇƇśŠɋɨɥ•ƈ‹•ƒ––ЇƇśŠɋɨɥ•ƈɐŜˆ‘”ƒ–ſ–Š‹‰ř’Žƒ ‡ƀ
ɐЇŠŠ™”ƒ‹–ŠŠŠ‹•ƒ––ЇŠŠ™‹†‘™ŠŠɐ

ǹȈȔȣȑȕȖȊȣȑșȚȐȓȤIșȚȘȖȒȐ
На данный момент для форматирования строк рекомендуется использовать f-строки,
которые появились в версии Python 3.6.
Чтобы создать f-строку, нужно сделать следующее:
‰ввести букву f или перед первой кавычкой;
‰поместить имена переменной или выражения в фигурные скобки (Ƈƈ), чтобы их
значения попали в строку.
Этот способ форматирования похож на новый стиль, но здесь не задействованы
функция ˆ‘”ƒ–ſƀ, пустые скобки (Ƈƈ) и позиционные аргументы (Ƈɨƈ) в строке
формата.
ʴʴʴ–Š‹‰ʰɐ™‡”‡†— ɐ
ʴʴʴ’Žƒ ‡ʰɐ™‡”‡’‘†ɐ
ʴʴʴˆɐЇƇ–Š‹‰ƈ‹•‹–ЇƇ’Žƒ ‡ƈɐ
ɐЇ™‡”‡†— ‹•‹–Ї™‡”‡’‘†ɐ

Как я уже говорил, в фигурных скобках можно размещать и выражения:


ʴʴʴˆɐЇƇ–Š‹‰Ŝ ƒ’‹–ƒŽ‹œ‡ſƀƈ‹•‹–ЇƇ’Žƒ ‡Ŝ”Œ—•–ſɩɥƀƈɐ
ɐЇ‡”‡†— ‹•‹–Ї™‡”‡’‘†ɐ

Таким образом, то, что вы могли делать внутри функции ˆ‘”ƒ–ſƀ из предыду-
щего раздела, можно сделать и здесь внутри фигурных скобок в главной строке.
Это упрощает чтение.
Для f-строк используется такой же язык форматирования (ширина, заполнитель,
выравнивание), как и в новом стиле. Выражения размещаются после двоеточия:
ʴʴʴˆɐЇƇ–Š‹‰śʴɩɥƈ‹•‹–ЇƇ’Žƒ ‡śŜɋɩɥƈɐ
ɐЇ™‡”‡†— ‹•‹–ЇŜŜŜŜŜŜ™‡”‡’‘†ŜŜŜŜŜŜɐ

Начиная с версии Python 3.8, f-строки позволяют выводить не только значения


переменных, но и их имена. Это очень удобно при отладке. Идея заключается в том,
чтобы поставить знак ʰ после имени переменной, размещенного в фигурных скобках:
ʴʴʴˆɐƇ–Š‹‰ʰƈřƇ’Žƒ ‡ʰƈɐ
–Š‹‰ʰɐ™‡”‡†— ɐř’Žƒ ‡ʰɐ™‡”‡’‘†ɐ

Этот прием также работает и для выражений. Каждое выражение будет выведено
полностью:
ʴʴʴˆɐƇ–Š‹‰ƃŞɫśƄʰƈřƇ’Žƒ ‡Ŝ–‹–އſƀʰƈɐ
–Š‹‰ƃŞɫśƄʰɐ†— ɐř’Žƒ ‡Ŝ–‹–އſƀʰɐ‡”‡’‘†ɐ
ǫȓȈȊȈǺȍȒșȚȖȊȣȍșȚȘȖȒȐ  

Наконец, после знака ʰ можно поставить двоеточие, за которым будут следовать


аргументы, такие как длины и выравнивания:
ʴʴʴˆɐƇ–Š‹‰ʰśʴɫŜɫƈɐ
–Š‹‰ʰɐ™‡”‡ɐ

ǿȚȖȍȡȍȔȖȎȕȖȌȍȓȈȚȤșȖșȚȘȖȒȈȔȐ
В Python имеется гораздо больше функций для работы со строками, нежели
я сейчас описал. Некоторые из них мы рассмотрим в следующих главах (особенно
в главе 12), но описания всех можно найти в стандартной документации (KWWSELWO\
S\GRFVVWULQJV).

ǿȐȚȈȑȚȍȌȈȓȍȍ
Следующая глава посвящена циклам в Python.

ǻȗȘȈȎȕȍȕȐȧ
5.1. Напишите с заглавной буквы слово, которое начинается с буквы m:
ʴʴʴ•‘‰ʰɑɑɑЇƒ‡‡Ž‰”ƒ„•›‘—”ƒ”ř
ŜŜŜ†‹– ƒ—•‡•‰”‡ƒ–Šƒ”ř
ŜŜŜŠƒ–ɐ•ރ‘”ƒ›Šɑɑɑ

5.2. Выведите на экран все вопросы из списка, а также правильные ответы в таком
виде:
Q: вопрос
A: ответ
ʴʴʴ“—‡•–‹‘•ʰƃ
ŜŜŜɑ‡†‘ɐ–•‡”˜‡•–”‹‰•ƒ”‘—†Ї”‡Ŝ”‡›‘—ƒ•–”‹‰ţɑř
ŜŜŜɑŠƒ–‹••ƒ‹†‘ ƒ–Ї”ɐ•ƒ›‹–Їˆ‘”‡•–ţɑř
ŜŜŜɑŠƒ–ƒ‡•–Ї•‘—†ɐ‹•Š‘‘ŠƒŠŠɐţɑ
ŜŜŜƄ
ʴʴʴƒ•™‡”•ʰƃ
ŜŜŜɑ‡š’Ž‘†‹‰•Ї‡’Ŝɑř
ŜŜŜɑ‘ř ɐƒˆ”ƒ›‡†‘–Ŝɑř
ŜŜŜɑɐ‘’Šɐ‰‘‡•–Ї™‡ƒ•‡ŽŜɑ
ŜŜŜƄ

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


тирования. Подставьте в него такие строки: ɐ”‘ƒ•– „‡‡ˆɐ, ɐŠƒɐ, ɐЇƒ†ɐ и ɐ Žƒɐ:
›‹––› ƒ–Ž‹‡•ʩ•ř
›‹––› ƒ–Ž‹‡•ʩ•ř
›‹––› ƒ–ˆ‡ŽŽ‘Š‹•ʩs
†‘™–Š‹•Їɐ•ƒʩ•Ŝ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

5.4. Напишите письмо с использованием нового стиля форматирования. Сохраните


предложенную строку в переменной letter (она понадобится вам в упражнении
ниже):
‡ƒ”Ƈ•ƒŽ—–ƒ–‹‘ƈƇƒ‡ƈř

Šƒ›‘—ˆ‘”›‘—”އ––‡”Ŝ‡ƒ”‡•‘””›–Šƒ–‘—”Ƈ’”‘†— –ƈ
Ƈ˜‡”„‡†ƈ‹›‘—”Ƈ”‘‘ƈŜއƒ•‡‘–‡–Šƒ–‹–•Š‘—ކ‡˜‡”
„‡—•‡†‹ƒƇ”‘‘ƈř‡•’‡ ‹ƒŽŽ›‡ƒ”ƒ›Ƈƒ‹ƒŽ•ƈŜ

‡†—•›‘—””‡ ‡‹’–ƒ†Ƈƒ‘—–ƈˆ‘”•Š‹’’‹‰ƒ†Šƒ†Ž‹‰Ŝ
‡™‹ŽŽ•‡†›‘—ƒ‘–Ї”Ƈ’”‘†— –ƈ–Šƒ–ř‹‘—”–‡•–•ř
‹•Ƈ’‡” ‡–ƈʩއ••Ž‹‡Ž›–‘Šƒ˜‡Ƈ˜‡”„‡†ƈŜ

Šƒ›‘—ˆ‘”›‘—”•—’’‘”–Ŝ
‹ ‡”‡Ž›ř
Ƈ•’‘‡•ƒƈ
ƇŒ‘„ɏ–‹–އƈ

5.5. Присвойте значения переменным ɐ•ƒŽ—–ƒ–‹‘ɐ, ɐƒ‡ɐ, ɐ’”‘†— –ɐ, ɐ˜‡”„‡†ɐ


(глагол в прошедшем времени), ɐ”‘‘ɐ , ɐƒ‹ƒŽ•ɐ , ɐ’‡” ‡–ɐ , ɐ•’‘‡•ƒɐ
и ɐŒ‘„ɏ–‹–އɐ. С помощью функции Ž‡––‡”Ŝˆ‘”ƒ–ſƀ выведите на экран значе-
ние переменной letter, в которую подставлены эти значения.
5.6. После проведения публичных опросов с целью выбора имени появились: ан-
глийская подводная лодка Boaty McBoatface, австралийская беговая лошадь
Horsey McHorseface и шведский поезд Trainy McTrainface. Используйте фор-
матирование с символом ʩ для того, чтобы вывести на экран победившие имена
для утки, тыквы и шпица.
5.7. Сделайте то же самое с помощью функции ˆ‘”ƒ–ſƀ.
5.8. А теперь еще раз с использованием f-строк.
ƋƓƈƊƈ
ǹȖȏȌȈȍȔȞȐȒȓȣșȗȖȔȖȡȤȦ
ȒȓȦȟȍȊȣȝșȓȖȊZKLOHȐIRU

При всем при том, при всем при том, пускай бедны мы
с вами…

Роберт Бёрнс. Честная бедность

Проверки с помощью if, elif и else выполняются последовательно, одна за другой.


Иногда определенные операции требуется выполнить более чем один раз. Для этого
нужен цикл, и Python предлагает два варианта: while и for.

ǷȖȊȚȖȘȧȍȔȌȍȑșȚȊȐȧșȗȖȔȖȡȤȦȞȐȒȓȈZKLOH
Самым простым циклическим механизмом в Python является while. Попробуйте
запустить с помощью интерактивного интерпретатора следующий пример — это
простейший цикл, который выводит на экран значения от ɨ до ɬ:
ʴʴʴ ‘—–ʰɨ
ʴʴʴ™Š‹Ž‡ ‘—–ʳʰɬś
ŜŜŜ’”‹–ſ ‘—–ƀ
ŜŜŜ ‘—–ʫʰɨ
ŜŜŜ
ɨ
ɩ
ɪ
ɫ
ɬ
ʴʴʴ

Сначала мы присваиваем значение ɨ переменной ‘—–. Цикл while сравнивает


значение переменной ‘—– с числом ɬ и продолжает работу, если значение пере-
менной ‘—– меньше или равно ɬ. Внутри цикла мы выводим значение переменной
‘—–, а затем увеличиваем его на 1 с помощью выражения ‘—– ʫʰ ɨ. Python возвра-
щается к началу цикла и снова сравнивает значение переменной ‘—– с числом ɬ.
Значение переменной ‘—– теперь равно ɩ, весь цикл while проходит очередной раз,
и затем переменная ‘—– увеличивается до ɪ.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Так продолжается до тех пор, пока переменная ‘—– не будет увеличена с ɬ до 6


в нижней части цикла. Во время очередного возвращения к началу цикла проверка
‘—– ʳʰ ɬ вернет значение ƒŽ•‡ и цикл while закончится. Python перейдет к вы-
полнению следующих строк.

ǷȘȍȘȣȊȈȍȔȞȐȒȓșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈEUHDN
Если вы хотите, чтобы цикл выполнялся до тех пор, пока что-то не произойдет,
однако вы не знаете точно, когда это событие случится, можно воспользоваться
бесконечным циклом, содержащим оператор „”‡ƒ. В этот раз мы прочитаем строку
с клавиатуры с помощью функции ‹’—–ſƀ, а затем выведем ее на экран, сделав
первую букву прописной. Цикл прервется, когда будет введена строка, содержащая
только букву q:
ʴʴʴ™Š‹Ž‡”—‡ś
ŜŜŜ•–—ˆˆʰ‹’—–ſɑ–”‹‰–‘ ƒ’‹–ƒŽ‹œ‡ƃ–›’‡“–‘“—‹–Ƅśɑƀ
ŜŜŜ‹ˆ•–—ˆˆʰʰɑ“ɑś
ŜŜŜ„”‡ƒ
ŜŜŜ’”‹–ſ•–—ˆˆŜ ƒ’‹–ƒŽ‹œ‡ſƀƀ
ŜŜŜ
–”‹‰–‘ ƒ’‹–ƒŽ‹œ‡ƃ–›’‡“–‘“—‹–Ƅś–‡•–
‡•–
–”‹‰–‘ ƒ’‹–ƒŽ‹œ‡ƃ–›’‡“–‘“—‹–ƄśЇ›ř‹–™‘”•
‡›ř‹–™‘”•
–”‹‰–‘ ƒ’‹–ƒŽ‹œ‡ƃ–›’‡“–‘“—‹–Ƅś“
ʴʴʴ

ǷȘȖȗțșȒȈȍȔȐȚȍȘȈȞȐȐȐșȗȖȓȤȏțȧȖȗȍȘȈȚȖȘFRQWLQXH
Иногда вам нужно не прерывать весь цикл, а пропустить по какой-либо причине
только одну итерацию. Рассмотрим пример: прочитаем целое число, и если оно
четное, выведем на экран его значение в квадрате, если же нечетное — пропустим
его. Мы даже добавим несколько комментариев. И вновь для выхода из цикла ис-
пользуем строку q:
ʴʴʴ™Š‹Ž‡”—‡ś
ŜŜŜ˜ƒŽ—‡ʰ‹’—–ſɑ –‡‰‡”ř’އƒ•‡ƃ“–‘“—‹–Ƅśɑƀ
ŜŜŜ‹ˆ˜ƒŽ—‡ʰʰɐ“ɐśɤȖȯȩȢȘ
ŜŜŜ„”‡ƒ
ŜŜŜ—„‡”ʰ‹–ſ˜ƒŽ—‡ƀ
ŜŜŜ‹ˆ—„‡”ʩɩʰʰɥśɤȡșȫșȦȡȢșȫȜȥȟȢ
ŜŜŜ ‘–‹—‡
ŜŜŜ’”‹–ſ—„‡”řɑ•“—ƒ”‡†‹•ɑř—„‡”Ƌ—„‡”ƀ
ŜŜŜ
–‡‰‡”ř’އƒ•‡ƃ“–‘“—‹–Ƅśɨ
ɨ•“—ƒ”‡†‹•ɨ
–‡‰‡”ř’އƒ•‡ƃ“–‘“—‹–Ƅśɩ
–‡‰‡”ř’އƒ•‡ƃ“–‘“—‹–Ƅśɪ
ɪ•“—ƒ”‡†‹•ɰ
ǫȓȈȊȈǹȖȏȌȈȍȔȞȐȒȓȣșȗȖȔȖȡȤȦȒȓȦȟȍȊȣȝșȓȖȊZKLOHȐIRU  

–‡‰‡”ř’އƒ•‡ƃ“–‘“—‹–Ƅśɫ
–‡‰‡”ř’އƒ•‡ƃ“–‘“—‹–Ƅśɬ
ɬ•“—ƒ”‡†‹•ɩɬ
–‡‰‡”ř’އƒ•‡ƃ“–‘“—‹–Ƅś“
ʴʴʴ

ǷȘȖȊȍȘȧȍȔȏȈȊȍȘȠȐȓșȧȓȐȞȐȒȓȘȈȕȤȠȍ
șȗȖȔȖȡȤȦȉȓȖȒȈHOVH
Если цикл while завершился нормально (без вызова „”‡ƒ), управление передается
в опциональный блок else. Вы пользуетесь этим, когда кодируете цикл так, чтобы,
выполняя некоторую проверку, он прервался, как только проверка успешно выпол-
нится. Блок else запустится в том случае, если цикл while пройдет полностью, но
искомый объект так и не будет найден:
ʴʴʴ—„‡”•ʰƃɨřɪřɬƄ
ʴʴʴ’‘•‹–‹‘ʰɥ
ʴʴʴ™Š‹Ž‡’‘•‹–‹‘ʳއſ—„‡”•ƀś
ŜŜŜ—„‡”ʰ—„‡”•ƃ’‘•‹–‹‘Ƅ
ŜŜŜ‹ˆ—„‡”ʩɩʰʰɥś
ŜŜŜ’”‹–ſɐ ‘—†‡˜‡—„‡”ɐř—„‡”ƀ
ŜŜŜ„”‡ƒ
ŜŜŜ’‘•‹–‹‘ʫʰɨ
ŜŜŜ‡Ž•‡śɤ„”‡ƒȡșȖȯțȯȖȔșȠ
ŜŜŜ’”‹–ſɐ‘‡˜‡—„‡”ˆ‘—†ɐƀ
ŜŜŜ
‘‡˜‡—„‡”ˆ‘—†

ǺȈȒȖȍȐșȗȖȓȤȏȖȊȈȕȐȍȒȓȦȟȍȊȖȋȖșȓȖȊȈHOVHȔȖȎȍȚȗȖȒȈȏȈȚȤșȧȕȍȓȖȋȐȟȕȣȔǪȖșȗȘȐ
ȕȐȔȈȑȚȍȍȋȖȒȈȒȗȘȖȊȍȘȒțȕȈȗȘȍȘȣȊȈȕȐȍȞȐȒȓȈ

ǪȣȗȖȓȕȧȍȔȐȚȍȘȈȞȐȐșȐșȗȖȓȤȏȖȊȈȕȐȍȔ
ȒȓȦȟȍȊȣȝșȓȖȊIRUȐLQ
В Python итераторы часто используются по одной простой причине. Они позволяют
вам проходить структуры данных без знания того, насколько эти структуры велики
и как реализованы. Вы даже можете обратиться к данным, которые были созданы
во время работы программы. Это позволяет обрабатывать потоки данных, которые
в противном случае не поместились бы в память компьютера.
Чтобы продемонстрировать итерирование, нам нужно что-то, по чему можно про-
итерировать. Вы уже познакомились со строками в главе 5, но пока не знаете всей
информации о других итерабельных объектах, таких как списки и кортежи (глава 7)
или словари (глава 8). Сейчас я покажу два способа итерирования по строке, а ите-
рирование по другим типам рассмотрим в соответствующих главах.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Вполне возможно пройти по строке таким образом:


ʴʴʴ™‘”†ʰɐ–Š—†ɐ
ʴʴʴ‘ˆˆ•‡–ʰɥ
ʴʴʴ™Š‹Ž‡‘ˆˆ•‡–ʳއſ™‘”†ƀś
ŜŜŜ’”‹–ſ™‘”†ƃ‘ˆˆ•‡–Ƅƀ
ŜŜŜ‘ˆˆ•‡–ʫʰɨ
ŜŜŜ
t
h
u
†

Однако существует более характерный для Python способ решения этой задачи:
ʴʴʴˆ‘”އ––‡”‹™‘”†ś
ŜŜŜ’”‹–ſއ––‡”ƀ
ŜŜŜ
t
h
u
†

Итерирование по строке возвращает один символ за раз.

ǷȘȍȘȣȊȈȍȔȞȐȒȓșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈEUHDN
Оператор „”‡ƒ прерывает цикл for точно так же, как и цикл while.
ʴʴʴ™‘”†ʰɐ–Š—†ɐ
ʴʴʴˆ‘”އ––‡”‹™‘”†ś
ŜŜŜ‹ˆއ––‡”ʰʰɐ—ɐś
ŜŜŜ„”‡ƒ
ŜŜŜ’”‹–ſއ––‡”ƀ
ŜŜŜ
t
h

ǷȘȖȗțșȒȈȍȔȐȚȍȘȈȞȐȐȐșȗȖȓȤȏțȧȖȗȍȘȈȚȖȘFRQWLQXH
Добавление ключевого слова ‘–‹—‡ в цикл for позволяет перейти на следующую
итерацию цикла, как и в случае с циклом while.

ǷȘȖȊȍȘȧȍȔȏȈȊȍȘȠȐȓșȧȓȐȞȐȒȓȘȈȕȤȠȍ
șȗȖȔȖȡȤȦȉȓȖȒȈHOVH
Как и в цикле while, в for имеется опциональный блок else, который проверяет,
выполнился ли цикл for полностью. Если ключевое слово „”‡ƒ не было вызвано,
будет выполнен блок else.
Это полезно в тех случаях, когда вам нужно убедиться в том, что предыдущий
цикл выполнился полностью, а не был прерван „”‡ƒ.
ǫȓȈȊȈǹȖȏȌȈȍȔȞȐȒȓȣșȗȖȔȖȡȤȦȒȓȦȟȍȊȣȝșȓȖȊZKLOHȐIRU  

ʴʴʴ™‘”†ʰɐ–Š—†ɐ
ʴʴʴˆ‘”އ––‡”‹™‘”†ś
ŜŜŜ‹ˆއ––‡”ʰʰɐšɐś
ŜŜŜ’”‹–ſɑ‡ŠɐšɐŠɑƀ
ŜŜŜ„”‡ƒ
ŜŜŜ’”‹–ſއ––‡”ƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ‘ɐšɐ‹–Ї”‡Ŝɑƀ
ŜŜŜ
t
h
u
†
‘ɐšɐ‹–Ї”‡

DzȈȒȐȊȞȐȒȓȍZKLOHȊȞȐȒȓȍIRUȐșȗȖȓȤȏȖȊȈȕȐȍȉȓȖȒȈHOVHȔȖȎȍȚȗȖȒȈȏȈȚȤșȧȕȍȓȖȋȐȟ
ȕȣȔǴȖȎȕȖȘȈșșȔȈȚȘȐȊȈȚȤȞȐȒȓIRUȒȈȒȗȖȐșȒȟȍȋȖȓȐȉȖȈȗȖȧȊȓȍȕȐȍHOVH²ȒȈȒșȐȋȕȈȓ
ȟȚȖȊȣȕȐȟȍȋȖȕȍȕȈȠȓȐǿȚȖȉȣȗȖȓțȟȐȚȤȚȖȚȎȍȥȜȜȍȒȚȉȍȏȉȓȖȒȈHOVHȐșȗȖȓȤȏțȑȚȍ
ȗȍȘȍȔȍȕȕțȦȒȖȚȖȘȈȧȉțȌȍȚȗȖȒȈȏȣȊȈȚȤȕȈȠȍȓșȧȓȐȐșȒȖȔȣȑȥȓȍȔȍȕȚȊȞȐȒȓȍIRU

ǫȍȕȍȘȐȘțȍȔȟȐșȓȖȊȣȍȗȖșȓȍȌȖȊȈȚȍȓȤȕȖșȚȐ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐUDQJH
Функция ”ƒ‰‡ſƀ выбирает поток чисел в заданном диапазоне без необходимости
создавать и сохранять крупную структуру данных, такую как список или кортеж.
Это позволяет создавать большие диапазоны, не используя всю память на вашем
компьютере и не сбивая программу.
Функцию ”ƒ‰‡ſƀ можно применять так же, как функцию •Ž‹ ‡ſƀ: range(ȡȔȫȔȟȢř
ȞȢȡșȪř ȬȔȗƀ. Если вы опустите значение ȡȔȫȔȟȢ, диапазон начнется с ɥ. Обязательным
является только значение ȞȢȡșȪ: как и в случае со •Ž‹ ‡ſƀ, последнее учтенное зна-
чение будет прямо перед ȞȢȡșȪ. Значение по умолчанию ȬȔȗ равно ɨ, но вы можете
изменить его на ŷɨ.
Как и œ‹’ſƀ, функция ”ƒ‰‡ſƀ возвращает итерабельный объект, поэтому вам
нужно пройти по значениям с помощью конструкции for ŜŜŜ in или преобразовать
объект в последовательность, такую как список. Создадим диапазон ɥ, ɨ, ɩ:
ʴʴʴˆ‘”š‹”ƒ‰‡ſɥřɪƀś
ŜŜŜ’”‹–ſšƀ
ŜŜŜ
ɥ
ɨ
ɩ
ʴʴʴŽ‹•–ſ”ƒ‰‡ſɥřɪƀƀ
ƃɥřɨřɩƄ

Вот так можно создать диапазон от ɩ до ɥ:


ʴʴʴˆ‘”š‹”ƒ‰‡ſɩřŞɨřŞɨƀś
ŜŜŜ’”‹–ſšƀ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ŜŜŜ
ɩ
ɨ
ɥ
ʴʴʴŽ‹•–ſ”ƒ‰‡ſɩřŞɨřŞɨƀƀ
ƃɩřɨřɥƄ

В следующем фрагменте кода шаг равен 2, что позволяет получить все четные
числа от 0 до 10:
ʴʴʴŽ‹•–ſ”ƒ‰‡ſɥřɨɨřɩƀƀ
ƃɥřɩřɫřɭřɯřɨɥƄ

ǷȘȖȟȐȍȐȚȍȘȈȚȖȘȣ
В главе 14 рассматривается итерирование по файлам. В главе 10 вы увидите, как
использовать итерирование для объектов, которые вы сами определили. В главе 11
мы рассмотрим itertools — стандартный модуль Python, содержащий множество
удобных функций.

ǿȐȚȈȑȚȍȌȈȓȍȍ
В следующей главе мы объединим индивидуальные объекты в списки и кортежи.

ǻȗȘȈȎȕȍȕȐȧ
6.1. Используйте цикл for, чтобы вывести на экран значения списка ƃɪř ɩř ɨř ɥƄ.
6.2. Присвойте значение 7 переменной ‰—‡••ɏ‡ и значение ɨ переменной —„‡”.
Напишите цикл while, который сравнивает переменные —„‡” и ‰—‡••ɏ‡.
Выведите строку ɐ–‘‘ Ž‘™ɐ, если значение переменной start меньше значе-
ния переменной ‰—‡••ɏ‡. Если значение переменной —„‡” равно значению
переменной ‰—‡••ɏ‡, выведите строку ɐˆ‘—† ‹–Šɐ и выйдите из цикла. Если
значение переменной —„‡” больше значения переменной ‰—‡••ɏ‡, выведите
строку ɐ‘‘’•ɐ и выйдите из цикла. Увеличьте значение переменной —„‡” на
выходе из цикла.
6.3. Присвойте значение ɬ переменной ‰—‡••ɏ‡. Используйте цикл for для того,
чтобы проитерировать с помощью переменной —„‡” по диапазону ”ƒ‰‡ſɨɥƀ.
Если значение переменной —„‡” меньше, чем значение ‰—‡••ɏ‡, выведите
на экран сообщение ɐ–‘‘ Ž‘™ɐ. Если оно равно значению ‰—‡••ɏ‡ — выведите
сообщение ɐˆ‘—† ‹–Šɐ, а затем выйдите из цикла. Если значение переменной
—„‡” больше, чем ‰—‡••ɏ‡, выведите на экран сообщение ɐ‘‘’•ɐ и выйдите
из цикла.
ƋƓƈƊƈ
DzȖȘȚȍȎȐȐșȗȐșȒȐ

Человек отличается от низших приматов страстью


к составлению списков.
Гарри Аллен Смит

В предыдущих главах мы говорили о базовых типах данных Python, таких как бу-
левы значения, целочисленные значения, числа с плавающей точкой и строки. Если
представлять их как атомы, то структуры данных, которые мы рассмотрим в этой
главе, можно назвать молекулами. Так и есть: мы объединим базовые типы в более
сложные структуры, которые вы будете использовать каждый день. Бо' льшая часть
работы программиста состоит из «разрезания» данных и «склеивания» их в конкрет-
ные формы, поэтому сейчас вы узнаете, как пользоваться ножовками и клеевыми
пистолетами.
Большинство языков программирования могут представлять последовательность
в виде объектов, проиндексированных по их позиции, выраженной целым числом:
первый, второй и далее до последнего. Вы уже знакомы со строками — последова-
тельностями символов.
В Python есть еще две структуры-последовательности: кортежи и списки. Они мо-
гут содержать ноль и более элементов. В отличие от строк в кортежах и списках
допускаются элементы разных типов: по факту каждый элемент может быть любым
объектом Python. Это позволяет создавать структуры любой сложности и глубины.
Почему же в Python имеются как списки, так и кортежи? Кортежи неизменяемы.
Когда вы включаете в кортеж элемент (всего один раз), он «запекается» и больше
не изменяется. Списки же можно изменять — добавлять и удалять элементы
в любой удобный момент. Я покажу вам множество примеров использования обоих
типов, сделав акцент на списках.

DzȖȘȚȍȎȐ
Давайте сразу же рассмотрим один очевидный вопрос. Вы могли слышать два
возможных варианта произношения слова tuple (кортеж). Какой же из них явля-
ется правильным? Гвидо ван Россум, создатель языка Python, написал в Twitter
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

(KWWSELWO\WXSOHWZHHW): «Я произношу слово tuple как too-pull по понедельникам, сре-


дам и пятницам и как tub-pull — по вторникам, четвергам и субботам. В воскресенье
я вообще об этом не говорю :)».

ǹȖȏȌȈȍȔȒȖȘȚȍȎȐșȗȖȔȖȡȤȦȏȈȗȧȚȣȝ
ȐȖȗȍȘȈȚȖȘȈ
Синтаксис создания кортежей несколько необычен, что вы и увидите в следующих
примерах.
Начнем с создания пустого кортежа с помощью оператора ſƀ:
ʴʴʴ‡’–›ɏ–—’އʰſƀ
ʴʴʴ‡’–›ɏ–—’އ
ſƀ

Чтобы создать кортеж, содержащий один элемент и более, после каждого элемен-
та надо ставить запятую. Это вариант для кортежей с одним элементом:
ʴʴʴ‘‡ɏƒ”šʰɐ ”‘— Š‘ɐř
ʴʴʴ‘‡ɏƒ”š
ſɐ ”‘— Š‘ɐřƀ

Вы можете поместить элемент в круглые скобки и получить такой же кортеж:


ʴʴʴ‘‡ɏƒ”šʰſɐ ”‘— Š‘ɐřƀ
ʴʴʴ‘‡ɏƒ”š
ſɐ ”‘— Š‘ɐřƀ

Однако следует иметь в виду: если в круглые скобки вы поместите один объект
и опустите при этом запятую, в результате вы получите не кортеж, а тот же самый
объект (в этом примере строку ɐ ”‘— Š‘ɐ):
ʴʴʴ‘‡ɏƒ”šʰſɐ ”‘— Š‘ɐƀ
ʴʴʴ‘‡ɏƒ”š
ɐ ”‘— Š‘ɐ
ʴʴʴ–›’‡ſ‘‡ɏƒ”šƀ
ʳ Žƒ••ɐ•–”ɐʴ

Если в вашем кортеже более одного элемента, ставьте запятую после каждого из
них, кроме последнего:
ʴʴʴƒ”šɏ–—’އʰɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐ
ʴʴʴƒ”šɏ–—’އ
ſɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƀ

При отображении кортежа Python выводит на экран скобки. Как правило, они
не нужны для определения кортежа, но с ними более безопасно, так как они делают
кортеж более заметным:
ʴʴʴƒ”šɏ–—’އʰſɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƀ
ʴʴʴƒ”šɏ–—’އ
ſɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƀ
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

В тех случаях, когда у запятой могут быть и другие варианты использования,


также рекомендуется ставить круглые скобки. В следующем примере вы можете
создать кортеж с одним элементом и присвоить ему значение, поставив в конце за-
пятую, но не можете передать эту конструкцию как аргумент функции:
ʴʴʴ‘‡ɏƒ”šʰɐ ”‘— Š‘ɐř
ʴʴʴ–›’‡ſ‘‡ɏƒ”šƀ
ʳ Žƒ••ɐ–—’އɐʴ
ʴʴʴ–›’‡ſɐ ”‘— Š‘ɐřƀ
ʳ Žƒ••ɐ•–”ɐʴ
ʴʴʴ–›’‡ſſɐ ”‘— Š‘ɐřƀƀ
ʳ Žƒ••ɐ–—’އɐʴ

Кортежи позволяют присваивать значение нескольким переменным одновре-


менно:
ʴʴʴƒ”šɏ–—’އʰſɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƀ
ʴʴʴƒř„ř ʰƒ”šɏ–—’އ
ʴʴʴƒ
ɐ ”‘— Š‘ɐ
ʴʴʴ„
ɐŠ‹ ‘ɐ
ʴʴʴ
ɐ ƒ”’‘ɐ

Иногда это называется распаковкой кортежа.


Вы можете использовать кортежи для обмена значениями с помощью одного
выражения, не применяя временную переменную:
ʴʴʴ’ƒ••™‘”†ʰɐ•™‘”†ˆ‹•Šɐ
ʴʴʴ‹ ‡ ”‡ƒʰɐ–—––‹ˆ”—––‹ɐ
ʴʴʴ’ƒ••™‘”†ř‹ ‡ ”‡ƒʰ‹ ‡ ”‡ƒř’ƒ••™‘”†
ʴʴʴ’ƒ••™‘”†
ɐ–—––‹ˆ”—––‹ɐ
ʴʴʴ‹ ‡ ”‡ƒ
ɐ•™‘”†ˆ‹•Šɐ
ʴʴʴ

ǹȖȏȌȈȍȔȒȖȘȚȍȎȐșȗȖȔȖȡȤȦȜțȕȒȞȐȐWXSOH
Функция преобразования –—’އſƀ создает кортежи из других объектов:
ʴʴʴƒ”šɏŽ‹•–ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴ–—’އſƒ”šɏŽ‹•–ƀ
ſɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƀ

ǶȉȢȍȌȐȕȧȍȔȒȖȘȚȍȎȐșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈ
Это похоже на объединение строк:
ʴʴʴſɐ ”‘— Š‘ɐřƀʫſɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƀ
ſɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƀ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǸȈȏȔȕȖȎȈȍȔȥȓȍȔȍȕȚȣșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈ 
Принцип похож на многократное использование оператора ʫ:
ʴʴʴſɐ›ƒ†ƒɐřƀƋɪ
ſɐ›ƒ†ƒɐřɐ›ƒ†ƒɐřɐ›ƒ†ƒɐƀ

ǹȘȈȊȕȐȊȈȍȔȒȖȘȚȍȎȐ
Сравнение кортежей похоже на сравнение списков:
ʴʴʴƒʰſɮřɩƀ
ʴʴʴ„ʰſɮřɩřɰƀ
ʴʴʴƒʰʰ„
ƒŽ•‡
ʴʴʴƒʳʰ„
”—‡
ʴʴʴƒʳ„
”—‡

ǰȚȍȘȐȘțȍȔȗȖȒȖȘȚȍȎȈȔșȗȖȔȖȡȤȦIRUȐLQ
Итерирование по кортежам выполняется так же, как и итерирование по другим
типам:
ʴʴʴ™‘”†•ʰſɐˆ”‡•Šɐřɐ‘—–ɐřɐ‘ˆɐřɐ‹†‡ƒ•ɐƀ
ʴʴʴˆ‘”™‘”†‹™‘”†•ś
ŜŜŜ’”‹–ſ™‘”†ƀ
ŜŜŜ
fresh
out
of
‹†‡ƒ•

ǰȏȔȍȕȧȍȔȒȖȘȚȍȎ
Этого сделать вы не можете! Как и строки, кортежи неизменяемы. Но ранее вы
уже видели на примере строк, что можно сконкатенировать (объединить) кортежи
и создать таким образом новый кортеж:
ʴʴʴ–ɨʰſɐ ‡‡ɐřɐ ‹‡ɐřɐ ‘‡ɐƀ
ʴʴʴ–ɩʰſɐ Ž‘’ɐřƀ
ʴʴʴ–ɨʫ–ɩ
ſɐ ‡‡ɐřɐ ‹‡ɐřɐ ‘‡ɐřɐ Ž‘’ɐƀ

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


ʴʴʴ–ɨʰſɐ ‡‡ɐřɐ ‹‡ɐřɐ ‘‡ɐƀ
ʴʴʴ–ɩʰſɐ Ž‘’ɐřƀ
ʴʴʴ–ɨʫʰ–ɩ
ʴʴʴ–ɨ
ſɐ ‡‡ɐřɐ ‹‡ɐřɐ ‘‡ɐřɐ Ž‘’ɐƀ
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

Это уже не тот же самый кортеж –ɨ. Python создал новый кортеж из исходных
–ɨ и –ɩ и присвоил ему имя –ɨ. С помощью ‹†ſƀ вы можете увидеть, когда имя пере-
менной будет указывать на новое значение:
ʴʴʴ–ɨʰſɐ ‡‡ɐřɐ ‹‡ɐřɐ ‘‡ɐƀ
ʴʴʴ–ɩʰſɐ Ž‘’ɐřƀ
ʴʴʴ‹†ſ–ɨƀ
ɫɪɭɬɫɥɬɮɨɩ
ʴʴʴ–ɨʫʰ–ɩ
ʴʴʴ‹†ſ–ɨƀ
ɫɪɭɫɮɮɥɮɫɫ

ǹȗȐșȒȐ
Списки особенно удобны для хранения в них объектов в определенном порядке,
особенно если порядок или содержимое нужно будет изменить. В отличие от строк
список изменяем: вы можете добавить новые элементы, перезаписать существу-
ющие и удалить ненужные. Одно и то же значение может встречаться в списке
несколько раз.

ǹȖȏȌȈȍȔșȗȐșȒȐșȗȖȔȖȡȤȦșȒȖȉȖȒ>@
Список можно создать из нуля и более элементов, разделенных запятыми и заклю-
ченных в квадратные скобки:
ʴʴʴ‡’–›ɏŽ‹•–ʰƃƄ
ʴʴʴ™‡‡†ƒ›•ʰƃɐ‘†ƒ›ɐřɐ—‡•†ƒ›ɐřɐ‡†‡•†ƒ›ɐřɐŠ—”•†ƒ›ɐřɐ ”‹†ƒ›ɐƄ
ʴʴʴ„‹‰ɏ„‹”†•ʰƃɐ‡—ɐřɐ‘•–”‹ Šɐřɐ ƒ••‘™ƒ”›ɐƄ
ʴʴʴˆ‹”•–ɏƒ‡•ʰƃɐ ”ƒŠƒɐřɐ ‘Аɐřɐ‡””›ɐřɐ‡””›ɐřɐ‹ Šƒ‡ŽɐƄ
ʴʴʴއƒ’ɏ›‡ƒ”•ʰƃɩɥɥɥřɩɥɥɫřɩɥɥɯƄ
ʴʴʴ”ƒ†‘‡••ʰƃɐ—š•ƒ–ƒ™‡›ɑřƇɑ‰”‘—†Š‘‰ɑśɑŠ‹Žɑƈřɑ ‡„Ŝɩɑƈ

Список ˆ‹”•–ɏƒ‡• показывает, что значения не должны быть уникальными.

ǭșȓȐȊȣȝȖȚȐȚȍȘȈȏȔȍȡȈȚȤȊȗȖșȓȍȌȖȊȈȚȍȓȤȕȖșȚȐȚȖȓȤȒȖțȕȐȒȈȓȤȕȣȍȏȕȈȟȍȕȐȧȐȊȈȔ
ȕȍȊȈȎȍȕȐȝȗȖȘȧȌȖȒȔȕȖȎȍșȚȊȖ VHW ȔȖȎȍȚȖȒȈȏȈȚȤșȧȉȖȓȍȍțȌȖȉȕȣȔȊȈȘȐȈȕȚȖȔ
ȟȍȔșȗȐșȖȒǪȗȘȍȌȣȌțȡȍȔȗȘȐȔȍȘȍșȗȐșȖȒELJBELUGVȊȗȖȓȕȍȔȖȋȉȣȚȤȔȕȖȎȍșȚȊȖȔ
ǶȔȕȖȎȍșȚȊȈȝȊȣȗȘȖȟȐȚȈȍȚȍȊȋȓȈȊȍ

ǹȖȏȌȈȍȔșȗȐșȖȒȐȓȐȗȘȍȖȉȘȈȏțȍȔȊșȗȐșȖȒșȗȖȔȖȡȤȦ
ȜțȕȒȞȐȐOLVW
Вы также можете создать пустой список с помощью функции Ž‹•–ſƀ:
ʴʴʴƒ‘–Ї”ɏ‡’–›ɏŽ‹•–ʰŽ‹•–ſƀ
ʴʴʴƒ‘–Ї”ɏ‡’–›ɏŽ‹•–
ƃƄ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Функция Ž‹•–ſƀ преобразует другие итерабельные типы данных (например,


кортежи, строки, множества и словари) в списки. В следующем примере строка
преобразуется в список, состоящий из односимвольных строк:
ʴʴʴŽ‹•–ſɐ ƒ–ɐƀ
ƃɐ ɐřɐƒɐřɐ–ɐƄ

В этом примере кортеж преобразуется в список:


ʴʴʴƒɏ–—’އʰſɐ”‡ƒ†›ɐřɐˆ‹”‡ɐřɐƒ‹ɐƀ
ʴʴʴŽ‹•–ſƒɏ–—’އƀ
ƃɐ”‡ƒ†›ɐřɐˆ‹”‡ɐřɐƒ‹ɐƄ

ǹȖȏȌȈȍȔșȗȐșȖȒȐȏșȚȘȖȒȐșȐșȗȖȓȤȏȖȊȈȕȐȍȔȜțȕȒȞȐȐVSOLW
Как я упоминал в разделе «Разделяем строку с помощью функции split()» главы 5,
функцию •’Ž‹–ſƀ можно использовать для преобразования строки в список, указав
некую строку-разделитель:
ʴʴʴ–ƒŽɏŽ‹‡ɏƒɏ’‹”ƒ–‡ɏ†ƒ›ʰɐɰŵɨɰŵɩɥɨɰɐ
ʴʴʴ–ƒŽɏŽ‹‡ɏƒɏ’‹”ƒ–‡ɏ†ƒ›Ŝ•’Ž‹–ſɐŵɐƀ
ƃɐɰɐřɐɨɰɐřɐɩɥɨɰɐƄ

Что, если в оригинальной строке содержится несколько включений строки-раз-


делителя подряд? В этом случае в качестве элемента списка вы получите пустую
строку:
ʴʴʴ•’Ž‹–‡ʰɐƒŵ„ŵŵ ŵ†ŵŵŵ‡ɐ
ʴʴʴ•’Ž‹–‡Ŝ•’Ž‹–ſɐŵɐƀ
ƃɐƒɐřɐ„ɐřɐɐřɐ ɐřɐ†ɐřɐɐřɐɐřɐ‡ɐƄ

Если бы вы использовали разделитель ŵŵ, состоящий из двух символов, то полу-


чили бы следующий результат:
ʴʴʴ•’Ž‹–‡ʰɐƒŵ„ŵŵ ŵ†ŵŵŵ‡ɐ
ʴʴʴ•’Ž‹–‡Ŝ•’Ž‹–ſɐŵŵɐƀ
ʴʴʴ
ƃɐƒŵ„ɐřɐ ŵ†ɐřɐŵ‡ɐƄ

ǷȖȓțȟȈȍȔȥȓȍȔȍȕȚșȗȖȔȖȡȤȦȒȖȕșȚȘțȒȞȐȐ>șȔȍȡȍȕȐȍ@
Как и в случае со строками, вы можете извлечь одно значение из списка, указав его
смещение:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•ƃɥƄ
ɐ ”‘— Š‘ɐ
ʴʴʴƒ”š‡•ƃɨƄ
ɐŠ‹ ‘ɐ
ʴʴʴƒ”š‡•ƃɩƄ
ɐ ƒ”’‘ɐ
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

Так же и отрицательные индексы отсчитываются с конца строки:


ʴʴʴƒ”š‡•ƃŞɨƄ
ɐ ƒ”’‘ɐ
ʴʴʴƒ”š‡•ƃŞɩƄ
ɐŠ‹ ‘ɐ
ʴʴʴƒ”š‡•ƃŞɪƄ
ɐ ”‘— Š‘ɐ
ʴʴʴ

ǹȔȍȡȍȕȐȍȌȖȓȎȕȖȉȣȚȤȌȖȗțșȚȐȔȣȔȌȓȧȥȚȖȋȖșȗȐșȒȈ²ȗȖȏȐȞȐȍȑȒȖȚȖȘȖȑȊȣȘȈȕȍȍ
ȗȘȐșȊȖȐȓȐȏȕȈȟȍȕȐȍǭșȓȐȊȣțȒȈȎȍȚȍȗȖȏȐȞȐȦȒȖȚȖȘȈȧȕȈȝȖȌȐȚșȧȗȍȘȍȌșȗȐșȒȖȔ
ȐȓȐȗȖșȓȍȕȍȋȖȉțȌȍȚșȋȍȕȍȘȐȘȖȊȈȕȖȐșȒȓȦȟȍȕȐȍ ȖȠȐȉȒȈ ǪȖȚȟȚȖșȓțȟȐȚșȧȍșȓȐ
ȔȣȗȖȗȘȖȉțȍȔȗȖȓțȟȐȚȤȠȍșȚȖȋȖȉȘȈȚȈǴȈȘȒș 0DU[HV  șȔȍȡȍȕȐȍȘȈȊȕȖȍșȓȐ
șȟȐȚȈȚȤȖȚȕțȓȧ ȐȓȐȎȍȗȧȚȖȋȖȗȍȘȍȌșȗȐșȒȖȔ
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•ƃɬƄ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
†‡š””‘”śŽ‹•–‹†‡š‘—–‘ˆ”ƒ‰‡
ʴʴʴƒ”š‡•ƃŞɬƄ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
†‡š””‘”śŽ‹•–‹†‡š‘—–‘ˆ”ƒ‰‡

ǰȏȊȓȍȒȈȍȔȥȓȍȔȍȕȚȣșȗȖȔȖȡȤȦȘȈȏȌȍȓȍȕȐȧ
Можно извлечь из списка подсписок, использовав разделение (slice):
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘řɐɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•ƃɥśɩƄ
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐƄ

Такой фрагмент списка тоже является списком.


Как и в случае со строками, при разделении можно пропускать некоторые значе-
ния. В следующем примере мы извлечем каждый нечетный элемент:
ʴʴʴƒ”š‡•ƃśśɩƄ
ƃɐ ”‘— Š‘ɐřɐ ƒ”’‘ɐƄ

Теперь начнем с последнего элемента и будем смещаться влево на 2:


ʴʴʴƒ”š‡•ƃśśŞɩƄ
ƃɐ ƒ”’‘ɐřɐ ”‘— Š‘ɐƄ

И наконец, рассмотрим прием инверсии списка:


ʴʴʴƒ”š‡•ƃśśŞɨƄ
ƃɐ ƒ”’‘ɐřɐŠ‹ ‘ɐřɐ ”‘— Š‘ɐƄ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Ни одно из этих разделений не затронуло сам список ƒ”š‡•, поскольку мы не вы-


полняли присваивание. Чтобы изменить порядок элементов в списке, используйте
функцию Ž‹•–Ŝ”‡˜‡”•‡ſƀ:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•Ŝ”‡˜‡”•‡ſƀ
ʴʴʴƒ”š‡•
ƃɐ ƒ”’‘ɐřɐŠ‹ ‘ɐřɐ ”‘— Š‘ɐƄ

ǼțȕȒȞȐȧUHYHUVH ȐȏȔȍȕȧȍȚșȗȐșȖȒȕȖȕȍȊȖȏȊȘȈȡȈȍȚȍȋȖȏȕȈȟȍȕȐȧ

Как и в случае со строками, если при разделении указать некорректный индекс,


исключение не сгенерируется. Будет использован ближайший корректный индекс
или же возвращено пустое значение:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•ƃɫśƄ
ƃƄ
ʴʴʴƒ”š‡•ƃŞɭśƄ
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•ƃŞɭśŞɩƄ
ƃɐ ”‘— Š‘ɐƄ
ʴʴʴƒ”š‡•ƃŞɭśŞɫƄ
ƃƄ

ǬȖȉȈȊȓȧȍȔȥȓȍȔȍȕȚȊȒȖȕȍȞșȗȐșȒȈ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐDSSHQG
Традиционный способ добавления элементов в список — вызов метода ƒ’’‡†ſƀ,
который один за одним добавит их в конец списка. В предыдущих примерах мы за-
были о Zeppo, но ничего страшного не случилось, поскольку список можно изменить.
Добавим его прямо сейчас:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•Ŝƒ’’‡†ſɐ‡’’‘ɐƀ
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ‡’’‘ɐƄ

ǬȖȉȈȊȓȧȍȔȥȓȍȔȍȕȚȕȈȖȗȘȍȌȍȓȍȕȕȖȍȔȍșȚȖ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐLQVHUW
Функция ƒ’’‡†ſƀ добавляет элементы только в конец списка. Когда вам нужно
добавить элемент и поставить его на заданную позицию, используйте функцию
‹•‡”–ſƀ. Если вы укажете смещение ɥ, элемент будет добавлен в начало списка.
Если значение смещения выходит за пределы списка, элемент будет добавлен в ко-
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

нец, как делает и функция ƒ’’‡†ſƀ: таким образом, вам не нужно беспокоиться
о том, что Python сгенерирует исключение:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•Ŝ‹•‡”–ſɩřɐ —‘ɐƀ
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ —‘ɐƄ
ʴʴʴƒ”š‡•Ŝ‹•‡”–ſɨɥřɐ‡’’‘ɐƀ
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ —‘ɐřɐ‡’’‘ɐƄ

ǸȈȏȔȕȖȎȈȍȔȥȓȍȔȍȕȚȣșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈ
В главе 5 вы видели, что можно размножить символы строки с помощью оператора *.
Точно так же можно сделать и со списками:
ʴʴʴƃɑ„ŽƒŠɑƄƋɪ
ƃɐ„ŽƒŠɐřɐ„ŽƒŠɐřɐ„ŽƒŠɐƄ

ǶȉȢȍȌȐȕȧȍȔșȗȐșȒȐșȗȖȔȖȡȤȦȔȍȚȖȌȈH[WHQG 
ȐȓȐȖȗȍȘȈȚȖȘȈ
Можно объединить один список с другим, используя ‡š–‡†ſƀ. Предположим, что
некий добрый человек дал нам новый список братьев Маркс, который называется
others, и мы хотим добавить его в основной список ƒ”š‡•:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ‡’’‘ɐƄ
ʴʴʴ‘–Ї”•ʰƃɐ —‘ɐřɐƒ”ŽɐƄ
ʴʴʴƒ”š‡•Ŝ‡š–‡†ſ‘–Ї”•ƀ
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ‡’’‘ɐřɐ —‘ɐřɐƒ”ŽɐƄ

Можно также использовать операторы ʫ или ʫʰ:


ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ‡’’‘ɐƄ
ʴʴʴ‘–Ї”•ʰƃɐ —‘ɐřɐƒ”ŽɐƄ
ʴʴʴƒ”š‡•ʫʰ‘–Ї”•
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ‡’’‘ɐřɐ —‘ɐřɐƒ”ŽɐƄ

Если бы мы использовали ƒ’’‡†ſƀ, список others был бы добавлен как один из


элементов списка, а не дополнил бы своими элементами список ƒ”š‡•:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ‡’’‘ɐƄ
ʴʴʴ‘–Ї”•ʰƃɐ —‘ɐřɐƒ”ŽɐƄ
ʴʴʴƒ”š‡•Ŝƒ’’‡†ſ‘–Ї”•ƀ
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ‡’’‘ɐřƃɐ —‘ɐřɐƒ”ŽɐƄƄ

Это еще раз показывает, что список может содержать элементы разных типов.
В этом случае — четыре строки и список из двух строк.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǰȏȔȍȕȧȍȔȥȓȍȔȍȕȚșȗȖȔȖȡȤȦȒȖȕșȚȘțȒȞȐȐ>șȔȍȡȍȕȐȍ@
Так же как значение какого-либо элемента из списка можно получить по смещению,
его можно и изменить:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•ƃɩƄʰɐƒ†ƒɐ
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐƒ†ƒɐƄ

Опять же смещение должно быть корректным для заданного списка.


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

ǰȏȔȍȕȧȍȔȥȓȍȔȍȕȚȣșȗȖȔȖȡȤȦȘȈȏȌȍȓȍȕȐȧ
В предыдущем разделе вы увидели, как получить подсписок с помощью разделе-
ния. Помимо этого, с помощью разделения можно присвоить значения под-
списку:
ʴʴʴ—„‡”•ʰƃɨřɩřɪřɫƄ
ʴʴʴ—„‡”•ƃɨśɪƄʰƃɯřɰƄ
ʴʴʴ—„‡”•
ƃɨřɯřɰřɫƄ

То, что находится справа от ʰ и что вы присваиваете списку, может содержать


иное количество элементов, нежели список, указанный слева:
ʴʴʴ—„‡”•ʰƃɨřɩřɪřɫƄ
ʴʴʴ—„‡”•ƃɨśɪƄʰƃɮřɯřɰƄ
ʴʴʴ—„‡”•
ƃɨřɮřɯřɰřɫƄ

ʴʴʴ—„‡”•ʰƃɨřɩřɪřɫƄ
ʴʴʴ—„‡”•ƃɨśɪƄʰƃƄ
ʴʴʴ—„‡”•
ƃɨřɫƄ

На самом деле то, что находится справа от оператора присваивания, может даже
не быть списком. Подойдет любой итерабельный объект, элементы которого можно
сделать элементами списка:
ʴʴʴ—„‡”•ʰƃɨřɩřɪřɫƄ
ʴʴʴ—„‡”•ƃɨśɪƄʰſɰɯřɰɰřɨɥɥƀ
ʴʴʴ—„‡”•
ƃɨřɰɯřɰɰřɨɥɥřɫƄ

ʴʴʴ—„‡”•ʰƃɨřɩřɪřɫƄ
ʴʴʴ—„‡”•ƃɨśɪƄʰɐ™ƒ–ţɐ
ʴʴʴ—„‡”•
ƃɨřɐ™ɐřɐƒɐřɐ–ɐřɐţɐřɫƄ
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

ǻȌȈȓȧȍȔȏȈȌȈȕȕȣȑȥȓȍȔȍȕȚșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈGHO
Только что наши консультанты проинформировали нас о том, что Гуммо (Gummo)
был одним из братьев Маркс, а Карл (Karl) — не был, и кто бы ни добавил его ранее,
он поступил очень неосмотрительно. Давайте это исправим:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ —‘ɐřɐƒ”ŽɐƄ
ʴʴʴƒ”š‡•ƃŞɨƄ
ɐƒ”Žɐ
ʴʴʴ†‡Žƒ”š‡•ƃŞɨƄ
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ —‘ɐƄ

Когда вы удаляете заданный с помощью смещения элемент, все идущие следом


за ним элементы сдвигаются, чтобы занять место удаленного, а длина списка умень-
шается на единицу. Если вы удалите Š‹ ‘ из последней версии списка ƒ”š‡•, то
получите такой результат:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ —‘ɐƄ
ʴʴʴ†‡Žƒ”š‡•ƃɨƄ
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐ ƒ”’‘ɐřɐ —‘ɐƄ

GHOȧȊȓȧȍȚșȧȖȗȍȘȈȚȖȘȖȔ3\WKRQȈȕȍȔȍȚȖȌȖȔșȗȐșȒȈ²ȕȍȓȤȏȧȕȈȗȐșȈȚȤPDU[HV>±@GHO 
ȅȚȖșȊȖȍȋȖȘȖȌȈȖȉȘȈȚȕȖȍȗȘȐșȊȈȐȊȈȕȐȍȚȈȒȒȈȒGHOȊȣȗȖȓȕȧȍȚȗȘȖȚȐȊȖȗȖȓȖȎȕțȦ
ȗȘȐșȊȈȐȊȈȕȐȦ ȖȗȍȘȈȞȐȦȖȚȒȘȍȗȓȧȍȚȐȔȧȖȚȖȉȢȍȒȚȈ3\WKRQȐȔȖȎȍȚȖșȊȖȉȖȌȐȚȤ
ȔȍșȚȖȖȉȢȍȒȚȈȊȗȈȔȧȚȐȍșȓȐȥȚȖȐȔȧȧȊȓȧȓȖșȤȗȖșȓȍȌȕȍȑșșȣȓȒȖȑȕȈȕȍȋȖ

ǻȌȈȓȧȍȔȥȓȍȔȍȕȚȗȖȏȕȈȟȍȕȐȦ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐUHPRYH
Если вы не знаете точно или вам все равно, в какой позиции находится элемент,
используйте функцию ”‡‘˜‡ſƀ, чтобы удалить его по значению. Прощай, Groucho:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•Ŝ”‡‘˜‡ſɐ ”‘— Š‘ɐƀ
ʴʴʴƒ”š‡•
ƃɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ

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


функция ”‡‘˜‡ſƀ удалит только первый найденный элемент.

ǷȖȓțȟȈȍȔȐțȌȈȓȧȍȔȏȈȌȈȕȕȣȑȥȓȍȔȍȕȚ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐSRS
Получить элемент из списка и так же удалить его можно с помощью функции
’‘’ſƀ. Если вызвать функцию ’‘’ſƀ и указать смещение, она возвратит элемент,
находящийся в заданной позиции. Если аргумент не указать, будет использовано
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

значение ŷɨ. Так, вызов ’‘’ſɥƀ вернет начальный элемент списка, а вызов ’‘’ſƀ или
’‘’ſʬɨƀ — конечный, как показано далее:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ‡’’‘ɐƄ
ʴʴʴƒ”š‡•Ŝ’‘’ſƀ
ɐ‡’’‘ɐ
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•Ŝ’‘’ſɨƀ
ɐŠ‹ ‘ɐ
ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐ ƒ”’‘ɐƄ

ǷȘȐȠȓȖ ȊȘȍȔȧ Ȍȓȧ ȒȖȔȗȤȦȚȍȘȕȖȋȖ ȎȈȘȋȖȕȈ ǵȍ ȊȖȓȕțȑȚȍșȤ ȥȚȖȋȖ ȕȍ ȉțȌȍȚ ȕȈ
ȐȚȖȋȖȊȖȔȥȒȏȈȔȍȕȍǭșȓȐȊȣȐșȗȖȓȤȏțȍȚȍȜțȕȒȞȐȦDSSHQG ȟȚȖȉȣȌȖȉȈȊȐȚȤȕȖ
ȊȣȍȥȓȍȔȍȕȚȣȊȒȖȕȍȞșȗȐșȒȈȐȜțȕȒȞȐȦSRS ȟȚȖȉȣțȌȈȓȐȚȤȟȚȖȓȐȉȖȐȏȒȖȕȞȈ
ȚȖȋȖȎȍșȗȐșȒȈȊȣȘȈȉȖȚȈȍȚȍșȖșȚȘțȒȚțȘȖȑȌȈȕȕȣȝȐȏȊȍșȚȕȖȑȒȈȒȖȟȍȘȍȌȤ/,)2
ODVWLQILUVWRXW²©ȗȖșȓȍȌȕȐȔȗȘȐȠȍȓȗȍȘȊȣȔțȠȍȓª ǭȍȟȈȡȍȕȈȏȣȊȈȦȚșȚȍȒȖȔ
ǪȣȏȖȊSRS  șȖȏȌȈȍȚȖȟȍȘȍȌȤ),)2 ILUVWLQILUVWRXW²©ȗȍȘȊȣȔȗȘȐȠȍȓȗȍȘȊȣȔ
țȠȍȓª ȅȚȖțȌȖȉȕȣȑșȗȖșȖȉșȖȉȐȘȈȚȤȌȈȕȕȣȍȗȖȔȍȘȍȐȝȗȖșȚțȗȓȍȕȐȧȐȘȈȉȖȚȈȚȤ
ȓȐȉȖșșȈȔȣȔȐșȚȈȘȣȔȐ ),)2 ȓȐȉȖșșȈȔȣȔȐȕȖȊȣȔȐ /,)2 

ǻȌȈȓȧȍȔȊșȍȥȓȍȔȍȕȚȣșȗȖȔȖȡȤȦȜțȕȒȞȐȐFOHDU
В Python 3.3 появился метод, позволяющий удалить все элементы из списка:
ʴʴʴ™‘”ɏ“—‘–‡•ʰƃɐ‘”‹‰Šƒ”†ţɐřɐ—‹ “—‡•–‹‘Šɐřɐ—„‡”‘‡’”‹‘”‹–‹‡•ŠɐƄ
ʴʴʴ™‘”ɏ“—‘–‡•
ƃɐ‘”‹‰Šƒ”†ţɐřɐ—‹ “—‡•–‹‘Šɐřɐ—„‡”‘‡’”‹‘”‹–‹‡•ŠɐƄ
ʴʴʴ™‘”ɏ“—‘–‡•Ŝ އƒ”ſƀ
ʴʴʴ™‘”ɏ“—‘–‡•
ƃƄ

ǶȗȘȍȌȍȓȧȍȔșȔȍȡȍȕȐȍȗȖȏȕȈȟȍȕȐȦ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐLQGH[
Если вы хотите узнать смещение элемента в списке по его значению, используйте
функцию ‹†‡šſƀ:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ‡’’‘ɐƄ
ʴʴʴƒ”š‡•Ŝ‹†‡šſɐŠ‹ ‘ɐƀ
ɨ

Если значение встречается в списке более одного раза, возвращается смещение


только первого найденного элемента:
ʴʴʴ•‹’•‘•ʰƃɐ‹•ƒɐřɐƒ”–ɐřɐƒ”‰‡ɐřɐ ‘‡”ɐřɐƒ”–ɐƄ
ʴʴʴ•‹’•‘•Ŝ‹†‡šſɐƒ”–ɐƀ
ɨ
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

ǷȘȖȊȍȘȧȍȔȕȈȕȈȓȐȟȐȍȥȓȍȔȍȕȚȈȊșȗȐșȒȍ
șȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈLQ
В Python наличие элемента в списке проверяется с помощью оператора in:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐřɐ‡’’‘ɐƄ
ʴʴʴɐ ”‘— Š‘ɐ‹ƒ”š‡•
”—‡
ʴʴʴɐ‘„ɐ‹ƒ”š‡•
ƒŽ•‡

Одно и то же значение может находиться в списке на нескольких позициях.


Пока оно присутствует хотя бы в единственном экземпляре, оператор in будет воз-
вращать значение ”—‡:
ʴʴʴ™‘”†•ʰƃɐƒɐřɐ†‡‡”ɐřɐƒɐɐˆ‡ƒŽ‡ɐřɐ†‡‡”ɐƄ
ʴʴʴɐ†‡‡”ɐ‹™‘”†•
”—‡

ǭșȓȐ Ȋȣ ȟȈșȚȖ ȗȘȖȊȍȘȧȍȚȍ ȕȈȓȐȟȐȍ ȥȓȍȔȍȕȚȈ Ȋ șȗȐșȒȍ Ȑ ȊȈȔ ȕȍȊȈȎȍȕ ȗȖȘȧȌȖȒ
ȥȓȍȔȍȕȚȖȊ ȚȖ Ȍȓȧ ȝȘȈȕȍȕȐȧ Ȑ ȗȖȐșȒȈ țȕȐȒȈȓȤȕȣȝ ȏȕȈȟȍȕȐȑ ȉȖȓȤȠȍ ȗȖȌȖȑȌȍȚ
ȔȕȖȎȍșȚȊȖǶȔȕȖȎȍșȚȊȈȝȔȣȗȖȋȖȊȖȘȐȔȟțȚȤȗȖȏȎȍȊȋȓȈȊȍ

ǷȖȌșȟȐȚȣȊȈȍȔȒȖȓȐȟȍșȚȊȖȊȒȓȦȟȍȕȐȑȏȕȈȟȍȕȐȧ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐFRXQW
Чтобы подсчитать, сколько раз какое-либо значение встречается в списке, исполь-
зуйте функцию ‘—–ſƀ:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”š‡•Ŝ ‘—–ſɐ ƒ”’‘ɐƀ
ɨ
ʴʴʴƒ”š‡•Ŝ ‘—–ſɐ‘„ɐƀ
ɥ

ʴʴʴ•Žɏ•‹–ʰƃɐ Ї‡•‡„—”‰‡”ɐřɐ Ї‡•‡„—”‰‡”ɐřɐ Ї‡•‡„—”‰‡”ɐƄ


ʴʴʴ•Žɏ•‹–Ŝ ‘—–ſɐ Ї‡•‡„—”‰‡”ɐƀ
ɪ

ǷȘȍȖȉȘȈȏțȍȔșȗȐșȖȒȊșȚȘȖȒțșȗȖȔȖȡȤȦȜțȕȒȞȐȐMRLQ
В разделе «Объединяем строки с помощью функции join()» главы 5 функция Œ‘‹ſƀ
рассматривается более подробно, но вот еще один пример того, что можно сделать
с ее помощью:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴɐřɐŜŒ‘‹ſƒ”š‡•ƀ
ɐ ”‘— Š‘řŠ‹ ‘ř ƒ”’‘ɐ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

На первый взгляд это выглядит неправильным. Ведь функция Œ‘‹ſƀ предназнача-


ется для строк, а не для списков. Вы не можете написать ƒ”š‡•ŜŒ‘‹ſɐř ɐƀ, даже если
интуиция вам так подсказывает. Аргументом для функции Œ‘‹ſƀ является строка
или любая итерабельная последовательность строк (в том числе и список), а вы-
водом — строка. Если бы функция Œ‘‹ſƀ была только методом списка, ее нельзя
было бы использовать для других итерабельных объектов, таких как кортежи
и строки. Если вы хотите, чтобы она работала с любым итерабельным типом, нуж-
но написать особый код для каждого типа и таким образом обработать подобное
объединение. Это поможет вам запомнить: Œ‘‹ſƀ противоположна •’Ž‹–ſƀ, как
показано здесь:
ʴʴʴˆ”‹‡†•ʰƃɐ ƒ””›ɐřɐ ‡”‹‘‡ɐřɐ‘ɐƄ
ʴʴʴ•‡’ƒ”ƒ–‘”ʰɐƋɐ
ʴʴʴŒ‘‹‡†ʰ•‡’ƒ”ƒ–‘”ŜŒ‘‹ſˆ”‹‡†•ƀ
ʴʴʴŒ‘‹‡†
ɐ ƒ””›Ƌ ‡”‹‘‡Ƌ‘ɐ
ʴʴʴ•‡’ƒ”ƒ–‡†ʰŒ‘‹‡†Ŝ•’Ž‹–ſ•‡’ƒ”ƒ–‘”ƀ
ʴʴʴ•‡’ƒ”ƒ–‡†
ƃɐ ƒ””›ɐřɐ ‡”‹‘‡ɐřɐ‘ɐƄ
ʴʴʴ•‡’ƒ”ƒ–‡†ʰʰˆ”‹‡†•
”—‡

ǴȍȕȧȍȔȗȖȘȧȌȖȒȥȓȍȔȍȕȚȖȊșȗȖȔȖȡȤȦȜțȕȒȞȐȑVRUW 
ȐȓȐVRUWHG
Часто вам будет нужно сортировать элементы в списке по значению, а не по смеще-
нию. Для этого Python предоставляет две функции:
‰функцию списка •‘”–ſƀ, которая сортирует сам список;
‰общую функцию •‘”–‡†ſƀ, которая возвращает отсортированную копию списка.
Если элементы списка являются числами, они по умолчанию сортируются по
возрастанию. Если строками — сортируются в алфавитном порядке:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴ•‘”–‡†ɏƒ”š‡•ʰ•‘”–‡†ſƒ”š‡•ƀ
ʴʴʴ•‘”–‡†ɏƒ”š‡•
ƃɐŠ‹ ‘ɐřɐ ”‘— Š‘ɐřɐ ƒ”’‘ɐƄ

•‘”–‡†ɏƒ”š‡• — это копия, ее создание не изменило оригинальный список:


ʴʴʴƒ”š‡•
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ

Но вызов функции списка •‘”–ſƀ для ƒ”š‡• список изменит:


ʴʴʴƒ”š‡•Ŝ•‘”–ſƀ
ʴʴʴƒ”š‡•
ƃɐŠ‹ ‘ɐřɐ ”‘— Š‘ɐřɐ ƒ”’‘ɐƄ

Если все элементы списка одного типа (в списке ƒ”š‡• находятся только стро-
ки), функция •‘”–ſƀ отработает корректно. Иногда можно даже смешать типы, на-
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

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


они автоматически преобразуются друг в друга:
ʴʴʴ—„‡”•ʰƃɩřɨřɫŜɥřɪƄ
ʴʴʴ—„‡”•Ŝ•‘”–ſƀ
ʴʴʴ—„‡”•
ƃɨřɩřɪřɫŜɥƄ

По умолчанию список сортируется по возрастанию, но можно добавить аргумент


”‡˜‡”•‡ʰ”—‡, чтобы отсортировать список по убыванию:
ʴʴʴ—„‡”•ʰƃɩřɨřɫŜɥřɪƄ
ʴʴʴ—„‡”•Ŝ•‘”–ſ”‡˜‡”•‡ʰ”—‡ƀ
ʴʴʴ—„‡”•
ƃɫŜɥřɪřɩřɨƄ

ǷȖȓțȟȈȍȔȌȓȐȕțșȗȐșȒȈșȗȖȔȖȡȤȦȜțȕȒȞȐȐOHQ
Функция އſƀ возвращает количество элементов списка:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴއſƒ”š‡•ƀ
ɪ

ǷȘȐșȊȈȐȊȈȍȔșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈ
Когда вы присваиваете один список более чем одной переменной, изменение списка
в одном месте также меняет его и в других, как показано далее:
ʴʴʴƒʰƃɨřɩřɪƄ
ʴʴʴƒ
ƃɨřɩřɪƄ
ʴʴʴ„ʰƒ
ʴʴʴ„
ƃɨřɩřɪƄ
ʴʴʴƒƃɥƄʰɐ•—”’”‹•‡ɐ
ʴʴʴƒ
ƃɐ•—”’”‹•‡ɐřɩřɪƄ

Что же собой представляет переменная b? Ее значение все еще равно ƃɨř ɩř ɪƄ


или изменилось на ƃɐ•—”’”‹•‡ɐř ɩř ɪƄ? Проверим:
ʴʴʴ„
ƃɐ•—”’”‹•‡ɐřɩřɪƄ

Помните аналогию с коробкой (объектом) и этикеткой (именем переменной)


из главы 2? b просто ссылается на тот же список объектов, что и Ȕ (обе этикетки
указывают на одну и ту же коробку с объектом), поэтому, независимо от того, с по-
мощью какого имени мы изменяем содержимое списка, изменение отражается на
обеих переменных:
ʴʴʴ„
ƃɐ•—”’”‹•‡ɐřɩřɪƄ
ʴʴʴ„ƃɥƄʰɐ Šƒ–‡•—”’”‹•‡•ɐ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ʴʴʴ„
ƃɐ Šƒ–‡•—”’”‹•‡•ɐřɩřɪƄ
ʴʴʴƒ
ƃɐ Šƒ–‡•—”’”‹•‡•ɐřɩřɪƄ

DzȖȗȐȘțȍȔșȗȐșȒȐșȗȖȔȖȡȤȦȜțȕȒȞȐȑFRS\ ȐOLVW 
ȐȓȐȗțȚȍȔȘȈȏȌȍȓȍȕȐȧ
Вы можете скопировать значения в отдельный новый список с помощью любого из
этих методов:
‰функции ‘’›ſƀ;
‰функции преобразования Ž‹•–ſƀ;
‰разделения списка ƃśƄ.
Оригинальный список снова будет присвоен переменной Ȕ. Мы создадим b с по-
мощью функции списка ‘’›ſƀ, — с помощью функции преобразования Ž‹•–ſƀ,
а † — с помощью разделения списка:
ʴʴʴƒʰƃɨřɩřɪƄ
ʴʴʴ„ʰƒŜ ‘’›ſƀ
ʴʴʴ ʰŽ‹•–ſƒƀ
ʴʴʴ†ʰƒƃśƄ

Опять же b, и † являются копиями a — новыми объектами со своими собствен-


ными значениями и не связанными с исходным списком объектов ƃɨř ɩř ɪƄ , на
который ссылается a. Изменение a не влияет на копии b, и †:
ʴʴʴƒƃɥƄʰɐ‹–‡‰‡”Ž‹•–•ƒ”‡„‘”‹‰ɐ
ʴʴʴƒ
ƃɐ‹–‡‰‡”Ž‹•–•ƒ”‡„‘”‹‰ɐřɩřɪƄ
ʴʴʴ„
ƃɨřɩřɪƄ
ʴʴʴ
ƃɨřɩřɪƄ
ʴʴʴ†
ƃɨřɩřɪƄ

DzȖȗȐȘțȍȔȊșȍșȗȖȔȖȡȤȦȜțȕȒȞȐȐGHHSFRS\
Функция ‘’›ſƀ хорошо работает, если все элементы списка являются неизменя-
емыми. Как вы видели ранее, изменяемые значения (например, списки, кортежи
или словари) являются ссылками. Изменение оригинала или копии отразится на
каждом из них.
Воспользуемся предыдущим примером, но в качестве последнего элемента спи-
ска a вместо целого числа ɪ используем список ƃɯř ɰƄ:
ʴʴʴƒʰƃɨřɩřƃɯřɰƄƄ
ʴʴʴ„ʰƒŜ ‘’›ſƀ
ʴʴʴ ʰŽ‹•–ſƒƀ
ʴʴʴ†ʰƒƃśƄ
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

ʴʴʴƒ
ƃɨřɩřƃɯřɰƄƄ
ʴʴʴ„
ƃɨřɩřƃɯřɰƄƄ
ʴʴʴ
ƃɨřɩřƃɯřɰƄƄ
ʴʴʴ†
ƃɨřɩřƃɯřɰƄƄ

Пока все хорошо. Теперь изменим элемент нашего подсписка из списка Ȕ:


ʴʴʴƒƃɩƄƃɨƄʰɨɥ
ʴʴʴƒ
ƃɨřɩřƃɯřɨɥƄƄ
ʴʴʴ„
ƃɨřɩřƃɯřɨɥƄƄ
ʴʴʴ
ƃɨřɩřƃɯřɨɥƄƄ
ʴʴʴ†
ƃɨřɩřƃɯřɨɥƄƄ

Значение элемента ƒƃɩƄ теперь является списком, и его элементы могут быть
изменены. Все методы копирования списков, которые мы уже рассмотрели, были
поверхностными: это не оценочное суждение — речь идет именно о том, насколько
глубоко распространяется копирование.
Для того чтобы это исправить, нужно использовать функцию †‡‡’ ‘’›ſƀ:
ʴʴʴ‹’‘”– ‘’›
ʴʴʴƒʰƃɨřɩřƃɯřɰƄƄ
ʴʴʴ„ʰ ‘’›Ŝ†‡‡’ ‘’›ſƒƀ
ʴʴʴƒ
ƃɨřɩřƃɯřɰƄƄ
ʴʴʴ„
ƃɨřɩřƃɯřɰƄƄ
ʴʴʴƒƃɩƄƃɨƄʰɨɥ
ʴʴʴƒ
ƃɨřɩřƃɯřɨɥƄƄ
ʴʴʴ„
ƃɨřɩřƃɯřɰƄƄ

Функция †‡‡’ ‘’›ſƀ может работать с вложенными списками, словарями и дру-


гими объектами.
Подробнее о директиве ‹’‘”– вы узнаете из главы 11.

ǹȘȈȊȕȐȊȈȍȔșȗȐșȒȐ
Сравнить списки можно с помощью операторов сравнения, таких как ʰʰ, ʳ и дру-
гие. Операторы проходят по обоим спискам, сравнивая элементы с одинаковым
смещением. Если список a короче списка b и все элементы списка a присутствуют
в списке b, будет считаться, что список a меньше списка b:
ʴʴʴƒʰƃɮřɩƄ
ʴʴʴ„ʰƃɮřɩřɰƄ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ʴʴʴƒʰʰ„
ƒŽ•‡
ʴʴʴƒʳʰ„
”—‡
ʴʴʴƒʳ„
”—‡

ǰȚȍȘȐȘțȍȔȗȖșȗȐșȒȈȔșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȖȊIRUȐLQ
Из главы 6 вы узнали, как можно проитерировать по строке с помощью цикла for.
Однако гораздо чаще доводится выполнять итерирование по спискам:
ʴʴʴ Ї‡•‡•ʰƃɐ„”‹‡ɐřɐ‰Œ‡–‘•–ɐřɐŠƒ˜ƒ”–‹ɐƄ
ʴʴʴˆ‘” Ї‡•‡‹ Ї‡•‡•ś
ŜŜŜ’”‹–ſ Ї‡•‡ƀ
ŜŜŜ
brie
‰Œ‡–‘•–
havarti

Как и раньше, ключевое слово „”‡ƒ завершает выполнение цикла for, а ключевое
слово ‘–‹—‡ позволяет перейти к следующей итерации:
ʴʴʴ Ї‡•‡•ʰƃɐ„”‹‡ɐřɐ‰Œ‡–‘•–ɐřɐŠƒ˜ƒ”–‹ɐƄ
ʴʴʴˆ‘” Ї‡•‡‹ Ї‡•‡•ś
ŜŜŜ‹ˆ Ї‡•‡Ŝ•–ƒ”–•™‹–Šſɐ‰ɐƀś
ŜŜŜ’”‹–ſɑ ™‘ɐ–‡ƒ–ƒ›–Š‹‰–Šƒ–•–ƒ”–•™‹–Šɐ‰ɐɑƀ
ŜŜŜ„”‡ƒ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſ Ї‡•‡ƀ
ŜŜŜ
brie
™‘ɐ–‡ƒ–ƒ›–Š‹‰–Šƒ–•–ƒ”–•™‹–Šɐ‰ɐ

Вы по-прежнему можете использовать опциональный блок else, если цикл for


завершился без „”‡ƒ:
ʴʴʴ Ї‡•‡•ʰƃɐ„”‹‡ɐřɐ‰Œ‡–‘•–ɐřɐŠƒ˜ƒ”–‹ɐƄ
ʴʴʴˆ‘” Ї‡•‡‹ Ї‡•‡•ś
ŜŜŜ‹ˆ Ї‡•‡Ŝ•–ƒ”–•™‹–Šſɐšɐƀś
ŜŜŜ’”‹–ſɑ ™‘ɐ–‡ƒ–ƒ›–Š‹‰–Šƒ–•–ƒ”–•™‹–Šɐšɐɑƀ
ŜŜŜ„”‡ƒ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſ Ї‡•‡ƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ‹†ɐ–ˆ‹†ƒ›–Š‹‰–Šƒ–•–ƒ”–‡†™‹–Šɐšɐɑƀ
ŜŜŜ
brie
‰Œ‡–‘•–
havarti
‹†ɐ–ˆ‹†ƒ›–Š‹‰–Šƒ–•–ƒ”–‡†™‹–Šɐšɐ
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

Если цикл for не отработал ни разу, выполнение также продолжится в блоке else:
ʴʴʴ Ї‡•‡•ʰƃƄ
ʴʴʴˆ‘” Ї‡•‡‹ Ї‡•‡•ś
ŜŜŜ’”‹–ſɐŠ‹••Š‘’Šƒ••‘‡Ž‘˜‡Ž›ɐř Ї‡•‡ƀ
ŜŜŜ„”‡ƒ
ŜŜŜ‡Ž•‡śɤȢȦȥȧȦȥȦȖȜș„”‡ƒȢțȡȔȫȔșȦȢȦȥȧȦȥȦȖȜșȥȯȤȔ
ŜŜŜ’”‹–ſɐŠ‹•‹•‘–— Š‘ˆƒ Ї‡•‡•Š‘’ř‹•‹–ţɐƀ
ŜŜŜ
Š‹•‹•‘–— Š‘ˆƒ Ї‡•‡•Š‘’ř‹•‹–ţ

Поскольку список Š‡‡•‡• в этом примере был пуст, цикл for Ї‡•‡ in Ї‡•‡•
ни разу не отработал, а оператор „”‡ƒ не был применен.

ǰȚȍȘȐȘțȍȔȗȖȕȍșȒȖȓȤȒȐȔȗȖșȓȍȌȖȊȈȚȍȓȤȕȖșȚȧȔ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐ]LS
Есть еще один хороший прием — параллельное итерирование по нескольким по-
следовательностям с помощью функции œ‹’ſƀ:
ʴʴʴ†ƒ›•ʰƃɐ‘†ƒ›ɐřɐ—‡•†ƒ›ɐřɐ‡†‡•†ƒ›ɐƄ
ʴʴʴˆ”—‹–•ʰƃɐ„ƒƒƒɐřɐ‘”ƒ‰‡ɐřɐ’‡ƒ ŠɐƄ
ʴʴʴ†”‹•ʰƃɐ ‘ˆˆ‡‡ɐřɐ–‡ƒɐřɐ„‡‡”ɐƄ
ʴʴʴ†‡••‡”–•ʰƃɐ–‹”ƒ‹•—ɐřɐ‹ ‡ ”‡ƒɐřɐ’‹‡ɐřɐ’—††‹‰ɐƄ
ʴʴʴˆ‘”†ƒ›řˆ”—‹–ř†”‹ř†‡••‡”–‹œ‹’ſ†ƒ›•řˆ”—‹–•ř†”‹•ř†‡••‡”–•ƀś
ŜŜŜ’”‹–ſ†ƒ›řɑś†”‹ɑř†”‹řɑ‡ƒ–ɑřˆ”—‹–řɑ‡Œ‘›ɑř†‡••‡”–ƀ
ŜŜŜ
‘†ƒ›ś†”‹ ‘ˆˆ‡‡Ź‡ƒ–„ƒƒƒŹ‡Œ‘›–‹”ƒ‹•—
—‡•†ƒ›ś†”‹–‡ƒŹ‡ƒ–‘”ƒ‰‡Ź‡Œ‘›‹ ‡ ”‡ƒ
‡†‡•†ƒ›ś†”‹„‡‡”ʇƒ–’‡ƒ ŠŹ‡Œ‘›’‹‡

Функция œ‹’ſƀ прекратит свою работу, когда будет выполнена самая короткая
последовательность. Один из списков (†‡••‡”–•) оказался длиннее остальных, по-
этому никто не получит пудинг, пока мы не увеличим остальные списки.
В главе 8 показывается, как с помощью функции †‹ –ſƀ можно создавать словари
из двухэлементных последовательностей, таких как кортежи, списки или строки.
Функция œ‹’ſƀ позволяет пройти по нескольким последовательностям и создать
кортежи из элементов с одинаковым смещением. Создадим два кортежа из соот-
ветствующих друг другу английских и французских слов:
ʴʴʴ‡‰Ž‹•Šʰɐ‘†ƒ›ɐřɐ—‡•†ƒ›ɐřɐ‡†‡•†ƒ›ɐ
ʴʴʴˆ”‡ Šʰɐ—†‹ɐřɐƒ”†‹ɐřɐ‡” ”‡†‹ɐ

Теперь используем функцию œ‹’ſƀ, чтобы объединить эти кортежи с состав-


лением пар. Значение, возвращаемое функцией œ‹’ſƀ, само по себе не является
списком или кортежем, но его можно преобразовать в любую из этих последова-
тельностей:
ʴʴʴŽ‹•–ſœ‹’ſ‡‰Ž‹•Šřˆ”‡ Šƀƀ
ƃſɐ‘†ƒ›ɐřɐ—†‹ɐƀřſɐ—‡•†ƒ›ɐřɐƒ”†‹ɐƀřſɐ‡†‡•†ƒ›ɐřɐ‡” ”‡†‹ɐƀƄ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Передадим результат работы функции œ‹’ſƀ непосредственно функции †‹ –ſƀ —


и у нас готов небольшой англо-французский словарь!
ʴʴʴ†‹ –ſœ‹’ſ‡‰Ž‹•Šřˆ”‡ Šƀƀ
Ƈɐ‘†ƒ›ɐśɐ—†‹ɐřɐ—‡•†ƒ›ɐśɐƒ”†‹ɐřɐ‡†‡•†ƒ›ɐśɐ‡” ”‡†‹ɐƈ

ǹȖȏȌȈȍȔșȗȐșȖȒșȗȖȔȖȡȤȦșȗȐșȒȖȊȣȝȊȒȓȦȟȍȕȐȑ
Вы уже знаете, что список можно создать с помощью квадратных скобок и функции
Ž‹•–ſƀ. Сейчас мы рассмотрим создание списка с помощью списковых включений
(их еще называют генераторами списков, представлением списков и т. д.): этот
механизм использует итерирование с помощью ключевых слов for/in, которое мы
только что рассмотрели.
Вы можете создать список целых чисел от 1 до 5, добавляя их по одному, напри-
мер так:
ʴʴʴ—„‡”ɏŽ‹•–ʰƃƄ
ʴʴʴ—„‡”ɏŽ‹•–Ŝƒ’’‡†ſɨƀ
ʴʴʴ—„‡”ɏŽ‹•–Ŝƒ’’‡†ſɩƀ
ʴʴʴ—„‡”ɏŽ‹•–Ŝƒ’’‡†ſɪƀ
ʴʴʴ—„‡”ɏŽ‹•–Ŝƒ’’‡†ſɫƀ
ʴʴʴ—„‡”ɏŽ‹•–Ŝƒ’’‡†ſɬƀ
ʴʴʴ—„‡”ɏŽ‹•–
ƃɨřɩřɪřɫřɬƄ

Или же используя итератор и функцию ”ƒ‰‡ſƀ:


ʴʴʴ—„‡”ɏŽ‹•–ʰƃƄ
ʴʴʴˆ‘”—„‡”‹”ƒ‰‡ſɨřɭƀś
ŜŜŜ—„‡”ɏŽ‹•–Ŝƒ’’‡†ſ—„‡”ƀ
ŜŜŜ
ʴʴʴ—„‡”ɏŽ‹•–
ƃɨřɩřɪřɫřɬƄ

Или же преобразуя в список сам результат работы функции ”ƒ‰‡ſƀś


ʴʴʴ—„‡”ɏŽ‹•–ʰŽ‹•–ſ”ƒ‰‡ſɨřɭƀƀ
ʴʴʴ—„‡”ɏŽ‹•–
ƃɨřɩřɪřɫřɬƄ

Все эти приемы абсолютно корректны с точки зрения Python и приводят к одина-
ковому результату. Однако более характерным для Python является создание списка
с помощью списковых включений. Простейшая форма такого включения выглядит
следующим образом:
ƃȖȯȤȔȚșȡȜșˆ‘”ȱȟșȠșȡȦ‹ȜȦșȤȔȕșȟȰȡȯȝȢȕȮșȞȦƄ

Вот так списковое включение может составить список целых чисел:


ʴʴʴ—„‡”ɏŽ‹•–ʰƃ—„‡”ˆ‘”—„‡”‹”ƒ‰‡ſɨřɭƀƄ
ʴʴʴ—„‡”ɏŽ‹•–
ƃɨřɩřɪřɫřɬƄ

Первая переменная —„‡” нужна для формирования значений для списка, то есть
для размещения результата работы цикла в переменной —„‡”ɏŽ‹•–. Вторая пере-
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

менная —„‡” является частью цикла for. Чтобы показать, что первая переменная
—„‡” является выражением, попробуем такой вариант:
ʴʴʴ—„‡”ɏŽ‹•–ʰƃ—„‡”Şɨˆ‘”—„‡”‹”ƒ‰‡ſɨřɭƀƄ
ʴʴʴ—„‡”ɏŽ‹•–
ƃɥřɨřɩřɪřɫƄ

Списковое включение перемещает цикл в квадратные скобки. Этот пример


включения не намного проще предыдущего, однако можно пойти дальше и добавить
условное выражение, которое выглядит следующим образом:
ƃȖȯȤȔȚșȡȜșˆ‘”ȱȟșȠșȡȦ‹ȜȦșȤȔȕșȟȰȡȯȝȢȕȮșȞȦ‹ˆȧȥȟȢȖȜșƄ

Используем новое включение для создания списка только из четных чисел,


расположенных в диапазоне от 1 до 5 (помните, что выражение —„‡” ʩ ɩ имеет
значение ”—‡ для четных чисел и ƒŽ•‡ для нечетных):
ʴʴʴƒɏŽ‹•–ʰƃ—„‡”ˆ‘”—„‡”‹”ƒ‰‡ſɨřɭƀ‹ˆ—„‡”ʩɩʰʰɨƄ
ʴʴʴƒɏŽ‹•–
ƃɨřɪřɬƄ

Такое включение выглядит чуть более компактно, чем в обычном варианте:


ʴʴʴƒɏŽ‹•–ʰƃƄ
ʴʴʴˆ‘”—„‡”‹”ƒ‰‡ſɨřɭƀś
ŜŜŜ‹ˆ—„‡”ʩɩʰʰɨś
ŜŜŜƒɏŽ‹•–Ŝƒ’’‡†ſ—„‡”ƀ
ŜŜŜ
ʴʴʴƒɏŽ‹•–
ƃɨřɪřɬƄ

Наконец, точно так же, как и при работе с вложенными циклами, можно написать
более чем один набор операторов for ŜŜŜ в соответствующем включении. Чтобы про-
демонстрировать это, сначала создадим старый добрый вложенный цикл и выведем
на экран результат:
ʴʴʴ”‘™•ʰ”ƒ‰‡ſɨřɫƀ
ʴʴʴ ‘Ž•ʰ”ƒ‰‡ſɨřɪƀ
ʴʴʴˆ‘””‘™‹”‘™•ś
ŜŜŜˆ‘” ‘Ž‹ ‘Ž•ś
ŜŜŜ’”‹–ſ”‘™ř ‘Žƀ
ŜŜŜ
ɨɨ
ɨɩ
ɩɨ
ɩɩ
ɪɨ
ɪɩ

Теперь воспользуемся включением и присвоим его переменной ‡ŽŽ•, создавая


тем самым список кортежей ſ”‘™ř ‘Žƀ:
ʴʴʴ”‘™•ʰ”ƒ‰‡ſɨřɫƀ
ʴʴʴ ‘Ž•ʰ”ƒ‰‡ſɨřɪƀ
ʴʴʴ ‡ŽŽ•ʰƃſ”‘™ř ‘Žƀˆ‘””‘™‹”‘™•ˆ‘” ‘Ž‹ ‘Ž•Ƅ
ʴʴʴˆ‘” ‡ŽŽ‹ ‡ŽŽ•ś
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ŜŜŜ’”‹–ſ ‡ŽŽƀ
ŜŜŜ
ſɨřɨƀ
ſɨřɩƀ
ſɩřɨƀ
ſɩřɩƀ
ſɪřɨƀ
ſɪřɩƀ

Кстати, вы можете воспользоваться распаковкой кортежа, чтобы получить зна-


чения row и ‘Ž из каждого кортежа по мере итерирования по списку ‡ŽŽ•:
ʴʴʴˆ‘””‘™ř ‘Ž‹ ‡ŽŽ•ś
ŜŜŜ’”‹–ſ”‘™ř ‘Žƀ
ŜŜŜ
ɨɨ
ɨɩ
ɩɨ
ɩɩ
ɪɨ
ɪɩ

Фрагменты for row ŜŜŜ и for ‘Ž ŜŜŜ в списковом включении также могут иметь
свои проверки if.

ǹȗȐșȒȐșȗȐșȒȖȊ
Списки могут содержать элементы различных типов, в том числе и другие списки,
как показано далее:
ʴʴʴ•ƒŽŽɏ„‹”†•ʰƃɐŠ—‹‰„‹”†ɐřɐˆ‹ ŠɐƄ
ʴʴʴ‡š–‹ –ɏ„‹”†•ʰƃɐ†‘†‘ɐřɐ’ƒ••‡‰‡”’‹‰‡‘ɐřɐ‘”™‡‰‹ƒŽ—‡ɐƄ
ʴʴʴ ƒ”‘Žɏ„‹”†•ʰƃɪřɐ ”‡ ŠЇ•ɐřɩřɐ–—”–އ†‘˜‡•ɐƄ
ʴʴʴƒŽŽɏ„‹”†•ʰƃ•ƒŽŽɏ„‹”†•ř‡š–‹ –ɏ„‹”†•řɐƒ ƒ™ɐř ƒ”‘Žɏ„‹”†•Ƅ

Как же будет выглядеть список списков ƒŽŽɏ„‹”†•?


ʴʴʴƒŽŽɏ„‹”†•
ƃƃɐŠ—‹‰„‹”†ɐřɐˆ‹ ŠɐƄřƃɐ†‘†‘ɐřɐ’ƒ••‡‰‡”’‹‰‡‘ɐřɐ‘”™‡‰‹ƒŽ—‡ɐƄřɐƒ ƒ™ɐř
ƃɪřɐ ”‡ ŠЇ•ɐřɩřɐ–—”–އ†‘˜‡•ɐƄƄ

Посмотрим на его первый элемент:


ʴʴʴƒŽŽɏ„‹”†•ƃɥƄ
ƃɐŠ—‹‰„‹”†ɐřɐˆ‹ ŠɐƄ

Первый элемент является списком — это список •ƒŽŽɏ„‹”†•, который мы указа-


ли как первый элемент списка ƒŽŽɏ„‹”†•. Нетрудно догадаться, чем является второй
элемент:
ʴʴʴƒŽŽɏ„‹”†•ƃɨƄ
ƃɐ†‘†‘ɐřɐ’ƒ••‡‰‡”’‹‰‡‘ɐřɐ‘”™‡‰‹ƒŽ—‡ɐƄ
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

Это второй указанный нами элемент, ‡š–‹ –ɏ„‹”†•. Если нам понадобится по-
лучить первый элемент списка ‡š–‹ –ɏ„‹”†•, извлечь его из списка ƒŽŽɏ„‹”†• мы
можем, указав два индекса:
ʴʴʴƒŽŽɏ„‹”†•ƃɨƄƃɥƄ
ɐ†‘†‘ɐ

Индекс ƃɨƄ ссылается на второй элемент списка ƒŽŽɏ„‹”†•, а ƃɥƄ — на первый


элемент внутреннего списка.

DzȖȘȚȍȎȐȐȓȐșȗȐșȒȐ"
Вместо списков можно использовать кортежи, однако у них меньше возможно-
стей — нет функций ƒ’’‡†ſƀ, ‹•‡”–ſƀ и т. д., поскольку кортеж не может быть
изменен после создания. Почему бы тогда не работать всегда со списками вместо
кортежей?
‰Кортежи занимают меньше места.
‰Вы не сможете уничтожить элементы кортежа по ошибке.
‰Вы можете использовать кортежи в качестве словарных ключей (см. главу 8).
‰Именованные кортежи (см. раздел «Именованные кортежи» в главе 10) могут
служить более простой альтернативой объектам.
Здесь я не буду вдаваться в подробности использования кортежей. Чаще при
решении повседневных задач вам доведется обращаться именно к спискам и сло-
варям.

ǪȒȓȦȟȍȕȐȑȒȖȘȚȍȎȍȑȕȍșțȡȍșȚȊțȍȚ
Изменяемые типы (списки, словари и множества) имеют включения. Неизменяе-
мые типы, такие как строки и кортежи, нужно создавать другими методами, описан-
ными в соответствующих разделах.
Вы можете подумать, что замена квадратных скобок спискового включения
круглыми скобками создаст кортежное включение. Может даже показаться, что это
работает, поскольку исключение не сгенерируется:
ʴʴʴ—„‡”ɏ–Š‹‰ʰſ—„‡”ˆ‘”—„‡”‹”ƒ‰‡ſɨřɭƀƀ

Однако в круглых скобках находится что-то совершенно иное — включение ге-


нератора, и оно вернет объект генератора:
ʴʴʴ–›’‡ſ—„‡”ɏ–Š‹‰ƀ
ʳ Žƒ••ɐ‰‡‡”ƒ–‘”ɐʴ

Генераторы мы рассмотрим более подробно в разделе «Генераторы» главы 9.


Генератор — это один из способов предоставления данных итератору.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǿȐȚȈȑȚȍȌȈȓȍȍ
Следующие темы — словари и множества — настолько объемные, что заслужили
отдельную главу.

ǻȗȘȈȎȕȍȕȐȧ
Используйте списки и кортежи из чисел (глава 3) и строки (глава 3), чтобы пред-
ставить самые разные элементы реального мира.
7.1. Создайте список ›‡ƒ”•ɏŽ‹•–, содержащий год, в который вы родились, и каждый
последующий год вплоть до вашего пятого дня рождения. Например, если вы
родились в 1980 году, список будет выглядеть так: ›‡ƒ”•ɏŽ‹•– ʰ ƃɨɰɯɥř ɨɰɯɨř
ɨɰɯɩř ɨɰɯɪř ɨɰɯɫř ɨɰɯɬƄ.
Если вам меньше пяти лет, но вы уже читаете эту книгу, то я даже не знаю, что
сказать.
7.2. В какой год из списка ›‡ƒ”•ɏŽ‹•– был ваш третий день рождения? Учтите,
в первый год вам было 0 лет.
7.3. В какой год из списка ›‡ƒ”•ɏŽ‹•– вам было больше всего лет?
7.4. Создайте список things, содержащий три элемента: ɑ‘œœƒ”‡ŽŽƒɑ, ɑ ‹†‡”‡ŽŽƒɑ,
ɑ•ƒŽ‘‡ŽŽƒɑ.
7.5. Напишите с большой буквы тот элемент списка things, который означает чело-
века, а затем выведите список. Изменился ли элемент списка?
7.6. Переведите сырный элемент списка things в верхний регистр целиком и вы-
ведите список.
7.7. Удалите из списка things заболевание, получите Нобелевскую премию и затем
выведите список на экран.
7.8. Создайте список с элементами ɑ ”‘— Š‘ɑ , ɑŠ‹ ‘ɑ и ɑ ƒ”’‘ɑ ; назовите его
surprise.
7.9. Напишите последний элемент списка surprise со строчной буквы, затем вы-
ведите эту строку в обратном порядке и с прописной буквы.
7.10. Используйте списковое включение, чтобы создать список с именем even, в ко-
тором будут содержаться четные числа в промежутке ”ƒ‰‡ſɨɥƀ.
7.11. Попробуйте создать генератор рифм для прыжков через скакалку. Напечатайте
последовательность двухстрочных рифм. Начните программу с этого фраг-
мента:
•–ƒ”–ɨʰƃɑˆ‡‡ɑřɑˆ‹‡ɑřɑˆ‘‡ɑƄ
”Š›‡•ʰƃ
ſɑˆŽ‘’ɑřɑ‰‡–ƒ‘’ɑƀř
ſɑˆ‘’‡ɑřɑ–—”–Ї”‘’‡ɑƀř
ſɑˆƒɑřɑ‰‡–›‘—”ƒɑƀř
ſɑˆ—†‰‡ɑřɑ ƒŽŽ–ЇŒ—†‰‡ɑƀř
ſɑˆƒ–ɑřɑ’‡––Ї ƒ–ɑƀř
ǫȓȈȊȈDzȖȘȚȍȎȐȐșȗȐșȒȐ  

ſɑˆ‘‰ɑřɑ™ƒŽ–Ї†‘‰ɑƀř
ſɑˆ—ɑřɑ•ƒ›™‡ɐ”‡†‘‡ɑƀř
Ƅ
•–ƒ”–ɩʰɑ‘‡‘‡„‡––‡”ɑ

Затем следуйте инструкциям.


Для каждого кортежа ſˆ‹”•–ř •‡ ‘†ƀ в списке ”Š›‡•.
‰Для первой строки:
y выведите на экран каждую строку списка •–ƒ”–ɨ: начните ее с большой
буквы, а закончите восклицательным знаком с пробелом;
y выведите на экран значение переменной first, также записав его с боль-
шой буквы и с восклицательным знаком на конце.
‰Для второй строки:
y выведите на экран значение переменной •–ƒ”–ɩ и пробел;
y выведите на экран значение переменной •‡ ‘† и точку.
ƋƓƈƊƈ
ǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ

Если в словаре слово записано неправильно, как нам


об этом узнать?

Стивен Райт

ǹȓȖȊȈȘȐ
Словарь очень похож на список, но порядок элементов в нем не имеет значения и они
не выбираются смещением, таким как 0 и 1. Вместо этого для каждого значения вы
указываете связанный с ним уникальный ключ. Этот ключ чаще всего представляет
собой строку, но, в принципе, может быть любым из неизменяемых типов: булевой
переменной, целым числом, числом с плавающей точкой, кортежем, строкой, а также
другими объектами, с которыми вы познакомитесь далее. Словари являются изме-
няемыми, а это значит, что вы можете добавить, удалить и изменить их элементы,
имеющие вид «ключ — значение».
Если вы работали с другими языками программирования, которые поддерживают
только массивы и списки, то полюбите словари.

ǪȌȘțȋȐȝȧȏȣȒȈȝșȓȖȊȈȘȐȔȖȋțȚȕȈȏȣȊȈȚȤșȧ ȈșșȖȞȐȈȚȐȊȕȣȔȐ ȔȈșșȐȊȈȔȐ ȝȍȠȈȔȐ


ȐȓȐȝȍȠȚȈȉȓȐȞȍȑǪ3\WKRQșȓȖȊȈȘȤȚȈȒȎȍȗȘȐȕȧȚȖȕȈȏȣȊȈȚȤGLFW

ǹȖȏȌȈȍȔșȓȖȊȈȘȤșȗȖȔȖȡȤȦ^`
Чтобы создать словарь, нужно заключить в фигурные скобки (Ƈƈ) разделенные за-
пятыми пары ȞȟȲȫ : țȡȔȫșȡȜș. Самым простым словарем является пустой словарь,
не содержащий ни ключей, ни значений:
ʴʴʴ‡’–›ɏ†‹ –ʰƇƈ
ʴʴʴ‡’–›ɏ†‹ –
Ƈƈ
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

Создадим небольшой словарь, включающий цитаты из «Словаря сатаны»


Амброза Бирса:
ʴʴʴ„‹‡” ‡ʰƇ
ŜŜŜɑ†ƒ›ɑśɑ’‡”‹‘†‘ˆ–™‡–›Şˆ‘—”Š‘—”•ř‘•–Ž›‹••’‡–ɑř
ŜŜŜɑ’‘•‹–‹˜‡ɑśɑ‹•–ƒ‡ƒ––Ї–‘’‘ˆ‘‡ɐ•˜‘‹ ‡ɑř
ŜŜŜɑ‹•ˆ‘”–—‡ɑśɑЇ‹†‘ˆˆ‘”–—‡–Šƒ–‡˜‡”‹••‡•ɑř
ŜŜŜƈ
ʴʴʴ

Ввод имени словаря в интерактивный интерпретатор выведет все его ключи


и значения:
ʴʴʴ„‹‡” ‡
Ƈɐ†ƒ›ɐśɐ’‡”‹‘†‘ˆ–™‡–›Şˆ‘—”Š‘—”•ř‘•–Ž›‹••’‡–ɐř
ɐ’‘•‹–‹˜‡ɐśɑ‹•–ƒ‡ƒ––Ї–‘’‘ˆ‘‡ɐ•˜‘‹ ‡ɑř
ɐ‹•ˆ‘”–—‡ɐśɐЇ‹†‘ˆˆ‘”–—‡–Šƒ–‡˜‡”‹••‡•ɐƈ

Ǫ3\WKRQȌȖȗțșȒȈȍȚșȧȕȈȓȐȟȐȍȏȈȗȧȚȖȑȗȖșȓȍȗȖșȓȍȌȕȍȋȖȥȓȍȔȍȕȚȈșȗȐșȒȈȒȖȘȚȍȎȈ
ȐȓȐșȓȖȊȈȘȧDzȘȖȔȍȚȖȋȖȕȍȖȉȧȏȈȚȍȓȤȕȖȌȍȓȈȚȤȖȚșȚțȗȣȒȈȒȌȍȓȈȓȧȊȗȘȍȌȣȌț
ȡȍȔȗȘȐȔȍȘȍȒȖȋȌȈȊȣȊȊȖȌȐȚȍȒȓȦȟȐȐȏȕȈȟȍȕȐȧȊȕțȚȘȐȜȐȋțȘȕȣȝșȒȖȉȖȒ²ȥȚȖ
ȗȘȖșȚȖțȓțȟȠȈȍȚȟȐȚȈȉȍȓȤȕȖșȚȤ

ǹȖȏȌȈȍȔșȓȖȊȈȘȤșȗȖȔȖȡȤȦȜțȕȒȞȐȐGLFW
Некоторым людям не нравится печатать так много фигурных скобок и кавычек.
И вы можете создать словарь, передав именованные аргументы и значения в функ-
цию †‹ –ſƀ.
Традиционный способ создания словаря:
ʴʴʴƒ ‡ɏ —•–‘‡”ʰƇɐˆ‹”•–ɐśɐ‹Ž‡ɐřɐ‹††Ž‡ɐśɐɐřɐŽƒ•–ɐśɐ‘›‘–‡ɐƈ
ʴʴʴƒ ‡ɏ —•–‘‡”
Ƈɐˆ‹”•–ɐśɐ‹Ž‡ɐřɐ‹††Ž‡ɐśɐɐřɐŽƒ•–ɐśɐ‘›‘–‡ɐƈ

С использованием †‹ –ſƀ:
ʴʴʴƒ ‡ɏ —•–‘‡”ʰ†‹ –ſˆ‹”•–ʰɑ‹Ž‡ɑř‹††Ž‡ʰɑɑřŽƒ•–ʰɑ‘›‘–‡ɑƀ
ʴʴʴƒ ‡ɏ —•–‘‡”
Ƈɐˆ‹”•–ɐśɐ‹Ž‡ɐřɐ‹††Ž‡ɐśɐɐřɐŽƒ•–ɐśɐ‘›‘–‡ɐƈ

Одним из ограничений второго способа является то, что имена аргументов


должны представлять собой корректные имена переменных (в них не должны ис-
пользоваться пробелы и ключевые слова):
ʴʴʴšʰ†‹ –ſƒ‡ʰɑŽ‡”ɑř†‡ˆʰɑŠ—–‡”ɑƀ
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨ
šʰ†‹ –ſƒ‡ʰɑŽ‡”ɑř†‡ˆʰɑŠ—–‡”ɑƀ
ɋ
›–ƒš””‘”ś‹˜ƒŽ‹†•›–ƒš
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǷȘȍȖȉȘȈȏțȍȔșȗȖȔȖȡȤȦȜțȕȒȞȐȐGLFW
С помощью функции †‹ –ſƀ можно преобразовывать двузначные последователь-
ности в словари. (Иногда вы можете столкнуться с такими последовательностями
«ключ — значение», как «Стронций, 90, углерод, 14»1.) Первый элемент каждой по-
следовательности применяется как ключ, второй — как значение.
Для начала рассмотрим небольшой пример использования lol — списка, состо-
ящего из двузначных списков:
ʴʴʴŽ‘Žʰƃƃɐƒɐřɐ„ɐƄřƃɐ ɐřɐ†ɐƄřƃɐ‡ɐřɐˆɐƄƄ
ʴʴʴ†‹ –ſŽ‘Žƀ
Ƈɐ ɐśɐ†ɐřɐƒɐśɐ„ɐřɐ‡ɐśɐˆɐƈ

Мы могли бы использовать любую последовательность, содержащую последова-


тельности из двух элементов. Рассмотрим другие примеры.
Список, содержащий двухэлементные кортежи:
ʴʴʴŽ‘–ʰƃſɐƒɐřɐ„ɐƀřſɐ ɐřɐ†ɐƀřſɐ‡ɐřɐˆɐƀƄ
ʴʴʴ†‹ –ſŽ‘–ƀ
Ƈɐ ɐśɐ†ɐřɐƒɐśɐ„ɐřɐ‡ɐśɐˆɐƈ

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


ʴʴʴ–‘Žʰſƃɐƒɐřɐ„ɐƄřƃɐ ɐřɐ†ɐƄřƃɐ‡ɐřɐˆɐƄƀ
ʴʴʴ†‹ –ſ–‘Žƀ
Ƈɐ ɐśɐ†ɐřɐƒɐśɐ„ɐřɐ‡ɐśɐˆɐƈ

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


ʴʴʴŽ‘•ʰƃɐƒ„ɐřɐ †ɐřɐ‡ˆɐƄ
ʴʴʴ†‹ –ſŽ‘•ƀ
Ƈɐ ɐśɐ†ɐřɐƒɐśɐ„ɐřɐ‡ɐśɐˆɐƈ

Кортеж, содержащий двухсимвольные строки:


ʴʴʴ–‘•ʰſɐƒ„ɐřɐ †ɐřɐ‡ˆɐƀ
ʴʴʴ†‹ –ſ–‘•ƀ
Ƈɐ ɐśɐ†ɐřɐƒɐśɐ„ɐřɐ‡ɐśɐˆɐƈ

В подразделе «Итерируем по нескольким последовательностям с помощью


функции zip()» главы 7 вы уже познакомились с функцией œ‹’ſƀ, которая позволит
вам легко создавать такие двухэлементные последовательности.

ǬȖȉȈȊȓȧȍȔȐȓȐȐȏȔȍȕȧȍȔȥȓȍȔȍȕȚșȗȖȔȖȡȤȦ
ȒȖȕșȚȘțȒȞȐȐ>ȒȓȦȟ@
Добавить элемент в словарь довольно легко. Просто обратитесь к элементу по его
ключу и присвойте ему значение. Если ключ уже существует в словаре, имеющееся
значение будет заменено новым. Если ключ новый, он и указанное значение будут
добавлены в словарь. В отличие от списков, здесь вам не нужно беспокоиться о том,

1
Очень похоже на финальный счет матча «Стронций» — «Углерод».
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

что Python сгенерирует исключение во время присваивания нового элемента, если


вы укажете индекс, который выходит за пределы существующего диапазона.
Сейчас мы создадим словарь с перечислением участников комик-группы из
Великобритании Monty Python, используя их фамилии в качестве ключей, а име-
на — в качестве значений:
ʴʴʴ’›–Š‘•ʰƇ
ŜŜŜɐŠƒ’ƒɐśɐ ”ƒŠƒɐř
ŜŜŜɐއ‡•‡ɐśɐ ‘Аɐř
ŜŜŜɐ †Ž‡ɐśɐ”‹ ɐř
ŜŜŜɐ ‘‡•ɐśɐ‡””›ɐř
ŜŜŜɐƒŽ‹ɐśɐ‹ Šƒ‡Žɐř
ŜŜŜƈ
ʴʴʴ’›–Š‘•
ƇɐŠƒ’ƒɐśɐ ”ƒŠƒɐřɐއ‡•‡ɐśɐ ‘Аɐřɐ †Ž‡ɐśɐ”‹ ɐř
ɐ ‘‡•ɐśɐ‡””›ɐřɐƒŽ‹ɐśɐ‹ Šƒ‡Žɐƈ

Не хватает одного участника — уроженца Америки Терри Гиллиама. Здесь вы


увидите попытку неизвестного программиста его добавить. Однако программист
ошибся, когда вводил имя:
ʴʴʴ’›–Š‘•ƃɐ ‹ŽŽ‹ƒɐƄʰɐ ‡””›ɐ
ʴʴʴ’›–Š‘•
ƇɐŠƒ’ƒɐśɐ ”ƒŠƒɐřɐއ‡•‡ɐśɐ ‘Аɐřɐ †Ž‡ɐśɐ”‹ ɐř
ɐ ‘‡•ɐśɐ‡””›ɐřɐƒŽ‹ɐśɐ‹ Šƒ‡Žɐřɐ ‹ŽŽ‹ƒɐśɐ ‡””›ɐƈ

А вот код другого программиста, который исправил эту ошибку:


ʴʴʴ’›–Š‘•ƃɐ ‹ŽŽ‹ƒɐƄʰɐ‡””›ɐ
ʴʴʴ’›–Š‘•
ƇɐŠƒ’ƒɐśɐ ”ƒŠƒɐřɐއ‡•‡ɐśɐ ‘Аɐřɐ †Ž‡ɐśɐ”‹ ɐř
ɐ ‘‡•ɐśɐ‡””›ɐřɐƒŽ‹ɐśɐ‹ Šƒ‡Žɐřɐ ‹ŽŽ‹ƒɐśɐ‡””›ɐƈ

Используя один и тот же ключ (ɐ ‹ŽŽ‹ƒɐ), мы заменили исходное значение


ɐ ‡””›ɐ на ɐ‡””›ɐ.
Помните, что ключи в словаре должны быть уникальными. Именно поэтому мы
в качестве ключей использовали фамилии, а не имена — двух участников Monty
Python зовут Терри. Если вы примените ключ более одного раза, победит последнее
значение:
ʴʴʴ•‘‡ɏ’›–Š‘•ʰƇ
ŜŜŜɐ ”ƒŠƒɐśɐŠƒ’ƒɐř
ŜŜŜɐ ‘Аɐśɐއ‡•‡ɐř
ŜŜŜɐ”‹ ɐśɐ †Ž‡ɐř
ŜŜŜɐ‡””›ɐśɐ ‹ŽŽ‹ƒɐř
ŜŜŜɐ‹ Šƒ‡ŽɐśɐƒŽ‹ɐř
ŜŜŜɐ‡””›ɐśɐ ‘‡•ɐř
ŜŜŜƈ
ʴʴʴ•‘‡ɏ’›–Š‘•
Ƈɐ ”ƒŠƒɐśɐŠƒ’ƒɐřɐ ‘Аɐśɐއ‡•‡ɐřɐ”‹ ɐśɐ †Ž‡ɐř
ɐ‡””›ɐśɐ ‘‡•ɐřɐ‹ Šƒ‡ŽɐśɐƒŽ‹ɐƈ

Сначала мы присвоили значение ɐ ‹ŽŽ‹ƒɐ ключу ɐ‡””›ɐ, а затем заменили его


на ɐ ‘‡•ɐ.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǷȖȓțȟȈȍȔȥȓȍȔȍȕȚșȓȖȊȈȘȧșȗȖȔȖȡȤȦ
ȒȖȕșȚȘțȒȞȐȐ>ȒȓȦȟ@ȐȓȐȜțȕȒȞȐȐJHW
Этот вариант использования словаря — самый распространенный. Вы указываете
словарь и ключ, чтобы получить соответствующее значение. Применим •‘‡ɏ’Š›–‘
из предыдущего подраздела:
ʴʴʴ•‘‡ɏ’›–Š‘•ƃɐ ‘АɐƄ
ɐއ‡•‡ɐ

Если ключа в словаре нет, будет сгенерировано исключение:


ʴʴʴ•‘‡ɏ’›–Š‘•ƃɐ ”‘— Š‘ɐƄ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
‡›””‘”śɐ ”‘— Š‘ɐ

Есть два хороших способа избежать возникновения подобного исключения.


Первый — с помощью ключевого слова in проверить, имеется ли заданный ключ.
Этот способ вы уже видели в предыдущем подразделе:
ʴʴʴɐ ”‘— Š‘ɐ‹’›–Š‘•
ƒŽ•‡

Второй способ — использовать специальную функцию словаря ‰‡–ſƀ. Вы указы-


ваете словарь, ключ и опциональное значение. Если ключ существует, вы получите
связанное с ним значение:
ʴʴʴ’›–Š‘•Ŝ‰‡–ſɐ ‘Аɐƀ
ɐއ‡•‡ɐ

Если такого ключа нет, вы получите опциональное значение:


ʴʴʴ’›–Š‘•Ŝ‰‡–ſɐ ”‘— Š‘ɐřɐ‘–ƒ›–Š‘ɐƀ
ɐ‘–ƒ›–Š‘ɐ

В противном случае вам будет возвращен объект ‘‡ (интерактивный интер-


претатор ничего не выведет):
ʴʴʴ’›–Š‘•Ŝ‰‡–ſ ”‘— Š‘ɐƀ
ʴʴʴ

ǷȖȓțȟȈȍȔȊșȍȒȓȦȟȐ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐNH\V
Вы можете использовать функцию ‡›•ſƀ , чтобы получить все ключи словаря.
Для следующих примеров обратимся к другому словарю:
ʴʴʴ•‹‰ƒŽ•ʰƇɐ‰”‡‡ɐśɐ‰‘ɐřɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐřɐ”‡†ɐśɐ•‹Ž‡ˆ‘”–Ї ƒ‡”ƒɐƈ
ʴʴʴ•‹‰ƒŽ•Ŝ‡›•ſƀ
†‹ –ɏ‡›•ſƃɐ‰”‡‡ɐřɐ”‡†ɐřɐ›‡ŽŽ‘™ɐƄƀ
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

Ǫ 3\WKRQ  ȜțȕȒȞȐȧ NH\V  ȊȖȏȊȘȈȡȈȍȚ ȗȘȖșȚȖȑ șȗȐșȖȒ Ǫ 3\WKRQ  ȥȚȈ ȜțȕȒȞȐȧ


ȊȖȏȊȘȈȡȈȍȚGLFWBNH\V ²ȐȚȍȘȈȉȍȓȤȕȖȍȗȘȍȌșȚȈȊȓȍȕȐȍȒȓȦȟȍȑȅȚȖțȌȖȉȕȖȌȓȧ
ȒȘțȗȕȣȝșȓȖȊȈȘȍȑȗȖșȒȖȓȤȒțȕȍȚȘȍȉțȍȚȊȘȍȔȍȕȐȐȗȈȔȧȚȐȌȓȧșȖȏȌȈȕȐȧȐșȖȝȘȈ
ȕȍȕȐȧșȗȐșȒȈȒȖȚȖȘȣȔȊȣȊȖȏȔȖȎȕȖȌȈȎȍȕȍȊȖșȗȖȓȤȏțȍȚȍșȤǵȖȏȈȟȈșȚțȦȊȈȔ
ȚȘȍȉțȍȚșȧȐȔȍȕȕȖșȗȐșȖȒǪ3\WKRQȕȈȌȖȊȣȏȊȈȚȤȜțȕȒȞȐȦOLVW ȟȚȖȉȣȗȘȍȖȉ
ȘȈȏȖȊȈȚȤGLFWBNH\VȊșȗȐșȖȒ

ʴʴʴŽ‹•–ſ•‹‰ƒŽ•Ŝ‡›•ſƀƀ
ƃɐ‰”‡‡ɐřɐ”‡†ɐřɐ›‡ŽŽ‘™ɐƄ

В Python 3 вам также необходимо применять функцию Ž‹•–ſƀ, чтобы преобра-


зовывать результат работы функций ˜ƒŽ—‡•ſƀ и ‹–‡•ſƀ в обычные списки. Я поль-
зуюсь этой функцией в своих примерах.

ǷȖȓțȟȈȍȔȊșȍȏȕȈȟȍȕȐȧșȗȖȔȖȡȤȦȜțȕȒȞȐȐYDOXHV
Чтобы получить все значения словаря, используйте функцию ˜ƒŽ—‡•ſƀ:
ʴʴʴŽ‹•–ſ•‹‰ƒŽ•Ŝ˜ƒŽ—‡•ſƀƀ
ƃɐ‰‘ɐřɐ•‹Ž‡ˆ‘”–Ї ƒ‡”ƒɐřɐ‰‘ˆƒ•–‡”ɐƄ

ǷȖȓțȟȈȍȔȊșȍȗȈȘȣ©ȒȓȦȟ²ȏȕȈȟȍȕȐȍª
șȗȖȔȖȡȤȦȜțȕȒȞȐȐLWHPV
Когда вам нужно получить все пары «ключ — значение» из словаря, используйте
функцию ‹–‡•ſƀ:
ʴʴʴŽ‹•–ſ•‹‰ƒŽ•Ŝ‹–‡•ſƀƀ
ƃſɐ‰”‡‡ɐřɐ‰‘ɐƀřſɐ”‡†ɐřɐ•‹Ž‡ˆ‘”–Ї ƒ‡”ƒɐƀřſɐ›‡ŽŽ‘™ɐřɐ‰‘ˆƒ•–‡”ɐƀƄ

Каждая пара будет возвращена в виде кортежа, например ſɐ‰”‡‡ɐř ɐ‰‘ɐƀ.

ǷȖȓțȟȈȍȔȌȓȐȕțșȓȖȊȈȘȧșȗȖȔȖȡȤȦȜțȕȒȞȐȐOHQ
Количество пар «ключ — значение» определяется так:
ʴʴʴއſ•‹‰ƒŽ•ƀ
ɪ

ǶȉȢȍȌȐȕȧȍȔșȓȖȊȈȘȐșȗȖȔȖȡȤȦȒȖȕșȚȘțȒȞȐȐ^ D E`
В версиях Python 3.5 и выше есть новый способ объединять словари с помощью
конструкции **, которая в главе 9 применяется совершенно по-иному:
ʴʴʴˆ‹”•–ʰƇɐƒɐśɐƒ‰‘›ɐřɐ„ɐśɐ„Ž‹••ɐƈ
ʴʴʴ•‡ ‘†ʰƇɐ„ɐśɐ„ƒ‰‡Ž•ɐřɐ ɐśɐ ƒ†›ɐƈ
ʴʴʴƇƋƋˆ‹”•–řƋƋ•‡ ‘†ƈ
Ƈɐƒɐśɐƒ‰‘›ɐřɐ„ɐśɐ„ƒ‰‡Ž•ɐřɐ ɐśɐ ƒ†›ɐƈ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Фактически вы можете передать в качестве параметров больше двух словарей:


ʴʴʴ–Š‹”†ʰƇɐ†ɐśɐ†‘—–•ɐƈ
ʴʴʴƇƋƋˆ‹”•–řƋƋ–Š‹”†řƋƋ•‡ ‘†ƈ
Ƈɐƒɐśɐƒ‰‘›ɐřɐ„ɐśɐ„ƒ‰‡Ž•ɐřɐ†ɐśɐ†‘—–•ɐřɐ ɐśɐ ƒ†›ɐƈ

Эти копии являются поверхностными. Обратитесь к подразделу, в котором


рассматривается функция †‡‡’ ‘’›ſƀ (см. подраздел «Копируем все с помощью
функции deepcopy()» далее в этой главе), если вам нужно получить полные копии
ключей и значений, не связанные с исходными словарями.

ǶȉȢȍȌȐȕȧȍȔșȓȖȊȈȘȐ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐXSGDWH
Вы можете использовать функцию —’†ƒ–‡ſƀ, чтобы скопировать ключи и значения
из одного словаря в другой.
Определим словарь pythons, содержащий имена всех участников:
ʴʴʴ’›–Š‘•ʰƇ
ŜŜŜɐŠƒ’ƒɐśɐ ”ƒŠƒɐř
ŜŜŜɐއ‡•‡ɐśɐ ‘Аɐř
ŜŜŜɐ ‹ŽŽ‹ƒɐśɐ‡””›ɐř
ŜŜŜɐ †Ž‡ɐśɐ”‹ ɐř
ŜŜŜɐ ‘‡•ɐśɐ‡””›ɐř
ŜŜŜɐƒŽ‹ɐśɐ‹ Šƒ‡Žɐř
ƈ
ʴʴʴ’›–Š‘•
ƇɐŠƒ’ƒɐśɐ ”ƒŠƒɐřɐއ‡•‡ɐśɐ ‘Аɐřɐ ‹ŽŽ‹ƒɐśɐ‡””›ɐř
ɐ †Ž‡ɐśɐ”‹ ɐřɐ ‘‡•ɐśɐ‡””›ɐřɐƒŽ‹ɐśɐ‹ Šƒ‡Žɐƈ

Кроме того, у нас есть еще один словарь — others, содержащий имена других
юмористов:
ʴʴʴ‘–Ї”•ʰƇɐƒ”šɐśɐ ”‘— Š‘ɐřɐ ‘™ƒ”†ɐśɐ‘‡ɐƈ

Теперь появляется еще один программист, который решил, что члены словаря
others должны быть членами Monty Python:
ʴʴʴ’›–Š‘•Ŝ—’†ƒ–‡ſ‘–Ї”•ƀ
ʴʴʴ’›–Š‘•
ƇɐŠƒ’ƒɐśɐ ”ƒŠƒɐřɐއ‡•‡ɐśɐ ‘Аɐřɐ ‹ŽŽ‹ƒɐśɐ‡””›ɐř
ɐ †Ž‡ɐśɐ”‹ ɐřɐ ‘‡•ɐśɐ‡””›ɐřɐƒŽ‹ɐśɐ‹ Šƒ‡Žɐř
ɐƒ”šɐśɐ ”‘— Š‘ɐřɐ ‘™ƒ”†ɐśɐ‘‡ɐƈ

Что произойдет, если во втором словаре будут находиться такие же ключи, что
и в первом? Победит значение из второго словаря:
ʴʴʴˆ‹”•–ʰƇɐƒɐśɨřɐ„ɐśɩƈ
ʴʴʴ•‡ ‘†ʰƇɐ„ɐśɐ’Žƒ–›’—•ɐƈ
ʴʴʴˆ‹”•–Ŝ—’†ƒ–‡ſ•‡ ‘†ƀ
ʴʴʴˆ‹”•–
Ƈɐƒɐśɨřɐ„ɐśɐ’Žƒ–›’—•ɐƈ
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

ǻȌȈȓȧȍȔȥȓȍȔȍȕȚȣȗȖȐȝȒȓȦȟțșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈGHO
Код нашего анонимного программиста ’›–Š‘•Ŝ—’†ƒ–‡ſ‘–Ї”•ƀ был корректным
технически, но не фактически. Члены словаря others, несмотря на свою известность
и чувство юмора, не участвовали в Monty Python. Отменим добавление последних
двух элементов:
ʴʴʴ†‡Ž’›–Š‘•ƃɐƒ”šɐƄ
ʴʴʴ’›–Š‘s
ƇɐŠƒ’ƒɐśɐ ”ƒŠƒɐřɐއ‡•‡ɐśɐ ‘Аɐřɐ ‹ŽŽ‹ƒɐśɐ‡””›ɐř
ɐ †Ž‡ɐśɐ”‹ ɐřɐ ‘‡•ɐśɐ‡””›ɐřɐƒŽ‹ɐśɐ‹ Šƒ‡Žɐř
ɐ ‘™ƒ”†ɐśɐ‘‡ɐƈ
ʴʴʴ†‡Ž’›–Š‘•ƃɐ ‘™ƒ”†ɐƄ
ʴʴʴ’›–Š‘•
ƇɐŠƒ’ƒɐśɐ ”ƒŠƒɐřɐއ‡•‡ɐśɐ ‘Аɐřɐ ‹ŽŽ‹ƒɐśɐ‡””›ɐř
ɐ †Ž‡ɐśɐ”‹ ɐřɐ ‘‡•ɐśɐ‡””›ɐřɐƒŽ‹ɐśɐ‹ Šƒ‡Žɐƈ

ǷȖȓțȟȈȍȔȥȓȍȔȍȕȚȗȖȒȓȦȟțȐțȌȈȓȧȍȔȍȋȖ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐSRS
В этой функции объединены функции ‰‡–ſƀ и †‡Ž. Если вы передадите функции
’‘’ſƀ ключ в качестве аргумента и такой ключ имеется в словаре, она вернет соот-
ветствующее значение и удалит пару. Если ключа в словаре нет, будет сгенериро-
вано исключение:
ʴʴʴއſ’›–Š‘•ƀ
6
ʴʴʴ’›–Š‘•Ŝ’‘’ſɐƒŽ‹ɐƀ
ɐ‹ Šƒ‡Žɐ
ʴʴʴއſ’›–Š‘•ƀ
ɬ
ʴʴʴ’›–Š‘•Ŝ’‘’ſɐƒŽ‹ɐƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
‡›””‘”śɐƒŽ‹ɐ

Но если вы передадите функции ’‘’ſƀ второй аргумент по умолчанию (как


и в случае с функцией ‰‡–ſƀ), словарь не изменится:
ʴʴʴ’›–Š‘•Ŝ’‘’ſɐ ‹”•–ɐřɐ —‰‘ɐƀ
ɐ —‰‘ɐ
ʴʴʴއſ’›–Š‘•ƀ
ɬ

ǻȌȈȓȧȍȔȊșȍȥȓȍȔȍȕȚȣșȗȖȔȖȡȤȦȜțȕȒȞȐȐFOHDU
Чтобы удалить все ключи и значения из словаря, вам следует использовать функцию
އƒ”ſƀ или просто переназначить заданному имени пустой словарь:
ʴʴʴ’›–Š‘•Ŝ އƒ”ſƀ
ʴʴʴ’›–Š‘•
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Ƈƈ
ʴʴʴ’›–Š‘•ʰƇƈ
ʴʴʴ’›–Š‘•
Ƈƈ

ǷȘȖȊȍȘȧȍȔȕȈȕȈȓȐȟȐȍȒȓȦȟȈșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈLQ
Если вы хотите узнать, содержится ли в словаре определенный ключ, используйте
ключевое слово in. Снова переопределим словарь pythons, но на этот раз пропустим
имена одного-двух участников:
ʴʴʴ’›–Š‘•ʰƇɐŠƒ’ƒɐśɐ ”ƒŠƒɐřɐއ‡•‡ɐśɐ ‘Аɐř
ŜŜŜɐ ‘‡•ɐśɐ‡””›ɐřɐƒŽ‹ɐśɐ‹ Šƒ‡Žɐřɐ †Ž‡ɐśɐ”‹ ɐƈ

Теперь проверим, кого мы добавили:


ʴʴʴɐŠƒ’ƒɐ‹’›–Š‘•
”—‡
ʴʴʴɐƒŽ‹ɐ‹’›–Š‘•
”—‡

На этот раз мы не забыли о Терри Гиллиаме?


ʴʴʴɐ ‹ŽŽ‹ƒɐ‹’›–Š‘•
ƒŽ•‡

Черт!

ǷȘȐșȊȈȐȊȈȍȔȏȕȈȟȍȕȐȧșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈ
Как и в случае со списками, если вы внесете в словарь изменение, оно отразится на
всех именах, которые на него ссылаются:
ʴʴʴ•‹‰ƒŽ•ʰƇɐ‰”‡‡ɐśɐ‰‘ɐř
ŜŜŜɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ŜŜŜɐ”‡†ɐśɐ•‹Ž‡ˆ‘”–Ї ƒ‡”ƒɐƈ
ʴʴʴ•ƒ˜‡ɏ•‹‰ƒŽ•ʰ•‹‰ƒŽ•
ʴʴʴ•‹‰ƒŽ•ƃɐ„Ž—‡ɐƄʰɐ ‘ˆ—•‡‡˜‡”›‘‡ɐ
ʴʴʴ•ƒ˜‡ɏ•‹‰ƒŽ•
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ɐ”‡†ɐśɐ•‹Ž‡ˆ‘”–Ї ƒ‡”ƒɐř
ɐ„Ž—‡ɐśɐ ‘ˆ—•‡‡˜‡”›‘‡ɐƈ

DzȖȗȐȘțȍȔȏȕȈȟȍȕȐȧșȗȖȔȖȡȤȦȜțȕȒȞȐȐFRS\
Чтобы скопировать ключи и значения из одного словаря в другой и запретить из-
меняться остальным словарям при изменении данных в одном из них, можно вос-
пользоваться функцией ‘’›ſƀ:
ʴʴʴ•‹‰ƒŽ•ʰƇɐ‰”‡‡ɐśɐ‰‘ɐř
ŜŜŜɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ŜŜŜɐ”‡†ɐśɐ•‹Ž‡ˆ‘”–Ї ƒ‡”ƒɐƈ
ʴʴʴ‘”‹‰‹ƒŽɏ•‹‰ƒŽ•ʰ•‹‰ƒŽ•Ŝ ‘’›ſƀ
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

ʴʴʴ•‹‰ƒŽ•ƃɐ„Ž—‡ɐƄʰɐ ‘ˆ—•‡‡˜‡”›‘‡ɐ
ʴʴʴ•‹‰ƒŽ•
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ɐ”‡†ɐśɐ•‹Ž‡ˆ‘”–Ї ƒ‡”ƒɐř
ɐ„Ž—‡ɐśɐ ‘ˆ—•‡‡˜‡”›‘‡ɐƈ
ʴʴʴ‘”‹‰‹ƒŽɏ•‹‰ƒŽ•
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ɐ”‡†ɐśɐ•‹Ž‡ˆ‘”–Ї ƒ‡”ƒɐƈ
ʴʴʴ

Эта копия является поверхностной: ее можно применять тогда, когда значения


словаря неизменяемы (как в нашем случае). Если значения словаря изменяются,
следует использовать функцию †‡‡’ ‘’›ſƀ.

DzȖȗȐȘțȍȔȊșȍșȗȖȔȖȡȤȦȜțȕȒȞȐȐGHHSFRS\ 
Если бы значением по ключу ”‡† в предыдущем примере был список, а не обычная
строка:
ʴʴʴ•‹‰ƒŽ•ʰƇɐ‰”‡‡ɐśɐ‰‘ɐř
ŜŜŜɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ŜŜŜɐ”‡†ɐśƃɐ•–‘’ɐřɐ•‹Ž‡ɐƄƈ
ʴʴʴ•‹‰ƒŽ•ɏ ‘’›ʰ•‹‰ƒŽ•Ŝ ‘’›ſƀ
ʴʴʴ•‹‰ƒŽ•
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ɐ”‡†ɐśƃɐ•–‘’ɐřɐ•‹Ž‡ɐƄƈ
ʴʴʴ•‹‰ƒŽ•ɏ ‘’›
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ɐ”‡†ɐśƃɐ•–‘’ɐřɐ•‹Ž‡ɐƄƈ
ʴʴʴ

Изменим одно из значений в списке ”‡†:


ʴʴʴ•‹‰ƒŽ•ƃɐ”‡†ɐƄƃɨƄʰɐ•™‡ƒ–ɐ
ʴʴʴ•‹‰ƒŽ•
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ɐ”‡†ɐśƃɐ•–‘’ɐřɐ•™‡ƒ–ɐƄƈ
ʴʴʴ•‹‰ƒŽ•ɏ ‘’›
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ɐ”‡†ɐśƃɐ•–‘’ɐřɐ•™‡ƒ–ɐƄƈ

Вы видите типичную картину, когда при внесении изменений в один объект из-
меняются оба объекта. Метод ‘’›ſƀ копировал значения как есть — это значит, что
•‹‰ƒŽɏ ‘’› получил тот же список значений для ɐ”‡†ɐ, которые имел и signals.
Решением проблемы является функция †‡‡’ ‘’›ſƀ:
ʴʴʴ‹’‘”– ‘’›
ʴʴʴ•‹‰ƒŽ•ʰƇɐ‰”‡‡ɐśɐ‰‘ɐř
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ŜŜŜɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ŜŜŜɐ”‡†ɐśƃɐ•–‘’ɐřɐ•‹Ž‡ɐƄƈ
ʴʴʴ•‹‰ƒŽ•ɏ ‘’›ʰ ‘’›Ŝ†‡‡’ ‘’›ſ•‹‰ƒŽ•ƀ
ʴʴʴ•‹‰ƒŽ•
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ɐ”‡†ɐśƃɐ•–‘’ɐřɐ•‹Ž‡ɐƄƈ
ʴʴʴ•‹‰ƒŽ•ɏ ‘’›
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
ɐ”‡†ɐśƃɐ•–‘’ɐřɐ•‹Ž‡ɐƄƈ
ʴʴʴ•‹‰ƒŽ•ƃɐ”‡†ɐƄƃɨƄʰɐ•™‡ƒ–ɐ
ʴʴʴ•‹‰ƒŽ•
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
”‡†ɐśƃɐ•–‘’ɐřɐ•™‡ƒ–ɐƄƈ
ʴʴʴ•‹‰ƒŽ•ɏ ‘’›
Ƈɐ‰”‡‡ɐśɐ‰‘ɐř
ɐ›‡ŽŽ‘™ɐśɐ‰‘ˆƒ•–‡”ɐř
”‡†ɐśƃɐ•–‘’ɐřɐ•‹Ž‡ɐƄƈ

ǹȘȈȊȕȐȊȈȍȔșȓȖȊȈȘȐ
Как и в случае со списками и кортежами, рассмотренными в предыдущей главе,
словари можно сравнивать с помощью операторов ʰʰ и Šʰ:
ʴʴʴƒʰƇɨśɨřɩśɩřɪśɪƈ
ʴʴʴ„ʰƇɪśɪřɨśɨřɩśɩƈ
ʴʴʴƒʰʰ„
”—‡
Другие операторы не будут работать:
ʴʴʴƒʰƇɨśɨřɩśɩřɪśɪƈ
ʴʴʴ„ʰƇɪśɪřɨśɨřɩśɩƈ
ʴʴʴƒʳʰ„
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
›’‡””‘”śɐʳʰɐ‘–•—’’‘”–‡†„‡–™‡‡‹•–ƒ ‡•‘ˆɐ†‹ –ɐƒ†ɐ†‹ –ɐ
Python сравнивает ключи и значения по одному. Порядок, в котором они создава-
лись, не имеет значения. В этом примере словари a и b равны, за исключением того,
что по ключу ɨ в словаре Ȕ находится список ƃɨř ɩƄ, а в словаре b — список ƃɨř ɨƄ.
ʴʴʴƒʰƇɨśƃɨřɩƄřɩśƃɨƄřɪśƃɨƄƈ
ʴʴʴ„ʰƇɨśƃɨřɨƄřɩśƃɨƄřɪśƃɨƄƈ
ʴʴʴƒʰʰ„
ƒŽ•‡

ǰȚȍȘȐȘțȍȔȗȖșȓȖȊȈȘȧȔșȗȖȔȖȡȤȦIRUȐLQ
Итерирование по словарю (или его функция ‡›•ſƀ) возвращает ключи. В этом
примере в качестве ключей используются типы карт для настольной игры Clue
(за пределами Северной Америки она называется Cluedo):
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

ʴʴʴƒ —•ƒ–‹‘ʰƇɐ”‘‘ɐśɐ„ƒŽŽ”‘‘ɐřɐ™‡ƒ’‘ɐśɐއƒ†’‹’‡ɐř
ŜŜŜɐ’‡”•‘ɐśɐ‘ŽŜ—•–ƒ”†ɐƈ
ʴʴʴˆ‘” ƒ”†‹ƒ —•ƒ–‹‘śɤȜȟȜˆ‘” ƒ”†‹ƒ —•ƒ–‹‘Ŝ‡›•ſƀś
ŜŜŜ’”‹–ſ ƒ”†ƀ
ŜŜŜ
”‘‘
weapon
person

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


функцию ˜ƒŽ—‡•ſƀ:
ʴʴʴˆ‘”˜ƒŽ—‡‹ƒ —•ƒ–‹‘Ŝ˜ƒŽ—‡•ſƀś
ŜŜŜ’”‹–ſ˜ƒŽ—‡ƀ
ŜŜŜ
„ƒŽŽ”‘‘
އƒ†’‹’‡
‘ŽŜ—•–ƒ”†
Для получения пар «ключ — значение» подходит функция ‹–‡•ſƀ:
ʴʴʴˆ‘”‹–‡‹ƒ —•ƒ–‹‘Ŝ‹–‡•ſƀś
ŜŜŜ’”‹–ſ‹–‡ƀ
ŜŜŜ
ſɐ”‘‘ɐřɐ„ƒŽŽ”‘‘ɐƀ
ſɐ™‡ƒ’‘ɐřɐއƒ†’‹’‡ɐƀ
ſɐ’‡”•‘ɐřɐ‘ŽŜ—•–ƒ”†ɐƀ
Присвоить значение кортежа другим переменным можно в один этап. Для каж-
дого кортежа, возвращенного функцией ‹–‡•ſƀ, присвоим первый элемент кортежа
(ключ) переменной ƒ”†, а второй элемент (значение) — переменной ‘–‡–•:
ʴʴʴˆ‘” ƒ”†ř ‘–‡–•‹ƒ —•ƒ–‹‘Ŝ‹–‡•ſƀś
ŜŜŜ’”‹–ſɐƒ”†ɐř ƒ”†řɐŠƒ•–Ї ‘–‡–•ɐř ‘–‡–•ƀ
ŜŜŜ
ƒ”†™‡ƒ’‘Šƒ•–Ї ‘–‡–•އƒ†’‹’‡
ƒ”†’‡”•‘Šƒ•–Ї ‘–‡–•‘ŽŜ—•–ƒ”†
ƒ”†”‘‘Šƒ•–Ї ‘–‡–•„ƒŽŽ”‘‘

ǪȒȓȦȟȍȕȐȧșȓȖȊȈȘȍȑ
У словарей также существуют включения.
Простейшая форма выглядит знакомо:
ƇȖȯȤȔȚșȡȜșȘȟȳȞȟȲȫȔśȖȯȤȔȚșȡȜșȘȟȳțȡȔȫșȡȜȳˆ‘”ȖȯȤȔȚșȡȜș‹ȜȦșȤȔȕșȟȰȡȯȝȢȕȮșȞȦƈ
ʴʴʴ™‘”†ʰɐއ––‡”•ɐ
ʴʴʴއ––‡”ɏ ‘—–•ʰƇއ––‡”ś™‘”†Ŝ ‘—–ſއ––‡”ƀˆ‘”އ––‡”‹™‘”†ƈ
ʴʴʴއ––‡”ɏ ‘—–•
ƇɐŽɐśɨřɐ‡ɐśɩřɐ–ɐśɩřɐ”ɐśɨřɐ•ɐśɨƈ

Мы проходим в цикле по каждой из семи букв строки ɐއ––‡”•ɐ и считаем, сколь-


ко раз буква встречается. Дважды использовать функцию ™‘”†Ŝ ‘—–ſއ––‡”ƀ —
значит впустую тратить время, поскольку нам придется по два раза посчитать
буквы e и t. Но это ничему не навредит, потому что после второго вызова этой
функции для буквы ș мы всего лишь заменим существующую запись в словаре.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

То же самое верно и для буквы t. Следующий фрагмент больше соответствует «пи-


тонскому» стилю:
ʴʴʴ™‘”†ʰɐއ––‡”•ɐ
ʴʴʴއ––‡”ɏ ‘—–•ʰƇއ––‡”ś™‘”†Ŝ ‘—–ſއ––‡”ƀˆ‘”އ––‡”‹•‡–ſ™‘”†ƀƈ
ʴʴʴއ––‡”ɏ ‘—–•
Ƈɐ–ɐśɩřɐŽɐśɨřɐ‡ɐśɩřɐ”ɐśɨřɐ•ɐśɨƈ

Порядок ключей словаря изменился по сравнению с предыдущим примером,


поскольку вызов •‡–ſ™‘”†ƀ возвращает буквы в другом порядке.
По аналогии со списковыми включениями для генератора словарей также можно
использовать условные проверки if и более одного блока for:
ƇȖȯȤȔȚșȡȜșȘȟȳȞȟȲȫȔśȖȯȤȔȚșȡȜșȘȟȳțȡȔȫșȡȜȳˆ‘”ȖȯȤȔȚșȡȜș‹ȜȦșȤȔȕșȟȰȡȯȝ
ȢȕȮșȞȦ‹ˆȧȥȟȢȖȜșƈ

ʴʴʴ˜‘™‡Ž•ʰɐƒ‡‹‘—ɐ
ʴʴʴ™‘”†ʰɐ‘‘ƒ–‘’‘‡‹ƒɐ
ʴʴʴ˜‘™‡Žɏ ‘—–•ʰƇއ––‡”ś™‘”†Ŝ ‘—–ſއ––‡”ƀˆ‘”އ––‡”‹•‡–ſ™‘”†ƀ
‹ˆއ––‡”‹˜‘™‡Ž•ƈ
ʴʴʴ˜‘™‡Žɏ ‘—–•
Ƈɐ‡ɐśɨřɐ‹ɐśɨřɐ‘ɐśɫřɐƒɐśɩƈ

Вы сможете найти дополнительные примеры использования генераторов слова-


рей в PEP-274 (KWWSVRUHLOO\XGNE).

ǴȕȖȎȍșȚȊȈ
Множество похоже на словарь, в котором значения отброшены, а оставлены только
ключи. Как и в словаре, ключи должны быть уникальными. Вы используете множе-
ство, если хотите знать только, существует что-то или нет, а другая информация вам
неважна. Это как сумка с ключами. Если же вам нужно прикрепить к ключу некую
информацию, воспользуйтесь словарем.
Было время, когда теорию множеств
преподавали в некоторых начальных
школах наряду с основами математи-
ки. Если в вашей школе такого не было
(или было, но вы в это время смотре-
ли в окно), на рис. 8.1 можно увидеть,
как объединяются и пересекаются мно-
жества.
Предположим, вы хотите объединить
два множества, у которых есть несколь-
ко общих ключей. Поскольку множество
должно содержать только уникальные
значения, объединение двух множеств
будет иметь всего лишь один такой оди-
наковый ключ. Пустое множество — это ǸȐșǶȉȣȟȕȣȍȖȗȍȘȈȞȐȐșȔȕȖȎȍșȚȊȈȔȐ
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

множество, содержащее ноль элементов. На рис. 8.1 примером пустого множества


будут женские имена, начинающиеся с буквы Х.

ǹȖȏȌȈȍȔȔȕȖȎȍșȚȊȖșȗȖȔȖȡȤȦȜțȕȒȞȐȐVHW
Чтобы создать множество, воспользуйтесь функцией •‡–ſƀ. Можно также разме-
стить в фигурных скобках одно или несколько разделенных запятыми значений,
как показано здесь:
ʴʴʴ‡’–›ɏ•‡–ʰ•‡–ſƀ
ʴʴʴ‡’–›ɏ•‡–
•‡–ſƀ
ʴʴʴ‡˜‡ɏ—„‡”•ʰƇɥřɩřɫřɭřɯƈ
ʴʴʴ‡˜‡ɏ—„‡”•
Ƈɥřɩřɫřɭřɯƈ
ʴʴʴ‘††ɏ—„‡”•ʰƇɨřɪřɬřɮřɰƈ
ʴʴʴ‘††ɏ—„‡”•
Ƈɨřɪřɬřɮřɰƈ

Порядок ключей в множестве не имеет значения.

ǷȖșȒȖȓȤȒțȗțșȚȣȍȒȊȈȌȘȈȚȕȣȍșȒȖȉȒȐ>@șȖȏȌȈȦȚȗțșȚȖȑșȗȐșȖȒȔȖȎȕȖȉȣȓȖȉȣ
ȗȘȍȌȗȖȓȖȎȐȚȤȟȚȖȗțșȚȣȍȜȐȋțȘȕȣȍșȒȖȉȒȐ^`șȖȏȌȈȦȚȗțșȚȖȍȔȕȖȎȍșȚȊȖǪȔȍșȚȖ
ȥȚȖȋȖȗțșȚȣȍȜȐȋțȘȕȣȍșȒȖȉȒȐșȖȏȌȈȦȚȗțșȚȖȑșȓȖȊȈȘȤǰȔȍȕȕȖȗȖȥȚȖȔțȐȕȚȍȘ
ȗȘȍȚȈȚȖȘȊȣȊȖȌȐȚȗțșȚȖȍȔȕȖȎȍșȚȊȖȒȈȒVHW ȊȔȍșȚȖ^`ǷȖȟȍȔțȚȈȒȗȘȖȐșȝȖȌȐȚ"
ǹȓȖȊȈȘȐȗȖȧȊȐȓȐșȤȊ3\WKRQȘȈȕȤȠȍȐțșȗȍȓȐȏȈȝȊȈȚȐȚȤȜȐȋțȘȕȣȍșȒȖȉȒȐȊșȊȖȍ
ȘȈșȗȖȘȧȎȍȕȐȍǨȊȓȈȌȍȕȐȍ²ȥȚȖȌȍȊȧȚȤȌȍșȧȚȣȝȏȈȒȖȕȕȖȋȖȗȘȈȊȈ

ǷȘȍȖȉȘȈȏțȍȔȌȘțȋȐȍȚȐȗȣȌȈȕȕȣȝ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐVHW
Вы можете создать множество из списка, строки, кортежа или словаря, отбрасывая
любые повторяющиеся значения.
Для начала взглянем на строку, в которой отдельные буквы встречаются не-
сколько раз:
ʴʴʴ•‡–ſɐއ––‡”•ɐƀ
ƇɐŽɐřɐ”ɐřɐ•ɐřɐ–ɐřɐ‡ɐƈ

Обратите внимание, что множество содержит только по одной e и t, хотя в слове


letters они встречаются дважды.
Создадим множество из списка:
ʴʴʴ•‡–ſƃɐƒ•Ї”ɐřɐƒ ‡”ɐřɐ”ƒ ‡”ɐřɐƒ•‘Ş‹š‘ɐƄƀ
Ƈɐƒ ‡”ɐřɐƒ•Ї”ɐřɐƒ•‘Ş‹š‘ɐřɐ”ƒ ‡”ɐƈ

А теперь из кортежа:
ʴʴʴ•‡–ſſɐƒ‰—ƒɐřɐ Š‘‡•ɐřɐ–‘ ‡ƒ”–‘–Ї”ɐƀƀ
Ƈɐƒ‰—ƒɐřɐ–‘ ‡ƒ”–‘–Ї”ɐřɐ Š‘‡•ɐƈ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Когда вы передаете функции •‡–ſƀ словарь, она возвращает только ключи:


ʴʴʴ•‡–ſƇɐƒ’’އɐśɐ”‡†ɐřɐ‘”ƒ‰‡ɐśɐ‘”ƒ‰‡ɐřɐ Ї””›ɐśɐ”‡†ɐƈƀ
Ƈɐ Ї””›ɐřɐ‘”ƒ‰‡ɐřɐƒ’’އɐƈ

ǷȖȓțȟȈȍȔȌȓȐȕțȔȕȖȎȍșȚȊȈșȗȖȔȖȡȤȦȜțȕȒȞȐȐOHQ
Пересчитаем наших оленей:
ʴʴʴ”‡‹†‡‡”ʰ•‡–ſƃɐƒ•Ї”ɐřɐƒ ‡”ɐřɐ”ƒ ‡”ɐřɐƒ•‘Ş‹š‘ɐƄƀ
ʴʴʴއſ”‡‹†‡‡”ƀ
ɫ

ǬȖȉȈȊȓȧȍȔȥȓȍȔȍȕȚșȗȖȔȖȡȤȦȜțȕȒȞȐȐDGG
Добавим во множество еще один элемент с помощью метода ƒ††ſƀ:
ʴʴʴ•ʰ•‡–ſſɨřɩřɪƀƀ
ʴʴʴ•
Ƈɨřɩřɪƈ
ʴʴʴ•Ŝƒ††ſɫƀ
ʴʴʴ•
Ƈɨřɩřɪřɫƈ

ǻȌȈȓȧȍȔȥȓȍȔȍȕȚșȗȖȔȖȡȤȦȜțȕȒȞȐȐUHPRYH
Вы можете удалить выбранное значение из множества:
ʴʴʴ•ʰ•‡–ſſɨřɩřɪƀƀ
ʴʴʴ•Ŝ”‡‘˜‡ſɪƀ
ʴʴʴ•
Ƈɨřɩƈ

ǰȚȍȘȐȘțȍȔȗȖȔȕȖȎȍșȚȊȈȔșȗȖȔȖȡȤȦIRUȐLQ
Как и в случае со словарями, вы можете проитерировать по всем элементам мно-
жества:
ʴʴʴˆ—”‹–—”‡ʰ•‡–ſſɐ•‘ˆƒɐřɐ‘––‘ƒɐřɐ–ƒ„އɐƀƀ
ʴʴʴˆ‘”’‹‡ ‡‹ˆ—”‹–—”‡ś
ŜŜŜ’”‹–ſ’‹‡ ‡ƀ
ŜŜŜ
‘––‘ƒ
table
sofa

ǷȘȖȊȍȘȧȍȔȕȈȕȈȓȐȟȐȍȏȕȈȟȍȕȐȧșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȈLQ
Такое использование множеств — самое распространенное. Мы создадим словарь,
который называется †”‹•. Каждый ключ будет названием коктейля, а соответству-
ющее значение — множеством с ингредиентами этого напитка:
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

ʴʴʴ†”‹•ʰƇ
ŜŜŜɐƒ”–‹‹ɐśƇɐ˜‘†ƒɐřɐ˜‡”‘—–Šɐƈř
ŜŜŜɐ„Žƒ ”—••‹ƒɐśƇɐ˜‘†ƒɐřɐƒŠŽ—ƒɐƈř
ŜŜŜɐ™Š‹–‡”—••‹ƒɐśƇɐ ”‡ƒɐřɐƒŠŽ—ƒɐřɐ˜‘†ƒɐƈř
ŜŜŜɐƒŠƒ––ƒɐśƇɐ”›‡ɐřɐ˜‡”‘—–Šɐřɐ„‹––‡”•ɐƈř
ŜŜŜɐ• ”‡™†”‹˜‡”ɐśƇɐ‘”ƒ‰‡Œ—‹ ‡ɐřɐ˜‘†ƒɐƈ
ŜŜŜƈ

Хотя и словарь, и множества заключаются в фигурные скобки (Ƈ и ƈ), множе-


ство — это всего лишь набор значений, а словарь содержит пары «ключ — значение».
Какой из коктейлей содержит водку?
ʴʴʴˆ‘”ƒ‡ř ‘–‡–•‹†”‹•Ŝ‹–‡•ſƀś
ŜŜŜ‹ˆɐ˜‘†ƒɐ‹ ‘–‡–•ś
ŜŜŜ’”‹–ſƒ‡ƀ
ŜŜŜ
• ”‡™†”‹˜‡”
ƒ”–‹‹
„Žƒ ”—••‹ƒ
™Š‹–‡”—••‹ƒ

Мы хотим выпить коктейль с водкой, но не переносим лактозу, а вермут на вкус


как керосин:
ʴʴʴˆ‘”ƒ‡ř ‘–‡–•‹†”‹•Ŝ‹–‡•ſƀś
ŜŜŜ‹ˆɐ˜‘†ƒɐ‹ ‘–‡–•ƒ†‘–ſɐ˜‡”‘—–Šɐ‹ ‘–‡–•‘”
ŜŜŜɐ ”‡ƒɐ‹ ‘–‡–•ƀś
ŜŜŜ’”‹–ſƒ‡ƀ
ŜŜŜ
• ”‡™†”‹˜‡”
„Žƒ ”—••‹ƒ

Перепишем этот пример чуть более кратко в следующем подразделе.

DzȖȔȉȐȕȈȞȐȐȐȖȗȍȘȈȚȖȘȣ
Что, если вам нужно проверить наличие сразу нескольких значений множества?
Предположим, вы хотите найти какой-нибудь напиток с апельсиновым соком или
вермутом. Для этого мы используем оператор пересечения множеств (ĺ):
ʴʴʴˆ‘”ƒ‡ř ‘–‡–•‹†”‹•Ŝ‹–‡•ſƀś
ŜŜŜ‹ˆ ‘–‡–•ĺƇɐ˜‡”‘—–Šɐřɐ‘”ƒ‰‡Œ—‹ ‡ɐƈś
ŜŜŜ’”‹–ſƒ‡ƀ
ŜŜŜ
• ”‡™†”‹˜‡”
ƒ”–‹‹
ƒŠƒ––ƒ

Результатом работы оператора ĺ является множество со всеми элементами из


обоих сравниваемых списков. Если ни один из заданных ингредиентов не содержит-
ся в предлагаемых коктейлях, оператор ĺ вернет пустое множество. Этот результат
можно считать равным ƒŽ•‡.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Теперь перепишем пример из предыдущего подраздела, когда мы хотели водки,


не смешанной со сливками или вермутом:
ʴʴʴˆ‘”ƒ‡ř ‘–‡–•‹†”‹•Ŝ‹–‡•ſƀś
ŜŜŜ‹ˆɐ˜‘†ƒɐ‹ ‘–‡–•ƒ†‘– ‘–‡–•ĺƇɐ˜‡”‘—–Šɐřɐ ”‡ƒɐƈś
ŜŜŜ’”‹–ſƒ‡ƀ
ŜŜŜ
• ”‡™†”‹˜‡”
„Žƒ ”—••‹ƒ

Сохраним множества ингредиентов для этих двух напитков в переменных, чтобы


не пришлось слишком много печатать в дальнейших примерах:
ʴʴʴ„”—••ʰ†”‹•ƃɐ„Žƒ ”—••‹ƒɐƄ
ʴʴʴ™”—••ʰ†”‹•ƃɐ™Š‹–‡”—••‹ƒɐƄ

Ниже приведены примеры всех операторов множеств. У одних есть специаль-


ная пунктуация, у других — специальные функции, у третьих — и то и другое. Мы
будем использовать тестовые множества Ȕ (содержит элементы ɨ и ɩ) и b (содержит
элементы ɩ и ɪ):
ʴʴʴƒʰƇɨřɩƈ
ʴʴʴ„ʰƇɩřɪƈ
Как вы видели ранее, пересечение (элементы, общие для обоих множеств) можно
получить с помощью особого пунктуационного символа ĺ. Функция ‹–‡”•‡ –‹‘ſƀ
делает то же самое:
ʴʴʴƒĺ„
Ƈɩƈ
ʴʴʴƒŜ‹–‡”•‡ –‹‘ſ„ƀ
Ƈɩƈ
В данном фрагменте используются сохраненные нами переменные:
ʴʴʴ„”—••ĺ™”—••
ƇɐƒŠŽ—ƒɐřɐ˜‘†ƒɐƈ
В следующем примере мы получаем объединение (члены обоих множеств), ис-
пользуя оператор Ŷ или функцию множества —‹‘ſƀ:
ʴʴʴƒŶ„
Ƈɨřɩřɪƈ
ʴʴʴƒŜ—‹‘ſ„ƀ
Ƈɨřɩřɪƈ
И алкогольная версия:
ʴʴʴ„”—••Ŷ™”—••
Ƈɐ ”‡ƒɐřɐƒŠŽ—ƒɐřɐ˜‘†ƒɐƈ
Разность множеств (члены только первого множества, но не второго) можно
получить с помощью символа — или функции †‹ˆˆ‡”‡ ‡ſƀ:
ʴʴʴƒŷ„
Ƈɨƈ
ʴʴʴƒŜ†‹ˆˆ‡”‡ ‡ſ„ƀ
Ƈɨƈ
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

ʴʴʴ„”—••ŷ™”—••
•‡–ſƀ
ʴʴʴ™”—••ŷ„”—••
Ƈɐ ”‡ƒɐƈ
Самыми распространенными операциями с множествами являются объединение,
пересечение и разность. Для полноты картины я включил в этот подраздел и осталь-
ные операции, но, возможно, вам никогда не придется их использовать.
Для выполнения исключающего ИЛИ (элементы или первого, или второго мно-
жества, но не общие) используйте оператор ɋ или функцию •›‡–”‹ ɏ†‹ˆˆ‡”‡ ‡ſƀ:
ʴʴʴƒɋ„
Ƈɨřɪƈ
ʴʴʴƒŜ•›‡–”‹ ɏ†‹ˆˆ‡”‡ ‡ſ„ƀ
Ƈɨřɪƈ
В этом примере определяется эксклюзивный ингредиент для русских напитков:
ʴʴʴ„”—••ɋ™”—••
Ƈɐ ”‡ƒɐƈ
Проверить, является ли одно множество подмножеством другого (когда все чле-
ны первого множества являются членами второго), можно с помощью оператора ʳʰ
или функции ‹••—„•‡–ſƀ:
ʴʴʴƒʳʰ„
ƒŽ•‡
ʴʴʴƒŜ‹••—„•‡–ſ„ƀ
ƒŽ•‡
Добавление сливок в коктейль «Черный русский» сделает его «Белым русским»,
поэтому wruss является подмножеством bruss:
ʴʴʴ„”—••ʳʰ™”—••
”—‡
Является ли любое множество подмножеством самого себя? Ага1.
ʴʴʴƒʳʰƒ
”—‡
ʴʴʴƒŜ‹••—„•‡–ſƒƀ
”—‡
Для того чтобы стать собственным подмножеством, второе множество должно
содержать все члены первого и несколько других. Определяется это с помощью
оператора ʳ, как показано в следующем примере:
ʴʴʴƒʳ„
ƒŽ•‡
ʴʴʴƒʳƒ
ƒŽ•‡

ʴʴʴ„”—••ʳ™”—••
”—‡

1
Однако, перефразируя Граучо Маркса, «я бы не хотел состоять в клубе, в который при-
нимают таких людей, как я».
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Надмножество противоположно подмножеству (все члены второго множества


являются также членами первого). Для определения этого используется оператор ʴʰ
или функция ‹••—’‡”•‡–ſƀ:
ʴʴʴƒʴʰ„
ƒŽ•‡
ʴʴʴƒŜ‹••—’‡”•‡–ſ„ƀ
ƒŽ•‡

ʴʴʴ™”—••ʴʰ„”—••
”—‡
Любое множество является надмножеством самого себя:
ʴʴʴƒʴʰƒ
”—‡
ʴʴʴƒŜ‹••—’‡”•‡–ſƒƀ
”—‡
И наконец, вы можете встретить правильное надмножество (первое множество
содержит все члены второго и несколько других) с помощью оператора ʴ, как по-
казано здесь:
ʴʴʴƒʴ„
ƒŽ•‡

ʴʴʴ™”—••ʴ„”—••
”—‡
Множество не может быть правильным надмножеством самого себя:
ʴʴʴƒʴƒ
ƒŽ•‡

ǪȒȓȦȟȍȕȐȍȔȕȖȎȍșȚȊȈ
Никто не хочет оставаться в стороне, поэтому даже у множеств есть включения.
Простейшая версия выглядит как включение списка или словаря, которые вы
только что видели:
ƇȖȯȤȔȚșȡȜșˆ‘”ȖȯȤȔȚșȡȜș‹ȜȦșȤȔȕșȟȰȡȯȝȢȕȮșȞȦƈ
Здесь также могут быть необязательные проверки условий:
ƇȖȯȤȔȚșȡȜșˆ‘”ȖȯȤȔȚșȡȜș‹ȜȦșȤȔȕșȟȰȡȯȝȢȕȮșȞȦ‹ˆȧȥȟȢȖȜșƈ

ʴʴʴƒɏ•‡–ʰƇ—„‡”ˆ‘”—„‡”‹”ƒ‰‡ſɨřɭƀ‹ˆ—„‡”ʩɪʰʰɨƈ
ʴʴʴƒɏ•‡–
Ƈɨřɫƈ

ǹȖȏȌȈȍȔȕȍȐȏȔȍȕȧȍȔȖȍȔȕȖȎȍșȚȊȖ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐIUR]HQVHW
Если вы хотите создать множество, которое нельзя будет изменить, вызовите функ-
цию ˆ”‘œ‡•‡–ſƀ, передав в нее любой итерабельный аргумент:
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

ʴʴʴˆ”‘œ‡•‡–ſƃɪřɩřɨƄƀ
ˆ”‘œ‡•‡–ſƇɨřɩřɪƈƀ
ʴʴʴˆ”‘œ‡•‡–ſ•‡–ſƃɩřɨřɪƄƀƀ
ˆ”‘œ‡•‡–ſƇɨřɩřɪƈƀ
ʴʴʴˆ”‘œ‡•‡–ſƇɪřɨřɩƈƀ
ˆ”‘œ‡•‡–ſƇɨřɩřɪƈƀ
ʴʴʴˆ”‘œ‡•‡–ſſɩřɪřɨƀƀ
ˆ”‘œ‡•‡–ſƇɨřɩřɪƈƀ

Достаточно ли «заморозилось» наше множество?


ʴʴʴˆ•ʰˆ”‘œ‡•‡–ſƃɪřɩřɨƄƀ
ʴʴʴˆ•
ˆ”‘œ‡•‡–ſƇɨřɩřɪƈƀ
ʴʴʴˆ•Ŝƒ††ſɫƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
––”‹„—–‡””‘”śɐˆ”‘œ‡•‡–ɐ‘„Œ‡ –Šƒ•‘ƒ––”‹„—–‡ɐƒ††ɐ

Да, множество хорошо «заморозилось».

ǹȚȘțȒȚțȘȣȌȈȕȕȣȝȒȖȚȖȘȣȍȔȣțȎȍȘȈșșȔȖȚȘȍȓȐ
Напомню, структуры данных создаются следующим образом:
‰список — с помощью квадратных скобок (ƃƄ);
‰кортеж — с помощью запятых (и опциональных скобок);
‰словарь и множество — с помощью фигурных скобок (Ƈƈ).
Во всех случаях, за исключением множеств, вы получаете доступ к отдельному
элементу с помощью квадратных скобок. Для списка и кортежа значение, находя-
щееся в квадратных скобках, является целочисленным смещением. Для словаря же
оно является ключом. Везде результатом будет значение. Для множества: значение
либо есть, либо нет; ключей и индексов нет.
ʴʴʴƒ”šɏŽ‹•–ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴƒ”šɏ–—’އʰɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐ
ʴʴʴƒ”šɏ†‹ –ʰƇɐ ”‘— Š‘ɐśɐ„ƒŒ‘ɐřɐŠ‹ ‘ɐśɐ’‹ƒ‘ɐřɐ ƒ”’‘ɐśɐŠƒ”’ɐƈ
ʴʴʴƒ”šɏ•‡–ʰƇɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƈ
ʴʴʴƒ”šɏŽ‹•–ƃɩƄ
ɐ ƒ”’‘ɐ
ʴʴʴƒ”šɏ–—’އƃɩƄ
ɐ ƒ”’‘ɐ
ʴʴʴƒ”šɏ†‹ –ƃɐ ƒ”’‘ɐƄ
ɐŠƒ”’ɐ
ʴʴʴɐ ƒ”’‘ɐ‹ƒ”šɏŽ‹•–
”—‡
ʴʴʴɐ ƒ”’‘ɐ‹ƒ”šɏ–—’އ
”—‡
ʴʴʴɐ ƒ”’‘ɐ‹ƒ”šɏ†‹ –
”—‡
ʴʴʴɐ ƒ”’‘ɐ‹ƒ”šɏ•‡–
”—‡
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǹȖȏȌȈȕȐȍȒȘțȗȕȣȝșȚȘțȒȚțȘȌȈȕȕȣȝ
Ранее мы работали с простыми булевыми значениями, числами и строками.
Теперь же мы работаем со списками, кортежами, множествами и словарями. Вы мо-
жете объединить эти встроенные структуры данных в свои более крупные и сложные
структуры. Начнем с трех разных списков:
ʴʴʴƒ”š‡•ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ
ʴʴʴ’›–Š‘•ʰƃɐŠƒ’ƒɐřɐއ‡•‡ɐřɐ ‹ŽŽ‹ƒɐřɐ ‘‡•ɐřɐƒŽ‹ɐƄ
ʴʴʴ•–‘‘‰‡•ʰƃɐ‘‡ɐřɐ—”Ž›ɐřɐƒ””›ɐƄ

Мы можем создать кортеж, элементами которого станут все эти списки:


ʴʴʴ–—’އɏ‘ˆɏŽ‹•–•ʰƒ”š‡•ř’›–Š‘•ř•–‘‘‰‡•
ʴʴʴ–—’އɏ‘ˆɏŽ‹•–•
ſƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄř
ƃɐŠƒ’ƒɐřɐއ‡•‡ɐřɐ ‹ŽŽ‹ƒɐřɐ ‘‡•ɐřɐƒŽ‹ɐƄř
ƃɐ‘‡ɐřɐ—”Ž›ɐřɐƒ””›ɐƄƀ

Можем также создать список, состоящий из трех списков:


ʴʴʴŽ‹•–ɏ‘ˆɏŽ‹•–•ʰƃƒ”š‡•ř’›–Š‘•ř•–‘‘‰‡•Ƅ
ʴʴʴŽ‹•–ɏ‘ˆɏŽ‹•–•
ƃƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄř
ƃɐŠƒ’ƒɐřɐއ‡•‡ɐřɐ ‹ŽŽ‹ƒɐřɐ ‘‡•ɐřɐƒŽ‹ɐƄř
ƃɐ‘‡ɐřɐ—”Ž›ɐřɐƒ””›ɐƄƄ

Словарь из списков также возможен. В этом примере используем название груп-


пы комиков в качестве ключа, а список ее участников — в качестве значения:
†‹ –ɏ‘ˆɏŽ‹•–•ʰƇɐƒ”š‡•ɐśƒ”š‡•řɐ›–Š‘•ɐś’›–Š‘•řɐ–‘‘‰‡•ɐś•–‘‘‰‡•ƈ
ʴʴ†‹ –ɏ‘ˆɏŽ‹•–•
Ƈɐƒ”š‡•ɐśƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄř
ɐ›–Š‘•ɐśƃɐŠƒ’ƒɐřɐއ‡•‡ɐřɐ ‹ŽŽ‹ƒɐřɐ ‘‡•ɐřɐƒŽ‹ɐƄř
ɐ–‘‘‰‡•ɐśƃɐ‘‡ɐřɐ—”Ž›ɐřɐƒ””›ɐƄƈ

Ваши единственные ограничения — только сами типы данных. Например, ключи


словаря должны быть неизменяемыми, поэтому списки, словари и множества не мо-
гут быть ключами для другого словаря. Но кортеж может быть. Создадим, к примеру,
алфавитный указатель достопримечательностей, основываясь на GPS-координатах
(широте, долготе и высоте). В главе 21 вы найдете еще несколько примеров работы
с картами:
ʴʴʴŠ‘—•‡•ʰƇ
ſɫɫŜɮɰřŞɰɪŜɨɫřɩɯɬƀśɐ› ‘—•‡ɐř
ſɪɯŜɯɰřŞɮɮŜɥɪřɨɪƀśɐЇŠ‹–‡ ‘—•‡ɐ
ƈ

ǿȐȚȈȑȚȍȌȈȓȍȍ
Мы вернемся к структурам кода. Покажем, как «завернуть» код в функцию и как
работать с исключениями, когда что-то идет не так.
ǫȓȈȊȈǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ  

ǻȗȘȈȎȕȍȕȐȧ
8.1. Создайте англо-французский словарь с названием ‡ɩˆ и выведите его на экран.
Вот ваши первые слова: †‘‰/ Š‹‡, ƒ–/ Šƒ– и walrus/‘”•‡.
8.2. Используя словарь ‡ɩˆ, выведите французский вариант слова walrus.
8.3. Создайте французско-английский словарь ˆɩ‡ на основе словаря ‡ɩˆ .
Используйте метод ‹–‡•.
8.4. Используя словарь ˆɩ‡, выведите английский вариант слова Š‹‡.
8.5. Выведите на экран множество английских слов из ключей словаря ‡ɩˆ.
8.6. Создайте многоуровневый словарь life. Используйте следующие строки для
ключей верхнего уровня: ɐƒ‹ƒŽ•ɐ, ɐ’Žƒ–•ɐ и ɐ‘–Ї”ɐ. Сделайте так, чтобы
ключ ɐƒ‹ƒŽ•ɐ ссылался на другой словарь, имеющий ключи ɐ ƒ–•ɐ, ɐ‘ –‘’‹ɐ
и ɐ‡—•ɐ. Сделайте так, чтобы ключ ɐ ƒ–•ɐ ссылался на список строк со значени-
ями ɐ ‡”‹ɐ, ɐ ”—’›ɐ и ɐ— ›ɐ. Остальные ключи должны ссылаться на пустые
словари.
8.7. Выведите на экран высокоуровневые ключи словаря life.
8.8. Выведите на экран ключи Ž‹ˆ‡ƃɐƒ‹ƒŽ•ɐƄ.
8.9. Выведите значения Ž‹ˆ‡ƃɐƒ‹ƒŽ•ɐƄƃɐ ƒ–•ɐƄ.
8.10. Используйте генератор словаря, чтобы создать словарь squares. Используйте
”ƒ‰‡ſɨɥƀ, чтобы получить ключи. В качестве значений используйте возведен-
ное в квадрат значение каждого ключа.
8.11. Используйте генератор множества, чтобы создать множество ‘†† из нечетных
чисел диапазона ”ƒ‰‡ſɨɥƀ.
8.12. Используйте включение генератора, чтобы вернуть строку ɐ ‘– ɐ и числа из
диапазона ”ƒ‰‡ſɨɥƀ. Итерируйте по этой конструкции с помощью цикла for.
8.13. Используйте функцию œ‹’ſƀ , чтобы создать словарь из кортежа ключей
(ɐ‘’–‹‹•–ɐ, ɐ’‡••‹‹•–ɐ, ɐ–”‘ŽŽɐ) и кортежа значений (ɐЇ glass is half ˆ—ŽŽɐ,
ɐЇ glass is half ‡’–›ɐ, ɐ ‘™ †‹† you get a ‰Žƒ••ţɐ).
8.14. Используйте функцию œ‹’ſƀ, чтобы создать словарь с именем ‘˜‹‡•, в котором
объединены списки titles ʰ ƃɐ”‡ƒ–—”‡ of ƒ„‹–ɐř ɐ”‡™‡Ž ƒ–‡ɐř ɐŠƒ”• 
a Žƒ‡ɐƄ и plots ʰ ƃɐ nun turns into a ‘•–‡”ɐř ɐ Šƒ—–‡† yarn •Š‘’ɐř ɐЇ 
your ‡š‹–•ɐƄ.
ƋƓƈƊƈ
ǼțȕȒȞȐȐ

Чем меньше функция, тем лучше управление.


Сирил Норткот Паркинсон

До этого момента все наши примеры кода были небольшими фрагментами. Они под-
ходят для решения небольших задач, но никому не хочется раз за разом эти фраг-
менты перепечатывать. Нужна какая-то форма преобразования большого кода в ряд
удобных в применении частей.
Первый шаг к повторному использованию кода — создание функций. Функция —
это именованный фрагмент кода, отделенный от других. Она может принимать
любое количество любых входных параметров и возвращать любое количество
любых результатов.
С функцией можно сделать две вещи:
‰определить ее, указав ноль или больше параметров;
‰вызвать ее и получить ноль или больше результатов.

ǶȗȘȍȌȍȓȧȍȔȜțȕȒȞȐȦ
șȗȖȔȖȡȤȦȒȓȦȟȍȊȖȋȖșȓȖȊȈGHI
Чтобы определить функцию, вам нужно написать †‡ˆ , имя функции, входные
параметры, заключенные в скобки, и, наконец, двоеточие (ś ). Имена функций
подчиняются тем же правилам, что и имена переменных (они должны начинаться
с буквы или символа подчеркивания и содержать только буквы, цифры или символ
подчеркивания).
Будем действовать пошагово. Сначала определим и вызовем функцию, которая
не имеет параметров. Перед вами пример простейшей функции:
ʴʴʴ†‡ˆ†‘ɏ‘–Š‹‰ſƀś
ŜŜŜ’ƒ••
Даже если функции не нужны параметры, вам все равно придется указать кру-
глые скобки и двоеточие в ее определении. Следующую строку необходимо вы-
делить пробелами точно так же, как если бы это был оператор if. Python требует
ǫȓȈȊȈǼțȕȒȞȐȐ  

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

ǪȣȏȣȊȈȍȔȜțȕȒȞȐȦșȗȖȔȖȡȤȦșȒȖȉȖȒ
Функцию можно вызвать, просто написав ее имя и скобки. Она сработает так, как
я и обещал, вполне успешно не сделав ничего:
ʴʴʴ†‘ɏ‘–Š‹‰ſƀ
ʴʴʴ
Теперь определим и вызовем другую функцию, которая не имеет параметров
и выводит на экран одно слово:
ʴʴʴ†‡ˆƒ‡ɏƒɏ•‘—†ſƀś
ŜŜŜ’”‹–ſɐ“—ƒ ɐƀ
ŜŜŜ
ʴʴʴƒ‡ɏƒɏ•‘—†ſƀ
“—ƒ 
Когда вы вызываете функцию ƒ‡ɏƒɏ•‘—†ſƀ, Python выполняет код, располо-
женный внутри ее описания. В этом случае он выводит одно слово и возвращает
управление основной программе.
Попробуем написать функцию, которая не имеет параметров, но возвращает
значение:
ʴʴʴ†‡ˆƒ‰”‡‡ſƀś
ŜŜŜ”‡–—””—‡
ŜŜŜ
Вы можете вызвать эту функцию и проверить значение, которое она вернула,
с помощью if:
ʴʴʴ‹ˆƒ‰”‡‡ſƀś
ŜŜŜ’”‹–ſɐ’އ†‹†Šɐƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɐŠƒ–™ƒ•—‡š’‡ –‡†Ŝɐƀ
ŜŜŜ
’އ†‹†Š
Только что вы шагнули далеко вперед. Комбинация функций с проверками вроде
if и циклами вроде while позволяет вам делать то, чего вы раньше не могли.

ǨȘȋțȔȍȕȚȣȐȗȈȘȈȔȍȚȘȣ
Пришло время поместить что-нибудь в эти скобки. Определим функцию ‡ Š‘ſƀ,
имеющую один параметр anything. Она использует оператор return, чтобы отпра-
вить значение anything вызывающей стороне дважды, разделив их пробелом:
ʴʴʴ†‡ˆ‡ Š‘ſƒ›–Š‹‰ƀś
ŜŜŜ”‡–—”ƒ›–Š‹‰ʫɐɐʫƒ›–Š‹‰
ŜŜŜ
ʴʴʴ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Теперь вызовем функцию ‡ Š‘ſƀ, передав ей строку ɐ—’އ•–‹Ž–•‹ɐ:


ʴʴʴ‡ Š‘ſɐ—’އ•–‹Ž–•‹ɐƀ
ɐ—’އ•–‹Ž–•‹—’އ•–‹Ž–•‹ɐ

Значения, которые вы передаете в функцию при вызове, называются аргумента-


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

ǬȘțȋȐȔȐ șȓȖȊȈȔȐ ȏȕȈȟȍȕȐȧ Ȋȕȍ ȜțȕȒȞȐȐ ȕȈȏȣȊȈȦȚșȧ ȈȘȋțȔȍȕȚȈȔȐ Ȉ ȏȕȈȟȍȕȐȧ


ȊȕțȚȘȐ²ȗȈȘȈȔȍȚȘȈȔȐ

В предыдущем примере функции ‡ Š‘ſƀ передавалась строка ɐ—’އ•–‹Ž–•‹ɐ.


Это значение копировалось внутри функции ‡ Š‘ſƀ в параметр anything, а затем
возвращалось (в этом случае оно удваивалось и разделялось пробелом) вызывающей
стороне.
Эти примеры функций довольно просты. А сейчас напишем функцию, которая
принимает аргумент и что-то с ним делает. Адаптируем предыдущий фрагмент кода,
который комментировал цвета. Назовем его ‘‡–ƒ”› и сделаем так, чтобы он при-
нимал в качестве аргумента строку ‘Ž‘”. Заставьте его вернуть описание строки
вызывающей стороне, которая может решить, что с ней делать дальше:
ʴʴʴ†‡ˆ ‘‡–ƒ”›ſ ‘Ž‘”ƀś
ŜŜŜ‹ˆ ‘Ž‘”ʰʰɐ”‡†ɐś
ŜŜŜ”‡–—”ɑ –ɐ•ƒ–‘ƒ–‘Ŝɑ
ŜŜŜ‡Ž‹ˆ ‘Ž‘”ʰʰɑ‰”‡‡ɑś
ŜŜŜ”‡–—”ɑ –ɐ•ƒ‰”‡‡’‡’’‡”Ŝɑ
ŜŜŜ‡Ž‹ˆ ‘Ž‘”ʰʰɐ„‡‡’—”’އɐś
ŜŜŜ”‡–—”ɑ †‘ɐ–‘™™Šƒ–‹–‹•ř„—–‘Ž›„‡‡• ƒ•‡‡‹–Ŝɑ
ŜŜŜ‡Ž•‡ś
ŜŜŜ”‡–—”ɑ ɐ˜‡‡˜‡”Їƒ”†‘ˆ–Ї ‘Ž‘”ɑʫ ‘Ž‘”ʫɑŜɑ
ŜŜŜ
ʴʴʴ

Вызовем функцию ‘‡–ƒ”›ſƀ , передав ей в качестве аргумента строку


ɐ„Ž—‡ɐ:
ʴʴʴ ‘‡–ʰ ‘‡–ƒ”›ſɐ„Ž—‡ɐƀ

Функция сделает следующее:


‰присвоит значение ɐ„Ž—‡ɐ параметру функции ‘Ž‘”;
‰пройдет по логической цепочке ‹ˆŞ‡Ž‹ˆŞ‡Ž•‡;
‰вернет строку.
Затем вызывающая сторона присвоит строку переменной ‘‡–.
Что мы получили в результате?
ʴʴʴ’”‹–ſ ‘‡–ƀ
ɐ˜‡‡˜‡”Їƒ”†‘ˆ–Ї ‘Ž‘”„Ž—‡Ŝ
ǫȓȈȊȈǼțȕȒȞȐȐ  

Функция может принимать любое количество аргументов (включая ноль) любого


типа. Она может возвращать любое количество результатов (также включая ноль)
любого типа. Если функция не вызывает return явно, вызывающая сторона получит
результат ‘‡:
ʴʴʴ’”‹–ſ†‘ɏ‘–Š‹‰ſƀƀ
‘‡

1RQH²ȥȚȖȗȖȓȍȏȕȖ
‘‡ — это специальное значение в Python, которое заполняет собой пустое место,
если функция ничего не возвращает. Оно не является булевым значением ƒŽ•‡, хоть
и похоже на него при проверке булевой переменной. Рассмотрим пример:
ʴʴʴ–Š‹‰ʰ‘‡
ʴʴʴ‹ˆ–Š‹‰ś
ŜŜŜ’”‹–ſɑ –ɐ••‘‡–Š‹‰ɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ –ɐ•‘–Š‹‰ɑƀ
ŜŜŜ
–ɐ•‘–Š‹‰
Чтобы отличить ‘‡ от булева значения ƒŽ•‡, используйте оператор is:
ʴʴʴ–Š‹‰ʰ‘‡
ʴʴʴ‹ˆ–Š‹‰‹•‘‡ś
ŜŜŜ’”‹–ſɑ –ɐ•‘–Š‹‰ɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ –ɐ••‘‡–Š‹‰ɑƀ
ŜŜŜ
–ɐ•‘–Š‹‰
Разница кажется небольшой, однако в Python она важна: ‘‡ потребуется вам,
чтобы различать отсутствующие значения и пустые. Помните, что целочисленные
нули, нули с плавающей точкой, пустые строки (ɐɐ), списки (ƃƄ), кортежи (ſřƀ),
словари (Ƈƈ) и множества (•‡–ſƀ) все равны ƒŽ•‡, но это не то же самое, что ‘‡.
Напишем небольшую функцию, которая выводит на экран, является ли ее аргу-
мент ‘‡, ”—‡ или ƒŽ•‡:
ʴʴʴ†‡ˆ™Šƒ–‹•ſ–Š‹‰ƀś
ŜŜŜ‹ˆ–Š‹‰‹•‘‡ś
ŜŜŜ’”‹–ſ–Š‹‰řɑ‹•‘‡ɑƀ
ŜŜŜ‡Ž‹ˆ–Š‹‰ś
ŜŜŜ’”‹–ſ–Š‹‰řɑ‹•”—‡ɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſ–Š‹‰řɑ‹• ƒŽ•‡ɑƀ
ŜŜŜ
Теперь выполним несколько проверок:
ʴʴʴ™Šƒ–‹•ſ‘‡ƀ
‘‡‹•‘‡
ʴʴʴ™Šƒ–‹•ſ”—‡ƀ
”—‡‹•”—‡
ʴʴʴ™Šƒ–‹•ſ ƒŽ•‡ƀ
ƒŽ•‡‹• ƒŽ•‡
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Как насчет реальных значений?


ʴʴʴ™Šƒ–‹•ſɥƀ
ɥ‹• ƒŽ•‡
ʴʴʴ™Šƒ–‹•ſɥŜɥƀ
ɥŜɥ‹• ƒŽ•‡
ʴʴʴ™Šƒ–‹•ſɐɐƀ
‹• ƒŽ•‡
ʴʴʴ™Šƒ–‹•ſɑɑƀ
‹• ƒŽ•‡
ʴʴʴ™Šƒ–‹•ſɐɐɐɐɐɐƀ
‹• ƒŽ•‡
ʴʴʴ™Šƒ–‹•ſſƀƀ
ſƀ‹• ƒlse
ʴʴʴ™Šƒ–‹•ſƃƄƀ
ƃƄ‹• ƒŽ•‡
ʴʴʴ™Šƒ–‹•ſƇƈƀ
Ƈƈ‹• ƒlse
ʴʴʴ™Šƒ–‹•ſ•‡–ſƀƀ
•‡–ſƀ‹• ƒŽ•‡

ʴʴʴ™Šƒ–‹•ſɥŜɥɥɥɥɨƀ
ɨ‡Şɥɬ‹•”—‡
ʴʴʴ™Šƒ–‹•ſƃɥƄƀ
ƃɥƄ‹•”—‡
ʴʴʴ™Šƒ–‹•ſƃɐɐƄƀ
ƃɐɐƄ‹•”—‡
ʴʴʴ™Šƒ–‹•ſɐɐƀ
‹•”—‡

ǷȖȏȐȞȐȖȕȕȣȍȈȘȋțȔȍȕȚȣ
Python довольно гибко обрабатывает аргументы функций в сравнении со мно-
гими другими языками. Наиболее распространенный тип аргументов — это по-
зиционные аргументы, чьи значения копируются в соответствующие параметры
по порядку.
Эта функция создает словарь из позиционных входных аргументов и возвра-
щает его:
ʴʴʴ†‡ˆ‡—ſ™‹‡ř‡–”‡‡ř†‡••‡”–ƀś
ŜŜŜ”‡–—”Ƈɐ™‹‡ɐś™‹‡řɐ‡–”‡‡ɐś‡–”‡‡řɐ†‡••‡”–ɐś†‡••‡”–ƈ
ŜŜŜ
ʴʴʴ‡—ſɐ Šƒ”†‘ƒ›ɐřɐ Š‹ ‡ɐřɐ ƒ‡ɐƀ
Ƈɐ™‹‡ɐśɐ Šƒ”†‘ƒ›ɐřɐ‡–”‡‡ɐśɐ Š‹ ‡ɐřɐ†‡••‡”–ɐśɐ ƒ‡ɐƈ

Несмотря на распространенность аргументов такого типа, у них есть недостаток:


вам нужно запоминать значение каждой позиции. Если бы мы вызвали функцию
‡—ſƀ, передав в качестве последнего аргумента марку вина, обед вышел бы со-
вершенно другим:
ʴʴʴ‡—ſɐ„‡‡ˆɐřɐ„ƒ‰‡Žɐřɐ„‘”†‡ƒ—šɐƀ
Ƈɐ†‡••‡”–ɐśɐ„‘”†‡ƒ—šɐřɐ™‹‡ɐśɐ„‡‡ˆɐřɐ‡–”‡‡ɐśɐ„ƒ‰‡Žɐƈ
ǫȓȈȊȈǼțȕȒȞȐȐ  

ǨȘȋțȔȍȕȚȣ²ȒȓȦȟȍȊȣȍșȓȖȊȈ
Для того чтобы избежать путаницы с позиционными аргументами, вы можете ука-
зать аргументы с помощью имен соответствующих параметров. Порядок следования
аргументов в этом случае может быть иным:
ʴʴʴ‡—ſ‡–”‡‡ʰɐ„‡‡ˆɐř†‡••‡”–ʰɐ„ƒ‰‡Žɐř™‹‡ʰɐ„‘”†‡ƒ—šɐƀ
Ƈɐ†‡••‡”–ɐśɐ„ƒ‰‡Žɐřɐ™‹‡ɐśɐ„‘”†‡ƒ—šɐřɐ‡–”‡‡ɐśɐ„‡‡ˆɐƈ

Можно объединять позиционные аргументы и аргументы — ключевые слова.


Сначала выберем вино, а для десерта и основного блюда используем аргументы —
ключевые слова.
ʴʴʴ‡—ſɐˆ”‘–‡ƒ ɐř†‡••‡”–ʰɐˆŽƒɐř‡–”‡‡ʰɐˆ‹•Šɐƀ
Ƈɐ‡–”‡‡ɐśɐˆ‹•Šɐřɐ†‡••‡”–ɐśɐˆŽƒɐřɐ™‹‡ɐśɐˆ”‘–‡ƒ ɐƈ

Если вы вызываете функцию, имеющую как позиционные аргументы, так и ар-


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

ǻȒȈȏȣȊȈȍȔȏȕȈȟȍȕȐȍȗȈȘȈȔȍȚȘȈȗȖțȔȖȓȟȈȕȐȦ
Вы можете указать для параметров значения по умолчанию. Значения по умолчанию
используются в том случае, если вызывающая сторона не предоставила соответ-
ствующий аргумент. Это стандартное действие оказывается достаточно полезным.
Обратимся к предыдущему примеру:
ʴʴʴ†‡ˆ‡—ſ™‹‡ř‡–”‡‡ř†‡••‡”–ʰɐ’—††‹‰ɐƀś
ŜŜŜ”‡–—”Ƈɐ™‹‡ɐś™‹‡řɐ‡–”‡‡ɐś‡–”‡‡řɐ†‡••‡”–ɐś†‡••‡”–ƈ

В этот раз мы вызовем функцию ‡—ſƀ, не передав ей аргумент †‡••‡”–:


ʴʴʴ‡—ſɐ Šƒ”†‘ƒ›ɐřɐ Š‹ ‡ɐƀ
Ƈɐ™‹‡ɐśɐ Šƒ”†‘ƒ›ɐřɐ‡–”‡‡ɐśɐ Š‹ ‡ɐřɐ†‡••‡”–ɐśɐ’—††‹‰ɐƈ

Если вы предоставите аргумент, он будет использован вместо аргумента по


умолчанию:
ʴʴʴ‡—ſɐ†—‡Žˆ‡Ž†‡”ɐřɐ†— ɐřɐ†‘—‰Š—–ɐƀ
Ƈɐ™‹‡ɐśɐ†—‡Žˆ‡Ž†‡”ɐřɐ‡–”‡‡ɐśɐ†— ɐřɐ†‡••‡”–ɐśɐ†‘—‰Š—–ɐƈ

ǯȕȈȟȍȕȐȍȗȈȘȈȔȍȚȘȖȊȗȖțȔȖȓȟȈȕȐȦȊȣșȟȐȚȣȊȈȍȚșȧȒȖȋȌȈȜțȕȒȞȐȧȖȗȘȍȌȍȓȧȍȚșȧ
Ȉ ȕȍ ȊȣȗȖȓȕȧȍȚșȧ ǸȈșȗȘȖșȚȘȈȕȍȕȕȖȑ ȖȠȐȉȒȖȑ ȕȖȊȐȟȒȖȊ Ȉ ȐȕȖȋȌȈ Ȑ ȕȍ șȖȊșȍȔ
ȕȖȊȐȟȒȖȊ  ȧȊȓȧȍȚșȧ ȐșȗȖȓȤȏȖȊȈȕȐȍ ȐȏȔȍȕȧȍȔȖȋȖ ȚȐȗȈ ȌȈȕȕȣȝ ȚȈȒȐȝ ȒȈȒ șȗȐșȖȒ
ȐȓȐșȓȖȊȈȘȤȊȒȈȟȍșȚȊȍȗȈȘȈȔȍȚȘȈȗȖțȔȖȓȟȈȕȐȦ

В следующей проверке функция „—‰‰›ſƀ каждый раз должна запускаться с новым


пустым списком result, добавлять в него аргумент arg, а затем выводить на экран
список, состоящий из одного элемента. Однако в этой функции есть баг: список пуст
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

только при первом вызове. Во второй раз список result будет содержать элемент,
оставшийся после предыдущего вызова:
ʴʴʴ†‡ˆ„—‰‰›ſƒ”‰ř”‡•—Ž–ʰƃƄƀś
ŜŜŜ”‡•—Ž–Ŝƒ’’‡†ſƒ”‰ƀ
ŜŜŜ’”‹–ſ”‡•—Ž–ƀ
ŜŜŜ
ʴʴʴ„—‰‰›ſɐƒɐƀ
ƃɐƒɐƄ
ʴʴʴ„—‰‰›ſɐ„ɐƀɤȢȚȜȘȔșȠȧȖȜȘșȦȰƃɐ„ɐƄ
ƃɐƒɐřɐ„ɐƄ

Функция работала бы корректно, если бы код выглядел так:


ʴʴʴ†‡ˆ™‘”•ſƒ”‰ƀś
ŜŜŜ”‡•—Ž–ʰƃƄ
ŜŜŜ”‡•—Ž–Ŝƒ’’‡†ſƒ”‰ƀ
ŜŜŜ”‡–—””‡•—Ž–
ŜŜŜ
ʴʴʴ™‘”•ſɐƒɐƀ
ƃɐƒɐƄ
ʴʴʴ™‘”•ſɐ„ɐƀ
ƃɐ„ɐƄ

Решить проблему можно, передав в функцию что-либо еще, указывающее на то,


что вызов является первым:
ʴʴʴ†‡ˆ‘„—‰‰›ſƒ”‰ř”‡•—Ž–ʰ‘‡ƀś
ŜŜŜ‹ˆ”‡•—Ž–‹•‘‡ś
ŜŜŜ”‡•—Ž–ʰƃƄ
ŜŜŜ”‡•—Ž–Ŝƒ’’‡†ſƒ”‰ƀ
ŜŜŜ’”‹–ſ”‡•—Ž–ƀ
ŜŜŜ
ʴʴʴ‘„—‰‰›ſɐƒɐƀ
ƃɐƒɐƄ
ʴʴʴ‘„—‰‰›ſɐ„ɐƀ
ƃɐ„ɐƄ

Иногда этот вопрос задают на собеседованиях, связанных с Python. Теперь вы


предупреждены.

ǷȖȓțȟȈȍȔȘȈȏȉȐȊȈȍȔȈȘȋțȔȍȕȚȣ²ȒȓȦȟȍȊȣȍșȓȖȊȈ
șȗȖȔȖȡȤȦșȐȔȊȖȓȈ
Если вы работали с языками программирования C или C++, то можете предположить,
что астериск (*) в Python имеет какое-то отношение к указателям. Нет, у Python нет
указателей.
Если символ * будет использован внутри функции с параметром, произвольное
количество позиционных аргументов сгруппируется в один кортеж. В следующем
примере args является кортежем параметров, который был создан из нуля или более
аргументов, переданных в функцию ’”‹–ɏƒ”‰•ſƀ:
ǫȓȈȊȈǼțȕȒȞȐȐ  

ʴʴʴ†‡ˆ’”‹–ɏƒ”‰•ſƋƒ”‰•ƀś
ŜŜŜ’”‹–ſɐ‘•‹–‹‘ƒŽƒ”‰—‡––—’އśɐřƒ”‰•ƀ
ŜŜŜ

Если вы вызовете функцию без аргументов, то получите пустой кортеж:


ʴʴʴ’”‹–ɏƒ”‰•ſƀ
‘•‹–‹‘ƒŽƒ”‰—‡––—’އśſƀ

Все аргументы, которые вы передадите, будут выведены на экран как кортеж args:
ʴʴʴ’”‹–ɏƒ”‰•ſɪřɩřɨřɐ™ƒ‹–Šɐřɐ—ŠŜŜŜɐƀ
‘•‹–‹‘ƒŽƒ”‰—‡––—’އśſɪřɩřɨřɐ™ƒ‹–Šɐřɐ—ŠŜŜŜɐƀ

Это удобно при написании таких функций, как ’”‹–ſƀ, которые принимают
произвольное количество аргументов. Если в вашей функции имеются также обяза-
тельные позиционные аргументы, поместите их в начало — *args отправится в конец
списка и получит все остальные аргументы:
ʴʴʴ†‡ˆ’”‹–ɏ‘”‡ſ”‡“—‹”‡†ɨř”‡“—‹”‡†ɩřƋƒ”‰•ƀś
ŜŜŜ’”‹–ſɐ‡‡†–Š‹•‘‡śɐř”‡“—‹”‡†ɨƀ
ŜŜŜ’”‹–ſɐ‡‡†–Š‹•‘‡–‘‘śɐř”‡“—‹”‡†ɩƀ
ŜŜŜ’”‹–ſɐŽŽ–Ї”‡•–śɐřƒ”‰•ƀ
ŜŜŜ
ʴʴʴ’”‹–ɏ‘”‡ſɐ ƒ’ɐřɐ‰Ž‘˜‡•ɐřɐ• ƒ”ˆɐřɐ‘‘ އɐřɐ—•–ƒ Ї™ƒšɐƀ
‡‡†–Š‹•‘‡ś ƒ’
‡‡†–Š‹•‘‡–‘‘ś‰Ž‘˜‡•
ŽŽ–Ї”‡•–śſɐ• ƒ”ˆɐřɐ‘‘ އɐřɐ—•–ƒ Ї™ƒšɐƀ

ǷȘȐȐșȗȖȓȤȏȖȊȈȕȐȐ ȊȈȔȕȍȕțȎȕȖȖȉȧȏȈȚȍȓȤȕȖȕȈȏȣȊȈȚȤȒȖȘȚȍȎȈȘȋțȔȍȕȚȖȊDUJV
ȖȌȕȈȒȖȥȚȖȘȈșȗȘȖșȚȘȈȕȍȕȕȈȧȐȌȐȖȔȈȊ3\WKRQǺȈȒȎȍȟȈșȚȖȊȕțȚȘȐȜțȕȒȞȐȐȐș
ȗȖȓȤȏțȍȚșȧȒȖȕșȚȘțȒȞȐȧ DUJVȒȈȒȥȚȖȗȖȒȈȏȈȕȖȊȗȘȍȌȣȌțȡȍȔȗȘȐȔȍȘȍȕȍșȔȖȚȘȧ
ȕȈȚȖȟȚȖȚȍȝȕȐȟȍșȒȐȖȕȈȧȊȓȧȍȚșȧȗȈȘȈȔȍȚȘȖȔȐȌȖȓȎȕȈȕȈȏȣȊȈȚȤșȧ SDUDPV

Подведем итоги.
‰Можно передавать позиционный аргумент в функцию, которая соотнесет его
с позиционным параметром. Подобные примеры вы уже видели в этой книге.
‰Можно передать в функцию кортеж, и внутри он также останется кортежем.
Это более простой вариант предыдущей ситуации.
‰Можно передать позиционные аргументы в функцию и объединить их в пара-
метр *args, который будет развернут в кортеж args. Эту ситуацию мы описали
в текущем подразделе.
‰Можно «разбить» кортеж с именем args на позиционные параметры *args внутри
функции, которые затем будут пересобраны в кортеж-параметр args:
ʴʴʴ’”‹–ɏƒ”‰•ſɩřɬřɮřɐšɐƀ
‘•‹–‹‘ƒŽ–—’އśſɩřɬřɮřɐšɐƀ
ʴʴʴƒ”‰•ʰſɩřɬřɮřɐšɐƀ
ʴʴʴ’”‹–ɏƒ”‰•ſƒ”‰•ƀ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

‘•‹–‹‘ƒŽ–—’އśſſɩřɬřɮřɐšɐƀřƀ
ʴʴʴ’”‹–ɏƒ”‰•ſƋƒ”‰•ƀ
‘•‹–‹‘ƒŽ–—’އśſɩřɬřɮřɐšɐƀ

Символ * можно использовать только при описании функции и ее вызове:


ʴʴʴƋƒ”‰•
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨ
›–ƒš””‘”ś ƒɐ–—•‡•–ƒ””‡†‡š’”‡••‹‘Ї”‡

Итак:
‰находясь за пределами функции, *args разбивает кортеж args на разделенные
запятыми позиционные параметры;
‰будучи внутри функции, *args собирает все позиционные аргументы в единый
кортеж args. Вы можете использовать имена Ƌ’ƒ”ƒ• и ’ƒ”ƒ•, но чаще всего имя
*args используется как для аргументов, так и для параметров.
Читатели, обладающие синестезией, могут неявно услышать, что *args произ-
носится как выдох-args снаружи и вдох-args изнутри.

ǷȖȓțȟȈȍȔȘȈȏȉȐȊȈȍȔȈȘȋțȔȍȕȚȣ²ȒȓȦȟȍȊȣȍșȓȖȊȈ
șȗȖȔȖȡȤȦșȐȔȊȖȓȖȊ
Вы можете использовать два астериска (**), чтобы сгруппировать аргументы — клю-
чевые слова в словарь, где имена аргументов станут ключами, а их значения — соот-
ветствующими значениями в словаре. В следующем примере определяется функция
’”‹–ɏ™ƒ”‰•ſƀ, в которой выводятся ее аргументы — ключевые слова:
ʴʴʴ†‡ˆ’”‹–ɏ™ƒ”‰•ſƋƋ™ƒ”‰•ƀś
ŜŜŜ’”‹–ſɐ‡›™‘”†ƒ”‰—‡–•śɐř™ƒ”‰•ƀ
ŜŜŜ

Теперь попробуйте вызвать ее, передав несколько аргументов:


ʴʴʴ’”‹–ɏ™ƒ”‰•ſƀ
‡›™‘”†ƒ”‰—‡–•śƇƈ
ʴʴʴ’”‹–ɏ™ƒ”‰•ſ™‹‡ʰɐ‡”Ž‘–ɐř‡–”‡‡ʰɐ—––‘ɐř†‡••‡”–ʰɐƒ ƒ”‘‘ɐƀ
‡›™‘”†ƒ”‰—‡–•śƇɐ†‡••‡”–ɐśɐƒ ƒ”‘‘ɐřɐ™‹‡ɐśɐ‡”Ž‘–ɐřɐ‡–”‡‡ɐśɐ—––‘ɐƈ

Внутри функции ™ƒ”‰• является параметром-словарем.


Порядок аргументов будет следующим:
‰обязательные позиционные аргументы;
‰необязательные позиционные аргументы (*args);
‰необязательные аргументы — ключевые слова (ƋƋ™ƒ”‰•).
Как и в случае с args, вам не обязательно называть этот аргумент ™ƒ”‰•, однако
такова распространенная практика1.

1
Имена Args и Kwargs очень хорошо подошли бы пиратским попугаям.
ǫȓȈȊȈǼțȕȒȞȐȐ  

Синтаксис ** можно применять только при вызове функции или ее опреде-


лении1:
ʴʴʴƋƋ™’ƒ”ƒ•
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨ
ƋƋ™’ƒ”ƒ•
ɋ
›–ƒš””‘”ś‹˜ƒŽ‹†•›–ƒš

Подведем итоги:
‰вы можете передавать аргументы в функцию по ключевым словам — они будут
соотнесены с параметрами. Вы уже видели этот подход на практике;
‰вы можете передать в функцию словарь — внутри он также будет представлять
собой словарь с параметрами. Это частный случай предыдущей ситуации;
‰вы можете передать в функцию один или несколько аргументов по ключевым
словам (в формате ȜȠȳʰțȡȔȫșȡȜș ) и собрать их внутри в виде конструкции
ƋƋ™ƒ”‰•, которая будет преобразована в параметр-словарь с именем ™ƒ”‰•.
Такую ситуацию мы рассмотрели в этом подразделе;
‰находясь за пределами функции, ƋƋ™ƒ”‰• разбивает словарь ™ƒ”‰• на аргумен-
ты в формате ȜȠȳʰțȡȔȫșȡȜș;
‰находясь внутри функции, ƋƋ™ƒ”‰• собирает аргументы в формате ȜȠȳʰțȡȔȫșȡȜș
в словарь с именем ™ƒ”‰•.
Если вам помогает аналогия со слуховыми образами, представьте, что при раз-
биении аргументов для каждой звездочки делается выдох, а при их сборе — вдох.

ǨȘȋțȔȍȕȚȣȗȍȘȍȌȈȊȈȍȔȣȍȚȖȓȤȒȖ
ȗȖȒȓȦȟȍȊȣȔșȓȖȊȈȔ
В функцию можно передать аргумент — ключевое слово с тем же самым именем, что
и у позиционного параметра. Однако, скорее всего, это приведет не к тому результату,
который вы ожидаете. Python 3 позволяет указывать аргументы, которые передают-
ся только по ключевым словам. Соответственно названию их нужно предоставлять
в формате ȜȠȳʰțȡȔȫșȡȜș, а не позиционно, как значение. Знак * в определении функ-
ции говорит о том, что параметры start и ‡† нужно предоставлять как именованные
аргументы, если мы не хотим использовать их значения по умолчанию:
ʴʴʴ†‡ˆ’”‹–ɏ†ƒ–ƒſ†ƒ–ƒřƋř•–ƒ”–ʰɥř‡†ʰɨɥɥƀś
ŜŜŜˆ‘”˜ƒŽ—‡‹ſ†ƒ–ƒƃ•–ƒ”–ś‡†Ƅƀś
ŜŜŜ’”‹–ſ˜ƒŽ—‡ƀ
ŜŜŜ
ʴʴʴ†ƒ–ƒʰƃɐƒɐřɐ„ɐřɐ ɐřɐ†ɐřɐ‡ɐřɐˆɐƄ
ʴʴʴ’”‹–ɏ†ƒ–ƒſ†ƒ–ƒƀ
a

1
А также, начиная с версии Python 3.5, при объединении словарей с помощью конструкции
{**a, **b}, которую вы видели в главе 8.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

†
e
f
ʴʴʴ’”‹–ɏ†ƒ–ƒſ†ƒ–ƒř•–ƒ”–ʰɫƀ
e
f
ʴʴʴ’”‹–ɏ†ƒ–ƒſ†ƒ–ƒř‡†ʰɩƀ
a
b

ǰȏȔȍȕȧȍȔȣȍȐȕȍȐȏȔȍȕȧȍȔȣȍȈȘȋțȔȍȕȚȣ
Вы не забыли, что, если присвоить один список двум переменным, вы сможете из-
менить его, используя любую из этих переменных? И что это не сработает, если
обе переменные ссылаются, например, на целое число или строку? Это происходит
потому, что список является изменяемым, а строка и целое число — нет. Вам нужно
помнить про эту особенность при передаче аргументов в функцию. Если аргумент
изменяемый, то его значение можно изменить изнутри функции с помощью соот-
ветствующего параметра1:
ʴʴʴ‘—–•‹†‡ʰƃɐ‘‡ɐřɐˆ‹‡ɐřɐ†ƒ›ɐƄ
ʴʴʴ†‡ˆƒ‰Ž‡ſƒ”‰ƀś
ŜŜŜƒ”‰ƃɨƄʰɐ–‡””‹„އŠɐ
ŜŜŜ
ʴʴʴ‘—–•‹†‡
ƃɐ‘‡ɐřɐˆ‹‡ɐřɐ†ƒ›ɐƄ
ʴʴʴƒ‰Ž‡ſ‘—–•‹†‡ƀ
ʴʴʴ‘—–•‹†‡
ƃɐ‘‡ɐřɐ–‡””‹„އŠɐřɐ†ƒ›ɐƄ

Хорошим тоном считается умение избегать подобных ситуаций2. Любой до-


кумент, являющийся аргументом, может измениться или вернуть новое значение.

ǹȚȘȖȒȐȌȖȒțȔȍȕȚȈȞȐȐ
В Python удобочитаемость имеет значение. Вы можете прикрепить документацию
к определению функции, включив в начало ее тела строку, которая и называется
строкой документации:
ʴʴʴ†‡ˆ‡ Š‘ſƒ›–Š‹‰ƀś
ŜŜŜɐ‡ Š‘”‡–—”•‹–•‹’—–ƒ”‰—‡–ɐ
ŜŜŜ”‡–—”ƒ›–Š‹‰

1
Как в подростковых фильмах ужасов, когда герои узнают: «Звонок идет изнутри дома!»
2
Как в старом врачебном анекдоте: «Мне больно, когда я делаю вот так». — «Значит, боль-
ше так не делайте».
ǫȓȈȊȈǼțȕȒȞȐȐ  

Вы можете сделать строку документации довольно длинной и даже применить


к ней, если хотите, форматирование. Это показано в следующем примере:
†‡ˆ’”‹–ɏ‹ˆɏ–”—‡ſ–Š‹‰ř Ї ƀś
ɐɐɐ
”‹–•–Їˆ‹”•–ƒ”‰—‡–‹ˆƒ•‡ ‘†ƒ”‰—‡–‹•–”—‡Ŝ
Ї‘’‡”ƒ–‹‘‹•ś
ɨŜЇ ™Š‡–Ї”–ЇƋ•‡ ‘†Ƌƒ”‰—‡–‹•–”—‡Ŝ
ɩŜ ˆ‹–‹•ř’”‹––ЇƋˆ‹”•–Ƌƒ”‰—‡–Ŝ
ɐɐɐ
‹ˆ Ї ś
’”‹–ſ–Š‹‰ƀ

Для вывода строки документации функции вызовите функцию Їޒſƀ. Передайте


ей имя функции, чтобы получить список всех аргументов и красиво отформатиро-
ванную строку документации:
ʴʴʴЇޒſ‡ Š‘ƀ
‡Ž’‘ˆ— –‹‘‡ Š‘‹‘†—އɏɏƒ‹ɏɏś

‡ Š‘ſƒ›–Š‹‰ƀ
‡ Š‘”‡–—”•‹–•‹’—–ƒ”‰—‡–

Если хотите увидеть только строку документации без форматирования:


ʴʴʴ’”‹–ſ‡ Š‘Ŝɏɏ†‘ ɏɏƀ
‡ Š‘”‡–—”•‹–•‹’—–ƒ”‰—‡–

Подозрительно выглядящая строка ɏɏ†‘ ɏɏ является внутренним именем строки


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

ǼțȕȒȞȐȐ²ȥȚȖȖȉȢȍȒȚȣȗȍȘȊȖȋȖȒȓȈșșȈ
Я уже упоминал мантру Python: все является объектом. Числа, строки, кортежи, спи-
ски, словари и даже функции — это объекты. Функции в Python выступают объектами
первого класса. Вы можете присвоить их переменным, использовать как аргументы
для других функций и возвращать из функций. Это дает возможность решать в Python
такие задачи, которые трудно выполнить во многих других языках.
Для того чтобы убедиться в этом, определим простую функцию ƒ•™‡”ſƀ, которая
не имеет аргументов и просто выводит число ɫɩ:
ʴʴʴ†‡ˆƒ•™‡”ſƀś
ŜŜŜ’”‹–ſɫɩƀ

Вы знаете, что получите в качестве результата, если запустите эту функцию:


ʴʴʴƒ•™‡”ſƀ
ɫɩ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Теперь определим еще одну функцию с именем ”—ɏ•‘‡–Š‹‰. Она имеет один
аргумент с именем ˆ— , представляющий собой функцию, которую нужно запустить
и которая просто вызывает другую функцию:
ʴʴʴ†‡ˆ”—ɏ•‘‡–Š‹‰ſˆ— ƀś
ŜŜŜˆ— ſƀ

Если мы передадим answer в функцию ”—ɏ•‘‡–Š‹‰ſƀ, то используем ее в каче-


стве данных, как и другие объекты:
ʴʴʴ”—ɏ•‘‡–Š‹‰ſƒ•™‡”ƀ
ɫɩ

Обратите внимание: вы передали строку answer, а не ƒ•™‡”ſƀ. В Python круглые


скобки означают «вызови эту функцию». Если скобок нет, Python относится к функ-
ции как к любому другому объекту. Это происходит потому, что функция является
объектом, как и все остальное в Python:
ʴʴʴ–›’‡ſ”—ɏ•‘‡–Š‹‰ƀ
ʳ Žƒ••ɐˆ— –‹‘ɐʴ

Попробуем запустить функцию с аргументами. Определим функцию ƒ††ɏƒ”‰•ſƀ,


которая выводит на экран сумму двух числовых аргументов ƒ”‰ɨ и ƒ”‰ɩ:
ʴʴʴ†‡ˆƒ††ɏƒ”‰•ſƒ”‰ɨřƒ”‰ɩƀś
ŜŜŜ’”‹–ſƒ”‰ɨʫƒ”‰ɩƀ

Чем является ƒ††ɏƒ”‰•ſƀ?


ʴʴʴ–›’‡ſƒ††ɏƒ”‰•ƀ
ʳ Žƒ••ɐˆ— –‹‘ɐʴ

Теперь определим функцию, которая называется ”—ɏ•‘‡–Š‹‰ɏ™‹–Šɏƒ”‰•ſƀ


и принимает три аргумента:
‰ˆ— — функция, которую нужно запустить;
‰ƒ”‰ɨ — первый аргумент функции ˆ— ;
‰ƒ”‰ɩ — второй аргумент функции ˆ— .

ʴʴʴ†‡ˆ”—ɏ•‘‡–Š‹‰ɏ™‹–Šɏƒ”‰•ſˆ— řƒ”‰ɨřƒ”‰ɩƀś
ŜŜŜˆ— ſƒ”‰ɨřƒ”‰ɩƀ

Когда вы вызываете функцию ”—ɏ•‘‡–Š‹‰ɏ™‹–Šɏƒ”‰•ſƀ, та функция, что


передается вызывающей стороной, присваивается параметру ˆ— , а переменные
ƒ”‰ɨ и ƒ”‰ɩ получают значения, которые следуют далее в списке аргументов. Вызов
ˆ— ſƒ”‰ɨř ƒ”‰ɩƀ выполняет данную функцию с этими аргументами, потому что
круглые скобки указывают Python сделать это.
Проверим функцию ”—ɏ•‘‡–Š‹‰ɏ™‹–Šɏƒ”‰•ſƀ , передав ей имя функции
ƒ††ɏƒ”‰• и аргументы ɬ и 9:
ʴʴʴ”—ɏ•‘‡–Š‹‰ɏ™‹–Šɏƒ”‰•ſƒ††ɏƒ”‰•řɬřɰƀ
ɨɫ
ǫȓȈȊȈǼțȕȒȞȐȐ  

Внутри функции ”—ɏ•‘‡–Š‹‰ɏ™‹–Šɏƒ”‰•ſƀ аргумент ƒ††ɏƒ”‰•, представляющий


собой имя функции, был присвоен параметру ˆ— , ɬ — параметру ƒ”‰ɨ, а 9 — пара-
метру ƒ”‰ɩ. В итоге получается следующая конструкция:
ƒ††ɏƒ”‰•ſɬřɰƀ

Вы можете объединить этот прием с использованием *args и ƋƋ™ƒ”‰•.


Определим тестовую функцию, которая принимает любое количество позицион-
ных аргументов, определяет их сумму с помощью функции •—ſƀ и возвращает ее:
ʴʴʴ†‡ˆ•—ɏƒ”‰•ſƋƒ”‰•ƀś
ŜŜŜ”‡–—”•—ſƒ”‰•ƀ

Я не упоминал функцию •—ſƀ ранее. Она встроена в Python и высчитывает сум-


му значений итерабельного числового (целочисленного или с плавающей точкой)
аргумента.
Определим новую функцию ”—ɏ™‹–Šɏ’‘•‹–‹‘ƒŽɏƒ”‰•ſƀ, принимающую функ-
цию и произвольное количество позиционных аргументов, которые нужно будет
передать в нее:
ʴʴʴ†‡ˆ”—ɏ™‹–Šɏ’‘•‹–‹‘ƒŽɏƒ”‰•ſˆ— řƋƒ”‰•ƀś
ŜŜŜ”‡–—”ˆ— ſƋƒ”‰•ƀ

Теперь вызовем ее:


ʴʴʴ”—ɏ™‹–Šɏ’‘•‹–‹‘ƒŽɏƒ”‰•ſ•—ɏƒ”‰•řɨřɩřɪřɫƀ
ɨɥ

Вы можете использовать функции как элементы списков, кортежей, множеств


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

ǪȕțȚȘȍȕȕȐȍȜțȕȒȞȐȐ
Вы можете определить функцию внутри другой функции:
ʴʴʴ†‡ˆ‘—–‡”ſƒř„ƀś
ŜŜŜ†‡ˆ‹‡”ſ ř†ƀś
ŜŜŜ”‡–—” ʫ†
ŜŜŜ”‡–—”‹‡”ſƒř„ƀ
ŜŜŜ
ʴʴʴ
ʴʴʴ‘—–‡”ſɫřɮƀ
ɨɨ

Внутренние функции могут быть полезны при выполнении некоторых сложных


задач более одного раза внутри другой функции. Это позволит избежать использо-
вания циклов или дублирования кода. Рассмотрим пример работы со строкой, когда
внутренняя функция добавляет текст в свой аргумент:
ʴʴʴ†‡ˆ‹‰Š–•ſ•ƒ›‹‰ƀś
ŜŜŜ†‡ˆ‹‡”ſ“—‘–‡ƀś
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ŜŜŜ”‡–—”ɑ‡ƒ”‡–Ї‹‰Š–•™Š‘•ƒ›śɐʩ•ɐɑʩ“—‘–‡
ŜŜŜ”‡–—”‹‡”ſ•ƒ›‹‰ƀ
ŜŜŜ
ʴʴʴ‹‰Š–•ſɐ‹Šɐƀ
ɑ‡ƒ”‡–Ї‹‰Š–•™Š‘•ƒ›śɐ‹Šɐɑ

Замыкания. Внутренняя функция может действовать как замыкание. Замыка-


ние — это функция, которая динамически генерируется другой функцией. Обе они
могут изменяться и запоминать значения переменных, которые были созданы вне
функции.
Обратимся еще раз к примеру ‹‰Š–•ſƀ. Назовем новую функцию ‹‰Š–•ɩſƀ,
поскольку у нас нет воображения, и превратим функцию ‹‡”ſƀ в замыкание, ко-
торое называется ‹‡”ɩſƀ. Различия заключаются в следующем:
‰‹‡”ɩſƀ использует внешний параметр saying непосредственно, вместо того
чтобы получить его как аргумент;
‰‹‰Š–•ɩſƀ возвращает имя функции ‹‡”ɩ, вместо того чтобы вызывать ее:
ʴʴʴ†‡ˆ‹‰Š–•ɩſ•ƒ›‹‰ƀś
ŜŜŜ†‡ˆ‹‡”ɩſƀś
ŜŜŜ”‡–—”ɑ‡ƒ”‡–Ї‹‰Š–•™Š‘•ƒ›śɐʩ•ɐɑʩ•ƒ›‹‰
ŜŜŜ”‡–—”‹‡”ɩ
ŜŜŜ

Функция ‹‡”ɩſƀ знает значение переменой saying, которое было передано


в функцию, и запоминает его. Строка ‹‡”ɩ возвращает эту особую копию функ-
ции ‹‡”ɩ (но не вызывает ее). Получается своего рода замыкание: динамически
созданная функция, которая запоминает, откуда она появилась.
Вызовем функцию ‹‰Š–•ɩſƀ два раза с разными аргументами:
ʴʴʴƒʰ‹‰Š–•ɩſɐ— ɐƀ
ʴʴʴ„ʰ‹‰Š–•ɩſɐ ƒ•‡’ˆ‡ˆˆ‡”ɐƀ

О’кей, чем являются a и b?


ʴʴʴ–›’‡ſƒƀ
ʳ Žƒ••ɐˆ— –‹‘ɐʴ
ʴʴʴ–›’‡ſ„ƀ
ʳ Žƒ••ɐˆ— –‹‘ɐʴ

Они являются функциями, а также замыканиями:


ʴʴʴƒ
ʳˆ— –‹‘‹‰Š–•ɩŜʳŽ‘ ƒŽ•ʴŜ‹‡”ɩƒ–ɥšɨɥɨɰɪ‡ɨɬɯʴ
ʴʴʴ„
ʳˆ— –‹‘‹‰Š–•ɩŜʳŽ‘ ƒŽ•ʴŜ‹‡”ɩƒ–ɥšɨɥɨɰɪ‡ɨ‡ɥʴ

Если мы вызовем их, они запомнят значение переменной saying, которое было
использовано, когда они создавались функцией ‹‰Š–•ɩ:
ʴʴʴƒſƀ
ɑ‡ƒ”‡–Ї‹‰Š–•™Š‘•ƒ›śɐ— ɐɑ
ʴʴʴ„ſƀ
ɑ‡ƒ”‡–Ї‹‰Š–•™Š‘•ƒ›śɐ ƒ•‡’ˆ‡ˆˆ‡”ɐɑ
ǫȓȈȊȈǼțȕȒȞȐȐ  

ǨȕȖȕȐȔȕȣȍȜțȕȒȞȐȐȓȧȔȉȌȈȊȣȘȈȎȍȕȐȧ
В Python лямбда-функция — это анонимная функция, выраженная в виде одного
оператора. Ее можно использовать вместо обычной небольшой функции.
Чтобы проиллюстрировать анонимные функции, сначала создадим пример,
в котором используются обычные функции. В первую очередь определим функцию
‡†‹–ɏ•–‘”›ſƀ. Она имеет следующие аргументы:

‰™‘”†• — список слов;


‰ˆ— — функцию, которая должна быть применена к каждому слову в списке ™‘”†•:
ʴʴʴ†‡ˆ‡†‹–ɏ•–‘”›ſ™‘”†•řˆ— ƀś
ŜŜŜˆ‘”™‘”†‹™‘”†•ś
ŜŜŜ’”‹–ſˆ— ſ™‘”†ƀƀ

Теперь нам нужны список слов и функция, которую требуется к ним применить.
В качестве слов я возьму список звуков (гипотетических), которые мог бы издать
мой кот, если бы (гипотетически) он не заметил одну из лестниц:
ʴʴʴ•–ƒ‹”•ʰƃɐ–Š—†ɐřɐ‡‘™ɐřɐ–Š—†ɐřɐŠ‹••ɐƄ

Функция запишет каждое слово с большой буквы и добавит к нему восклица-


тельный знак, что идеально подойдет для заголовка какой-нибудь желтой кошачьей
газетенки:
ʴʴʴ†‡ˆ‡Ž‹˜‡ſ™‘”†ƀśɤȕȢȟȰȬșȱȠȢȪȜȝŠ
ŜŜŜ”‡–—”™‘”†Ŝ ƒ’‹–ƒŽ‹œ‡ſƀʫɐŠɐ

Смешаем наши ингредиенты:


ʴʴʴ‡†‹–ɏ•–‘”›ſ•–ƒ‹”•ř‡Ž‹˜‡ƀ
Š—†Š
‡‘™Š
Š—†Š
‹••Š

Наконец переходим к лямбде. Функция ‡Ž‹˜‡ſƀ была такой короткой, что мы


можем заменить ее лямбдой:
ʴʴʴ
ʴʴʴ‡†‹–ɏ•–‘”›ſ•–ƒ‹”•řŽƒ„†ƒ™‘”†ś™‘”†Ŝ ƒ’‹–ƒŽ‹œ‡ſƀʫɐŠɐƀ
Š—†Š
‡‘™Š
Š—†Š
‹••Š
ʴʴʴ

Лямбда-выражение имеет ноль или больше аргументов, разделенных запятой, за


которыми следуют двоеточие (ś) и определение функции. Этому лямбда-выражению мы
передаем один аргумент ™‘”†. Для вызова лямбда-выражения не используются круглые
скобки, в отличие от вызова функции, созданной с помощью ключевого слова †‡ˆ.
Зачастую использование реальных функций, таких как ‡Ž‹˜‡ſƀ, гораздо по-
нятнее, чем использование лямбд. Лямбды наиболее полезны в случаях, когда вам
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

нужно определить множество мелких функций и запомнить все их имена. В частно-


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

ǫȍȕȍȘȈȚȖȘȣ
В Python генератор — это объект, который предназначен для создания последова-
тельностей. С его помощью вы можете итерировать потенциально огромные после-
довательности, не создавая и не сохраняя всю последовательность в памяти сразу.
Генераторы часто становятся источником данных для итераторов. Как вы помните,
один из них, ”ƒ‰‡ſƀ, мы уже использовали в примерах кода для того, чтобы сгене-
рировать последовательность целых чисел. В Python 2 функция ”ƒ‰‡ſƀ возвращает
список, ограниченный так, чтобы он помещался в память. В Python 2 также есть
функция š”ƒ‰‡ſƀ, которая стала обычной функцией ”ƒ‰‡ſƀ в Python 3. В этом
примере складываются все целые числа от 1 до 100:
ʴʴʴ•—ſ”ƒ‰‡ſɨřɨɥɨƀƀ
ɬɥɬɥ

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


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

ǼțȕȒȞȐȐȋȍȕȍȘȈȚȖȘȣ
Если вы хотите создать потенциально большую последовательность, вы можете на-
писать функцию-генератор. Это обычная функция, однако она возвращает значение
с помощью выражения ›‹‡Ž†, а не return. Напишем собственную функцию ”ƒ‰‡ſƀ:
ʴʴʴ†‡ˆ›ɏ”ƒ‰‡ſˆ‹”•–ʰɥřŽƒ•–ʰɨɥř•–‡’ʰɨƀś
ŜŜŜ—„‡”ʰˆ‹”•–
ŜŜŜ™Š‹Ž‡—„‡”ʳŽƒ•–ś
ŜŜŜ›‹‡Ž†—ber
ŜŜŜ—„‡”ʫʰ•–‡’
ŜŜŜ

Это обычная функция:


ʴʴʴ›ɏ”ƒ‰‡
ʳˆ— –‹‘›ɏ”ƒ‰‡ƒ–ɥšɨɥɨɰɪ‡ɩɭɯʴ

И она возвращает объект генератора:


ʴʴʴ”ƒ‰‡”ʰ›ɏ”ƒ‰‡ſɨřɬƀ
ʴʴʴ”ƒ‰‡”
ʳ‰‡‡”ƒ–‘”‘„Œ‡ –›ɏ”ƒ‰‡ƒ–ɥšɨɥɨƒɥƒɨɭɯʴ
ǫȓȈȊȈǼțȕȒȞȐȐ  

Мы можем проитерировать по этому объекту генератора:


ʴʴʴˆ‘”š‹”ƒ‰‡”ś
ŜŜŜ’”‹–ſšƀ
ŜŜŜ
ɨ
ɩ
ɪ
ɫ

ǫȍȕȍȘȈȚȖȘȔȖȎȕȖȏȈȗțșȚȐȚȤȓȐȠȤȖȌȕȈȎȌȣǹȗȐșȒȐȔȕȖȎȍșȚȊȈșȚȘȖȒȐȐșȓȖȊȈȘȐ
șțȡȍșȚȊțȦȚȊȗȈȔȧȚȐȈȋȍȕȍȘȈȚȖȘȣșȖȏȌȈȦȚșȊȖȐȏȕȈȟȍȕȐȧȕȈȓȍȚțȐȊȣȌȈȦȚȐȝ
ȗȖȖȌȕȖȔțșȗȖȔȖȡȤȦȐȚȍȘȈȚȖȘȈǫȍȕȍȘȈȚȖȘȕȍȏȈȗȖȔȐȕȈȍȚȏȕȈȟȍȕȐȧȗȖȥȚȖȔțȊȣ
ȕȍȔȖȎȍȚȍȗȍȘȍȏȈȗțșȚȐȚȤȍȋȖȐȓȐșȖȏȌȈȚȤȘȍȏȍȘȊȕțȦȒȖȗȐȦ

Если вы попробуете снова проитерировать по генератору, вы увидите, что он


истощился:
ʴʴʴˆ‘”–”›ɏƒ‰ƒ‹‹”ƒ‰‡”ś
ŜŜŜ’”‹–ſ–”›ɏƒ‰ƒ‹ƀ
ŜŜŜ
ʴʴʴ

ǪȒȓȦȟȍȕȐȧȋȍȕȍȘȈȚȖȘȖȊ
Вы уже сталкивались с включениями списков, словарей и множеств. Включение
генератора выглядит так же, но заключается в круглые скобки, а не в квадратные
или фигурные. Оно похоже на сокращенную функцию-генератор, которая неявно
выполняет ›‹‡Ž† и возвращает объект генератора:
ʴʴʴ‰‡‘„Œʰſ’ƒ‹”ˆ‘”’ƒ‹”‹œ‹’ſƃɐƒɐřɐ„ɐƄřƃɐɨɐřɐɩɐƄƀƀ
ʴʴʴ‰‡‘„Œ
ʳ‰‡‡”ƒ–‘”‘„Œ‡ –ʳ‰‡‡š’”ʴƒ–ɥšɨɥɪɥɯˆ†‡ɥʴ
ʴʴʴˆ‘”–Š‹‰‹‰‡‘„Œś
ŜŜŜ’”‹–ſ–Š‹‰ƀ
ŜŜŜ
ſɐƒɐřɐɨɐƀ
ſɐ„ɐřɐɩɐƀ

ǬȍȒȖȘȈȚȖȘȣ
Иногда вам нужно модифицировать существующую функцию, не меняя при этом ее
исходный код. Чаще всего добавляется выражение для отладки, чтобы посмотреть,
какие аргументы были переданы.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Декоратор — это функция, которая принимает одну функцию в качестве аргу-


мента и возвращает другую функцию. Давайте рассмотрим, какие приемы из нашего
арсенала мы можем использовать:
‰*args и ƋƋ™ƒ”‰•;
‰внутренние функции;
‰функции в качестве аргументов.
Функция †‘ —‡–ɏ‹–ſƀ определяет декоратор, который:
‰выведет имя функции и значения переданных в нее аргументов;
‰запустит функцию с полученными аргументами;
‰выведет результат;
‰вернет модифицированную функцию, готовую для использования.
Код будет выглядеть так:
ʴʴʴ†‡ˆ†‘ —‡–ɏ‹–ſˆ— ƀś
ŜŜŜ†‡ˆ‡™ɏˆ— –‹‘ſƋƒ”‰•řƋƋ™ƒ”‰•ƀś
ŜŜŜ’”‹–ſɐ—‹‰ˆ— –‹‘śɐřˆ— Ŝɏɏƒ‡ɏɏƀ
ŜŜŜ’”‹–ſɐ‘•‹–‹‘ƒŽƒ”‰—‡–•śɐřƒ”‰•ƀ
ŜŜŜ’”‹–ſɐ‡›™‘”†ƒ”‰—‡–•śɐř™ƒ”‰•ƀ
ŜŜŜ”‡•—Ž–ʰˆ— ſƋƒ”‰•řƋƋ™ƒ”‰•ƀ
ŜŜŜ’”‹–ſɐ‡•—Ž–śɐř”‡•—Ž–ƀ
ŜŜŜ”‡–—””‡•—Ž–
ŜŜŜ”‡–—”‡™ɏˆ— –‹‘

Независимо от того, какую функцию ˆ— вы передадите †‘ —‡–ɏ‹–ſƀ , вы


получите новую функцию с дополнительными выражениями, которые добавляет
†‘ —‡–ɏ‹–ſƀ. Декоратор не обязательно должен запускать код функции ˆ— , но
функция †‘ —‡–ɏ‹–ſƀ вызовет часть ˆ— , чтобы вы получили результат работы
функции ˆ— , а также дополнительные данные:
ʴʴʴ†‡ˆƒ††ɏ‹–•ſƒř„ƀś
ŜŜŜ”‡–—”ƒʫ„
ŜŜŜ
ʴʴʴƒ††ɏ‹–•ſɪřɬƀ
ɯ
ʴʴʴ ‘‘އ”ɏƒ††ɏ‹–•ʰ†‘ —‡–ɏ‹–ſƒ††ɏ‹–•ƀɤȥȢțȘȔȡȜșȘșȞȢȤȔȦȢȤȔȖȤȧȫȡȧȲ
ʴʴʴ ‘‘އ”ɏƒ††ɏ‹–•ſɪřɬƀ
—‹‰ˆ— –‹‘śƒ††ɏ‹–•
‘•‹–‹‘ƒŽƒ”‰—‡–•śſɪřɬƀ
‡›™‘”†ƒ”‰—‡–•śƇƈ
‡•—Ž–śɯ
ɯ

В качестве альтернативы созданию декоратора вручную (этот процесс мы только


что рассмотрели) можно добавить конструкцию ɘȜȠȳɕȘșȞȢȤȔȦȢȤȔ перед функцией,
которую нужно декорировать:
ǫȓȈȊȈǼțȕȒȞȐȐ  

ʴʴʴɒ†‘ —‡–ɏ‹–
ŜŜŜ†‡ˆƒ††ɏ‹–•ſƒř„ƀś
ŜŜŜ”‡–—”ƒʫ„
ŜŜŜ
ʴʴʴƒ††ɏ‹–•ſɪřɬƀ
—‹‰ˆ— –‹‘ƒ††ɏ‹–•
‘•‹–‹‘ƒŽƒ”‰—‡–•śſɪřɬƀ
‡›™‘”†ƒ”‰—‡–•śƇƈ
‡•—Ž–śɯ
ɯ

У каждой функции может быть больше одного декоратора. Напишем еще один
с именем •“—ƒ”‡ɏ‹–ſƀ, который возводит результат в квадрат:
ʴʴʴ†‡ˆ•“—ƒ”‡ɏ‹–ſˆ— ƀś
ŜŜŜ†‡ˆ‡™ɏˆ— –‹‘ſƋƒ”‰•řƋƋ™ƒ”‰•ƀś
ŜŜŜ”‡•—Ž–ʰˆ— ſƋƒ”‰•řƋƋ™ƒ”‰•ƀ
ŜŜŜ”‡–—””‡•—Ž–Ƌ”‡•—Ž–
ŜŜŜ”‡–—”‡™ɏˆ— –‹‘
ŜŜŜ

Декоратор, размещенный ближе всего к функции (прямо над †‡ˆ), будет выпол-
нен первым, а затем выполнится тот, что находится сразу над ним. Любой порядок
вызова вернет один и тот же конечный результат, но вы можете увидеть все про-
межуточные этапы:
ʴʴʴɒ†‘ —‡–ɏ‹–
ŜŜŜɒ•“—ƒ”‡ɏ‹–
ŜŜŜ†‡ˆƒ††ɏ‹–•ſƒř„ƀś
ŜŜŜ”‡–—”ƒʫ„
ŜŜŜ
ʴʴʴƒ††ɏ‹–•ſɪřɬƀ
—‹‰ˆ— –‹‘ś‡™ɏˆ— –‹‘
‘•‹–‹‘ƒŽƒ”‰—‡–•śſɪřɬƀ
‡›™‘”†ƒ”‰—‡–•śƇƈ
‡•—Ž–śɭɫ
ɭɫ

Попробуем изменить порядок декораторов:


ʴʴʴɒ•“—ƒ”‡ɏ‹–
ŜŜŜɒ†‘ —‡–ɏ‹–
ŜŜŜ†‡ˆƒ††ɏ‹–•ſƒř„ƀś
ŜŜŜ”‡–—”ƒʫ„
ŜŜŜ
ʴʴʴƒ††ɏ‹–•ſɪřɬƀ
—‹‰ˆ— –‹‘śƒ††ɏ‹–•
‘•‹–‹‘ƒŽƒ”‰—‡–•śſɪřɬƀ
‡›™‘”†ƒ”‰—‡–•śƇƈ
‡•—Ž–śɯ
ɭɫ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǷȘȖșȚȘȈȕșȚȊȈȐȔȍȕȐȖȉȓȈșȚȤȖȗȘȍȌȍȓȍȕȐȧ
С тем, кто в искусстве больше преуспел…

Уильям Шекспир

Имя может ссылаться на несколько разных объектов в зависимости от того, где оно
используется. Программы на Python имеют различные пространства имен — раз-
делы, внутри которых определенное имя уникально и не связано с таким же именем
в других пространствах имен.
Каждая функция определяет собственное пространство имен. Если вы опреде-
лите переменную с именем ȩ в основной программе и другую переменную ȩ в от-
дельной функции, они будут ссылаться на разные значения. Но эту стену можно
пробить: если нужно, вы можете получить доступ к именам в других пространствах
имен разными способами.
В основной программе определяется глобальное пространство имен, поэтому
переменные, находящиеся в нем, являются глобальными.
Значение глобальной переменной можно получить внутри функции:
ʴʴʴƒ‹ƒŽʰɐˆ”—‹–„ƒ–ɐ
ʴʴʴ†‡ˆ’”‹–ɏ‰Ž‘„ƒŽſƀś
ŜŜŜ’”‹–ſɐ‹•‹†‡’”‹–ɏ‰Ž‘„ƒŽśɐřƒ‹ƒŽƀ
ŜŜŜ
ʴʴʴ’”‹–ſɐƒ––Ї–‘’އ˜‡Žśɐřƒ‹ƒŽƀ
ƒ––Ї–‘’އ˜‡Žśˆ”—‹–„ƒ–
ʴʴʴ’”‹–ɏ‰Ž‘„ƒŽſƀ
‹•‹†‡’”‹–ɏ‰Ž‘„ƒŽśˆ”—‹–„ƒ–

Но если вы попробуете получить значение глобальной переменной и изменить


его внутри функции, то получите ошибку:
ʴʴʴ†‡ˆ Šƒ‰‡ɏƒ†ɏ’”‹–ɏ‰Ž‘„ƒŽſƀś
ŜŜŜ’”‹–ſɐ‹•‹†‡ Šƒ‰‡ɏƒ†ɏ’”‹–ɏ‰Ž‘„ƒŽśɐřƒ‹ƒŽƀ
ŜŜŜƒ‹ƒŽʰɐ™‘„ƒ–ɐ
ŜŜŜ’”‹–ſɐƒˆ–‡”–Ї Šƒ‰‡śɐřƒ‹ƒŽƀ
ŜŜŜ
ʴʴʴ Šƒ‰‡ɏƒ†ɏ’”‹–ɏ‰Ž‘„ƒŽſƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɩř‹ Šƒ‰‡ɏƒ†ɏ’”‹–ɏ‰Ž‘„ƒŽ
„‘—†‘ ƒŽ””‘”śŽ‘ ƒŽ˜ƒ”‹ƒ„އɐƒ‹ƒŽɐ”‡ˆ‡”‡ ‡†„‡ˆ‘”‡ƒ••‹‰‡–

Если вы просто измените его, то изменится другая переменная, которая также


называется ƒ‹ƒŽ, но находится внутри функции:
ʴʴʴ†‡ˆ Šƒ‰‡ɏŽ‘ ƒŽſƀś
ŜŜŜƒ‹ƒŽʰɐ™‘„ƒ–ɐ
ŜŜŜ’”‹–ſɐ‹•‹†‡ Šƒ‰‡ɏŽ‘ ƒŽśɐřƒ‹ƒŽř‹†ſƒ‹ƒŽƀƀ
ŜŜŜ
ʴʴʴ Šƒ‰‡ɏŽ‘ ƒŽſƀ
ǫȓȈȊȈǼțȕȒȞȐȐ  

‹•‹†‡ Šƒ‰‡ɏŽ‘ ƒŽś™‘„ƒ–ɫɪɪɥɫɥɭɨɭɥ


ʴʴʴƒ‹ƒŽ
ɐˆ”—‹–„ƒ–ɐ
ʴʴʴ‹†ſƒ‹ƒŽƀ
ɫɪɪɥɪɰɥɯɪɩ

Что же произошло? Сначала мы присвоили строку ɐˆ”—‹–„ƒ–ɐ глобальной пере-


менной с именем ƒ‹ƒŽ. Функция Šƒ‰‡ɏŽ‘ ƒŽſƀ также имеет переменную с име-
нем ƒ‹ƒŽ, но та находится в ее локальном пространстве имен.
Я использовал функцию ‹†ſƀ , чтобы вывести на экран уникальное значение
каждого объекта и доказать, что переменная ƒ‹ƒŽ, расположенная внутри функции
Šƒ‰‡ɏŽ‘ ƒŽſƀ, — это не переменная ƒ‹ƒŽ, расположенная на основном уровне
программы.
Чтобы получить доступ не к локальной переменной внутри функции, а к гло-
бальной переменой, нужно явно использовать ключевое слово global (вы знали, что
я это скажу: явное лучше, чем неявное):
ʴʴʴƒ‹ƒŽʰɐˆ”—‹–„ƒ–ɐ
ʴʴʴ†‡ˆ Šƒ‰‡ɏƒ†ɏ’”‹–ɏ‰Ž‘„ƒŽſƀś
ŜŜŜ‰Ž‘„ƒŽƒ‹ƒŽ
ŜŜŜƒ‹ƒŽʰɐ™‘„ƒ–ɐ
ŜŜŜ’”‹–ſɐ‹•‹†‡ Šƒ‰‡ɏƒ†ɏ’”‹–ɏ‰Ž‘„ƒŽśɐřƒ‹ƒŽƀ
ŜŜŜ
ʴʴʴƒ‹ƒŽ
ɐˆ”—‹–„ƒ–ɐ
ʴʴʴ Šƒ‰‡ɏƒ†ɏ’”‹–ɏ‰Ž‘„ƒŽſƀ
‹•‹†‡ Šƒ‰‡ɏƒ†ɏ’”‹–ɏ‰Ž‘„ƒŽś™‘„ƒ–
ʴʴʴƒ‹ƒŽ
ɐ™‘„ƒ–ɐ

Если вы не используете ключевое слово global внутри функции, Python задей-


ствует локальное пространство имен и переменная, таким образом, будет локальной.
Она пропадет после того, как функция завершит работу.
Python предоставляет две функции для доступа к содержимому ваших про-
странств имен:
‰Ž‘ ƒŽ•ſƀ — возвращает словарь, содержащий имена локального пространства
имен;
‰‰Ž‘„ƒŽ•ſƀ — возвращает словарь, содержащий имена глобального пространства
имен.
Вот как они используются:
ʴʴʴƒ‹ƒŽʰɐˆ”—‹–„ƒ–ɐ
ʴʴʴ†‡ˆ Šƒ‰‡ɏŽ‘ ƒŽſƀś
ŜŜŜƒ‹ƒŽʰɐ™‘„ƒ–ɐɤȟȢȞȔȟȰȡȔȳȣșȤșȠșȡȡȔȳ
ŜŜŜ’”‹–ſɐŽ‘ ƒŽ•śɐřŽ‘ ƒŽ•ſƀƀ
ŜŜŜ
ʴʴʴƒ‹ƒŽ
ɐˆ”—‹–„ƒ–ɐ
ʴʴʴ Šƒ‰‡ɏŽ‘ ƒŽſƀ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Ž‘ ƒŽ•śƇɐƒ‹ƒŽɐśɐ™‘„ƒ–ɐƈ
ʴʴʴ’”‹–ſɐ‰Ž‘„ƒŽ•śɐř‰Ž‘„ƒŽ•ſƀƀɤȡșȠȡȢȗȢȣșȤșȨȢȤȠȔȦȜȤȢȖȔȡȢȘȟȳȣȤșȘȥȦȔȖȟșȡȜȳ
‰Ž‘„ƒŽ•śƇɐƒ‹ƒŽɐśɐˆ”—‹–„ƒ–ɐř
ɐɏɏ†‘ ɏɏɐś‘‡ř
ɐ Šƒ‰‡ɏŽ‘ ƒŽɐśʳˆ— –‹‘ Šƒ‰‡ɏ‹–ƒ–ɥšɨɥɥɭ ɥɨɮɥʴř
ɐɏɏ’ƒ ƒ‰‡ɏɏɐś‘‡ř
ɐɏɏƒ‡ɏɏɐśɐɏɏƒ‹ɏɏɐř
ɐɏɏŽ‘ƒ†‡”ɏɏɐśʳ Žƒ••ɐɏˆ”‘œ‡ɏ‹’‘”–Ž‹„Ŝ—‹Ž–‹ ’‘”–‡”ɐʴř
ɐɏɏ„—‹Ž–‹•ɏɏɐśʳ‘†—އɐ„—‹Ž–‹•ɐʴƈ
ʴʴʴƒ‹ƒŽ
ɐˆ”—‹–„ƒ–ɐ

Локальное пространство имен внутри функции Šƒ‰‡ɏŽ‘ ƒŽſƀ содержало только


локальную переменную ƒ‹ƒŽ. Глобальное пространство имен содержало отдель-
ную глобальную переменную ƒ‹ƒŽ и многое другое.

ǰșȗȖȓȤȏȖȊȈȕȐȍșȐȔȊȖȓȖȊBȐBBȊȐȔȍȕȈȝ
Имена, которые начинаются с двух нижних подчеркиваний (ɏɏ) и заканчиваются
ими, зарезервированы для использования внутри Python, поэтому вам не следует
применять их к своим собственным переменным. Подобный шаблон именования
был выбран потому, что разработчики, скорее всего, не стали бы им пользоваться
для создания имен своих переменных.
Например, имя функции находится в системной переменной ˆ— –‹‘Ŝɏɏƒ‡ɏɏ,
а имя ее строки документации — в ˆ— –‹‘Ŝɏɏ†‘ ɏɏ:
ʴʴʴ†‡ˆƒƒœ‹‰ſƀś
ŜŜŜɐɐɐŠ‹•‹•–Їƒƒœ‹‰ˆ— –‹‘Ŝ
ŜŜŜƒ––‘•‡‡‹–ƒ‰ƒ‹ţɐɐɐ
ŜŜŜ’”‹–ſɐŠ‹•ˆ— –‹‘‹•ƒ‡†śɐřƒƒœ‹‰Ŝɏɏƒ‡ɏɏƀ
ŜŜŜ’”‹–ſɐ†‹–•†‘ •–”‹‰‹•śɐřƒƒœ‹‰Ŝɏɏ†‘ ɏɏƀ
ŜŜŜ
ʴʴʴƒƒœ‹‰ſƀ
Š‹•ˆ— –‹‘‹•ƒ‡†śƒƒœ‹‰
†‹–•†‘ •–”‹‰‹•śŠ‹•‹•–Їƒƒœ‹‰ˆ— –‹‘Ŝ
ƒ––‘•‡‡‹–ƒ‰ƒ‹ţ

Как вы видели ранее в содержимом globals, основной программе присвоено


специальное имя ɏɏƒ‹ɏɏ.

ǸȍȒțȘșȐȧ
До сих пор мы видели функции, которые выполняют какие-то определенные дей-
ствия и, возможно, вызывают другие функции. Но что, если функция вызовет саму
себя?1 Это называется рекурсией. Так же как не нужны бесконечные циклы while

1
Это как сказать: «Я хочу, чтоб мне давали монетку каждый раз, когда я хочу, чтобы мне
дали монетку».
ǫȓȈȊȈǼțȕȒȞȐȐ  

или for, не нужна и бесконечная рекурсия. Стоит ли нам волноваться за целостность


пространственно-временного континуума?
Python снова спасает Вселенную, генерируя исключение, если вы зайдете слиш-
ком далеко:
ʴʴʴ†‡ˆ†‹˜‡ſƀś
ŜŜŜ”‡–—”†‹˜‡ſƀ
ŜŜŜ
ʴʴʴ†‹˜‡ſƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɩř‹†‹˜‡
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɩř‹†‹˜‡
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɩř‹†‹˜‡
ƃ”‡˜‹‘—•Ž‹‡”‡’‡ƒ–‡†ɰɰɭ‘”‡–‹‡•Ƅ
‡ —”•‹‘””‘”śƒš‹—”‡ —”•‹‘†‡’–Ї𠇇†‡†

Рекурсия может быть полезна, если вы работаете с чем-то вроде списков, содер-
жащих списки, которые содержат списки.
Предположим, вы хотите «уплотнить» все подсписки1 независимо от того, на-
сколько глубоко они вложены. Для этого отлично подойдет функция-генератор:
ʴʴʴ†‡ˆˆŽƒ––‡ſŽ‘Žƀś
ŜŜŜˆ‘”‹–‡‹Ž‘Žś
ŜŜŜ‹ˆ‹•‹•–ƒ ‡ſ‹–‡řŽ‹•–ƀś
ŜŜŜˆ‘”•—„‹–‡‹ˆŽƒ––‡ſ‹–‡ƀś
ŜŜŜ›‹‡Ž†•—„‹–‡
ŜŜŜ‡Ž•‡ś
ŜŜŜ›‹‡Ž†‹–‡
ŜŜŜ
ʴʴʴŽ‘ŽʰƃɨřɩřƃɪřɫřɬƄřƃɭřƃɮřɯřɰƄřƃƄƄƄ
ʴʴʴˆŽƒ––‡ſŽ‘Žƀ
ʳ‰‡‡”ƒ–‘”‘„Œ‡ –ˆŽƒ––‡ƒ–ɥšɨɥɬɥɰƒɮɬɥʴ
ʴʴʴŽ‹•–ſˆŽƒ––‡ſŽ‘Žƀƀ
ƃɨřɩřɪřɫřɬřɭřɮřɯřɰƄ

В Python 3.3 появилось выражение ›‹‡Ž† ˆ”‘, которое позволяет генератору


передавать часть работы другому генератору. Мы можем использовать его для того,
чтобы упростить функцию ˆŽƒ––‡ſƀ:
ʴʴʴ†‡ˆˆŽƒ––‡ſŽ‘Žƀś
ŜŜŜˆ‘”‹–‡‹Ž‘Žś
ŜŜŜ‹ˆ‹•‹•–ƒ ‡ſ‹–‡řŽ‹•–ƀś
ŜŜŜ›‹‡Ž†ˆ”‘ˆŽƒ––‡ſ‹–‡ƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ›‹‡Ž†‹–‡
ŜŜŜ
ʴʴʴŽ‘ŽʰƃɨřɩřƃɪřɫřɬƄřƃɭřƃɮřɯřɰƄřƃƄƄƄ
ʴʴʴŽ‹•–ſˆŽƒ––‡ſŽ‘Žƀƀ
ƃɨřɩřɪřɫřɬřɭřɮřɯřɰƄ

1
Это еще один популярный вопрос на собеседованиях. Давайте соберем всю коллекцию!
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǨșȐȕȝȘȖȕȕȣȍȜțȕȒȞȐȐ
Ключевые слова ƒ•› и await были добавлены в Python 3.5 для того, чтобы можно
было определять и запускать асинхронные функции. Их можно описать так:
‰они относительно новые;
‰они значительно отличаются друг от друга, чтобы их сложнее было понять;
‰они станут более важными и более изученными со временем.
По этим причинам я перенес рассмотрение вопросов, связанных с асинхронно-
стью, в приложение В. Сейчас вам нужно знать, что, если вы в объявлении функции
перед словом †‡ˆ видите слово ƒ•› , это значит, что функция асинхронная. Ана-
логично, если перед вызовом функции вы видите слово await, эта функция также
является асинхронной. Основное различие между асинхронными и обычными
функциями заключается в том, что асинхронные могут «передавать управление»
вместо того, чтобы заставлять основной поток выполнения ждать до конца их вы-
полнения.

ǰșȒȓȦȟȍȕȐȧ
В некоторых языках программирования ошибки отображаются с помощью специ-
альных возвращаемых значений. В Python, если дело пахнет жареным1, используется
исключение: код, который выполняется, когда происходит связанная с ним ошибка.
Какие-то из исключений вы уже видели, пытаясь получить доступ к позиции,
не входящей в список/кортеж, или к словарю с несуществующим ключом. Когда
вы выполняете код, который при определенных условиях может не сработать, вам
также понадобятся обработчики исключений для перехвата любых потенциальных
ошибок.
Чтобы пользователь знал о происходящем, рекомендуется добавлять обработчи-
ки исключений везде, где исключение может быть сгенерировано. Не всегда у вас
получится исправить ошибку, но вы хотя бы будете знать, при каких обстоятельствах
она появилась, и аккуратно завершите программу. Если исключение сгенерирова-
лось в функции и там не обработалось, оно будет всплывать до тех пор, пока его
не поймает соответствующий обработчик в одной из вызывающих функций. Если вы
не предоставите собственный обработчик исключений, Python выведет сообщение
об ошибке и некоторую информацию о том, где произошла ошибка, а затем завершит
программу, как показано в следующем фрагменте кода:
ʴʴʴ•Š‘”–ɏŽ‹•–ʰƃɨřɩřɪƄ
ʴʴʴ’‘•‹–‹‘ʰɬ
ʴʴʴ•Š‘”–ɏŽ‹•–ƃ’‘•‹–‹‘Ƅ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
†‡š””‘”śŽ‹•–‹†‡š‘—–‘ˆ”ƒ‰‡

1
Интересно, это выражение характерно только для северного полушария? Говорят ли
австралийцы и новозеландцы«дело пахнет вареным», когда все идет не так, как хотелось бы?
ǫȓȈȊȈǼțȕȒȞȐȐ  

ǶȉȘȈȉȈȚȣȊȈȍȔȖȠȐȉȒȐșȗȖȔȖȡȤȦȖȗȍȘȈȚȖȘȖȊWU\ȐH[FHSW
Делай или не делай. Не надо пытаться.
Йода

Вместо того чтобы полагаться на волю случая, размещайте свой код в блоке try
и используйте блок ‡š ‡’– для обработки ошибки:
ʴʴʴ•Š‘”–ɏŽ‹•–ʰƃɨřɩřɪƄ
ʴʴʴ’‘•‹–‹‘ʰɬ
ʴʴʴ–”›ś
ŜŜŜ•Š‘”–ɏŽ‹•–ƃ’‘•‹–‹‘Ƅ
ŜŜŜ‡š ‡’–ś
ŜŜŜ’”‹–ſɐ‡‡†ƒ’‘•‹–‹‘„‡–™‡‡ɥƒ†ɐřއſ•Š‘”–ɏŽ‹•–ƀŞɨřɐ„—–‰‘–ɐř
ŜŜŜ’‘•‹–‹‘ƀ
ŜŜŜ
‡‡†ƒ’‘•‹–‹‘„‡–™‡‡ɥƒ†ɩ„—–‰‘–ɬ

Запускается код внутри блока try. Если произошла ошибка, генерируется ис-
ключение и выполняется код, расположенный внутри блока ‡š ‡’–. Если ошибок
не произошло, блок ‡š ‡’– пропускается.
Отсутствие аргументов в блоке ‡š ‡’–, как в предыдущем примере, позволяет
ловить исключения любого типа. Если предполагается, что могут возникнуть не-
сколько типов исключений, лучшим решением будет предоставить отдельный об-
работчик для каждого из них. Никто не заставляет это делать — можно использовать
блок ‡š ‡’– без аргументов, но тогда обработка будет достаточно поверхностной
(что-то вроде вывода на экран строки ǷȘȖȐȏȖȠȓȈ ȖȠȐȉȒȈ). Разрешается использовать
любое количество обработчиков исключений.
Иногда вам будут нужны и другие подробности исключения, а не только его тип.
Вы можете получить объект исключения целиком в переменной ȜȠȳ, если исполь-
зуете такую форму:
‡š ‡’–ȦȜȣɕȜȥȞȟȲȫșȡȜȳƒ•ȜȠȳ

В следующем примере выполняется проверка на †‡š””‘”, поскольку именно


это исключение вызывается, когда вы предоставляете недействительную позицию
последовательности. Исключение †‡š””‘” сохраняется в переменной err, а лю-
бое другое исключение — в переменной other. В примере на экран выводится все,
что хранится в переменной other, для демонстрации того, что вы получаете в этом
объекте:
ʴʴʴ•Š‘”–ɏŽ‹•–ʰƃɨřɩřɪƄ
ʴʴʴ™Š‹Ž‡”—‡ś
ŜŜŜ˜ƒŽ—‡ʰ‹’—–ſɐ‘•‹–‹‘ƃ“–‘“—‹–Ƅţɐƀ
ŜŜŜ‹ˆ˜ƒŽ—‡ʰʰɐ“ɐś
ŜŜŜ„”‡ƒ
ŜŜŜ–”›ś
ŜŜŜ’‘•‹–‹‘ʰ‹–ſ˜ƒŽ—‡ƀ
ŜŜŜ’”‹–ſ•Š‘”–ɏŽ‹•–ƃ’‘•‹–‹‘Ƅƀ
ŜŜŜ‡š ‡’– †‡š””‘”ƒ•‡””ś
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ŜŜŜ’”‹–ſɐƒ†‹†‡šśɐř’‘•‹–‹‘ƀ
ŜŜŜ‡š ‡’–š ‡’–‹‘ƒ•‘–Ї”ś
ŜŜŜ’”‹–ſɐ‘‡–Š‹‰‡Ž•‡„”‘‡śɐř‘–Ї”ƀ
ŜŜŜ
‘•‹–‹‘ƃ“–‘“—‹–Ƅţɨ
ɩ
‘•‹–‹‘ƃ“–‘“—‹–Ƅţɥ
ɨ
‘•‹–‹‘ƃ“–‘“—‹–Ƅţɩ
ɪ
‘•‹–‹‘ƃ“–‘“—‹–Ƅţɪ
ƒ†‹†‡šśɪ
‘•‹–‹‘ƃ“–‘“—‹–Ƅţɩ
ɪ
‘•‹–‹‘ƃ“–‘“—‹–Ƅţ–™‘
‘‡–Š‹‰‡Ž•‡„”‘‡ś‹˜ƒŽ‹†Ž‹–‡”ƒŽˆ‘”‹–ſƀ™‹–Š„ƒ•‡ɨɥśɐ–™‘ɐ
‘•‹–‹‘ƃ“–‘“—‹–Ƅţ“

Ввод позиции ɪ, как и ожидалось, генерирует исключение †‡š””‘”. Ввод слова


two не понравился функции ‹–ſƀ, которую мы обработали во втором, универсаль-
ном коде ‡š ‡’–.

ǹȖȏȌȈȍȔșȖȉșȚȊȍȕȕȣȍȐșȒȓȦȟȍȕȐȧ
В предыдущем подразделе обсуждалась обработка исключений, но все исключения
(такие как †‡š””‘”) заранее определены в Python или его стандартных библиоте-
ках. Вы можете использовать любые из этих исключений, но можете также и опреде-
лять собственные типы исключений, чтобы обрабатывать особые ситуации, которые
могут возникнуть в ваших программах.

ǬȓȧȥȚȖȋȖȗȖȚȘȍȉțȍȚșȧȖȗȘȍȌȍȓȐȚȤȕȖȊȣȑȚȐȗȖȉȢȍȒȚȈșȗȖȔȖȡȤȦȒȓȈșșȈǯȈȕȐȔȈȚȤ
șȧȒȓȈșșȈȔȐȔȣȕȈȟȕȍȔȊȋȓȈȊȍȗȖȥȚȖȔțȍșȓȐȊȣșȕȐȔȐȕȍȏȕȈȒȖȔȣȔȖȎȍȚȍ
ȖȉȘȈȚȐȚȤșȧȒșȖȖȚȊȍȚșȚȊțȦȡȍȔțȘȈȏȌȍȓț

Любое исключение является классом, частным случаем класса š ‡’–‹‘. Соз-


дадим исключение, которое называется ’’‡” ƒ•‡š ‡’–‹‘ и которое будет вызы-
ваться при нахождении слова, записанного буквами в верхнем регистре:
ʴʴʴ Žƒ••’’‡” ƒ•‡š ‡’–‹‘ſš ‡’–‹‘ƀś
ŜŜŜ’ƒ••
ŜŜŜ
ʴʴʴ™‘”†•ʰƃɐ‡‡‡‹‡ɐřɐ‡‡‹‡ɐřɐ‹›ɐřɐɐƄ
ʴʴʴˆ‘”™‘”†‹™‘”†•ś
ŜŜŜ‹ˆ™‘”†Ŝ‹•—’’‡”ſƀś
ŜŜŜ”ƒ‹•‡’’‡” ƒ•‡š ‡’–‹‘ſ™‘”†ƀ
ŜŜŜ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɪř‹ʳ‘†—އʴ
ɏɏƒ‹ɏɏŜ’’‡” ƒ•‡š ‡’–‹‘ś
ǫȓȈȊȈǼțȕȒȞȐȐ  

Мы даже не определяли какое-то поведение для ’’‡” ƒ•‡š ‡’–‹‘ (обратите


внимание — мы просто использовали pass), позволив его родительскому классу
š ‡’–‹‘ самостоятельно разобраться, что именно выводить на экран при генерации
исключения.
Вы можете получить доступ к самому объекту исключения и вывести его на экран:
ʴʴʴ–”›ś
ŜŜŜ”ƒ‹•‡‘’•š ‡’–‹‘ſɐ’ƒ‹ ɐƀ
ŜŜŜ‡š ‡’–‘’•š ‡’–‹‘ƒ•‡š ś
ŜŜŜ’”‹–ſ‡š ƀ
ŜŜŜ
’ƒ‹

ǿȐȚȈȑȚȍȌȈȓȍȍ
Объекты! В книге, посвященной объектно-ориентированному языку, мы когда-ни-
будь обязаны были до них добраться.

ǻȗȘȈȎȕȍȕȐȧ
9.1. Определите функцию ‰‘‘†ſƀ , которая возвращает следующий список:
ƃɐ ƒ””›ɐř ɐ‘ɐř ɐ ‡”‹‘‡ɐƄ.
9.2. Определите функцию генератора ‰‡–ɏ‘††•ſƀ, которая возвращает нечетные
числа из диапазона ”ƒ‰‡ſɨɥƀ. Используйте цикл for, чтобы найти и вывести
третье возвращенное значение.
9.3. Определите декоратор test, который выводит строку ɐ•–ƒ”–ɐ при вызове функ-
ции и строку ɐ‡†ɐ, когда функция завершает свою работу.
9.4. Определите исключение ‘’•š ‡’–‹‘. Сгенерируйте его и посмотрите, что
произойдет. Затем напишите код, позволяющий поймать это исключение и вы-
вести строку ɐƒ—‰Š– an ‘‘’•ɐ.
ƋƓƈƊƈ
ǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ

Таинственных объектов не бывает. Они такими


просто кажутся.

Элизабет Боуэн

Возьмите объект. Сделайте с ним что-нибудь.


Добавьте к нему что-нибудь еще.

Джаспер Джонс

Как я уже говорил ранее, в Python все, от чисел до функций, является объектами.
Однако Python скрывает бо' льшую часть функционирования объектных механизмов
с помощью особого синтаксиса. Вы можете написать — ʰ 7, и, таким образом, у вас
появится объект типа int со значением 7 и назначится ссылка на объект по имени
— . Заглядывать внутрь объектов нужно только в случае, если вам необходимо
создать собственный объект или модифицировать поведение уже существующих.
В этой главе вы увидите, как сделать и то и другое.

ǿȚȖȚȈȒȖȍȖȉȢȍȒȚȣ
Объект — это пользовательская структура данных, которая содержит как данные
(переменные, называемые атрибутами), так и код (функции, называемые мето-
дами). Он представляет собой уникальный экземпляр чего-то конкретного. Можно
думать об объектах как о существительных, а об их методах — как о глаголах. Объект
представляет собой единичный экземпляр, методы определяют его взаимодействие
с другими объектами.
Например, целочисленный объект со значением 7 может использовать такие
методы, как сложение и умножение, что показано в главе 3. ɯ — другой объект.
Это значит, что существует класс –‡‰‡”, встроенный в Python, которому принад-
лежат объекты 7 и ɯ. Строки ɐ ƒ–ɐ и ɐ†— ɐ также являются объектами и имеют
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

методы, с которыми вы уже познакомились в главе 5, — например, ƒ’‹–ƒŽ‹œ‡ſƀ


и ”‡’Žƒ ‡ſƀ.
В отличие от модулей у вас одновременно может быть несколько объектов
(также называемых экземплярами), каждый из которых может иметь самые разные
атрибуты. Объекты — как суперструктуры данных, в которые был добавлен код.

ǷȘȖșȚȣȍȖȉȢȍȒȚȣ
Начнем мы с простых классов, а разговор о наследовании перенесем на несколько
страниц вперед.

ǶȗȘȍȌȍȓȧȍȔȒȓȈșșșȗȖȔȖȡȤȦȒȓȦȟȍȊȖȋȖșȓȖȊȈFODVV
Чтобы создать новый объект, который никто раньше не создавал, вам сначала нужно
определить класс, который укажет на то, что в объекте содержится.
В главе 2 я сравнил объект с пластмассовой коробкой. Класс похож на форму, по
образцу которой создается эта коробка. Например, в Python есть встроенный класс,
создающий строковые объекты, такие как ɐ ƒ–ɐ и ɐ†— ɐ. Python имеет и множество
других встроенных классов, позволяющих создавать другие стандартные типы дан-
ных, в том числе списки, словари и т. д. Чтобы создать собственный объект в Python,
вам сначала нужно определить класс с помощью ключевого слова Žƒ••. Рассмотрим
несколько простых примеров.
Предположим, вы хотите определить объекты для представления информации
о котах1. Каждый объект будет представлять одного кота. Сначала вам нужно опре-
делить класс ƒ– в качестве формы. В последующих примерах мы попробуем ис-
пользовать больше версий этого класса, продвигаясь от простейшего класса к тому,
который действительно может делать что-то полезное.

ǴȣșȓȍȌțȍȔȒȖȕȞȍȗȞȐȧȔȖȉȐȔȍȕȖȊȈȕȐȐțȒȈȏȈȕȕȣȔȊ3(3 KWWSVRUHLOO\J$-2) 

Для начала создадим самый простой из возможных классов — пустой:


ʴʴʴ Žƒ••ƒ–ſƀś
ŜŜŜ’ƒ••

Можно и так:
ʴʴʴ Žƒ••ƒ–ś
ŜŜŜ’ƒ••

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

1
Мы это сделаем, даже если вы не хотите.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

объекта. Вы создаете объект из класса, вызывая имя класса так, как если бы это
была функция:
ʴʴʴƒɏ ƒ–ʰƒ–ſƀ
ʴʴʴƒ‘–Ї”ɏ ƒ–ʰƒ–ſƀ

В этом случае вызов ƒ–ſƀ создаст два отдельных объекта класса ƒ–, и мы при-
своим им имена ƒɏ ƒ– и ƒ‘–Ї”ɏ ƒ–. Но наш класс ƒ– пуст, поэтому объекты,
которые мы создали, просто занимают место и ничего не делают.
Хотя нет, кое-что они могут.

ǨȚȘȐȉțȚȣ
Атрибут — это переменная, расположенная внутри класса или объекта. Во время
и после создания объекта или класса вы можете присвоить им атрибуты. Атрибутом
может быть любой другой объект. Давайте снова создадим два объекта типа ƒ–:
ʴʴʴ Žƒ••ƒ–ś
ŜŜŜ’ƒ••
ŜŜŜ
ʴʴʴƒɏ ƒ–ʰƒ–ſƀ
ʴʴʴƒɏ ƒ–
ʳɏɏƒ‹ɏɏŜƒ–‘„Œ‡ –ƒ–ɥšɨɥɥ †ɨ†ƒɥʴ
ʴʴʴƒ‘–Ї”ɏ ƒ–ʰƒ–ſƀ
ʴʴʴƒ‘–Ї”ɏ ƒ–
ʳɏɏƒ‹ɏɏŜƒ–‘„Œ‡ –ƒ–ɥšɨɥɥ †ɨ‡ɫɯʴ

Когда мы определили класс ƒ–, мы не указали, в каком виде его объект будет
выведен на экран. Тут в дело вмешивается Python и выводит на экран что-то вроде
ʳɏɏƒ‹ɏɏŜƒ– ‘„Œ‡ – at ɥšɨɥɥ †ɨ†ƒɥʴ. В разделе «Магические методы» на с. 215 вы
увидите, как можно изменить это поведение, используемое по умолчанию.
Теперь назначим несколько атрибутов нашему первому объекту:
ʴʴʴƒɏ ƒ–Ŝƒ‰‡ʰɪ
ʴʴʴƒɏ ƒ–Ŝƒ‡ʰɑ”Ŝ —œœ›„—––‘•ɑ
ʴʴʴƒɏ ƒ–Ŝ‡‡•‹•ʰƒ‘–Ї”ɏ ƒ–

Можем ли мы получить доступ к этим значениям? Надеюсь, что да:


ʴʴʴƒɏ ƒ–Ŝƒ‰‡
ɪ
ʴʴʴƒɏ ƒ–Ŝƒ‡
ɐ”Ŝ —œœ›„—––‘•ɐ
ʴʴʴƒɏ ƒ–Ŝ‡‡•‹•
ʳɏɏƒ‹ɏɏŜƒ–‘„Œ‡ –ƒ–ɥšɨɥɥ †ɨ‡ɫɯʴ

Поскольку ‡‡•‹• был атрибутом, ссылающимся на другой объект ƒ– , мы


можем использовать атрибут ƒɏ ƒ–Ŝ‡‡•‹• для доступа к нему. Но у этого другого
объекта еще нет атрибута ƒ‡:
ʴʴʴƒɏ ƒ–Ŝ‡‡•‹•Ŝƒ‡
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
––”‹„—–‡””‘”śɐƒ–ɐ‘„Œ‡ –Šƒ•‘ƒ––”‹„—–‡ɐƒ‡ɐ
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

Дадим имя нашему коту:


ʴʴʴƒɏ ƒ–Ŝ‡‡•‹•Ŝƒ‡ʰɑ”Ŝ‹‰‰Ž‡•™‘”–Šɑ
ʴʴʴƒɏ ƒ–Ŝ‡‡•‹•Ŝƒ‡
ɐ”Ŝ‹‰‰Ž‡•™‘”–Šɐ
Даже в подобных простейших объектах можно хранить несколько атрибутов.
Так что для хранения разных значений допускается использование нескольких
объектов вместо чего-то наподобие списка или словаря.
Когда вы слышите слово «атрибуты», речь, скорее всего, идет об атрибутах
объектов. Помимо этого, существуют также атрибуты класса. Чем они различаются,
вы увидите в подразделе «Атрибуты классов и объектов» на с. 210.

ǴȍȚȖȌȣ
Метод — это функция класса или объекта. Метод выглядит так же, как и любая
другая функция, но может быть использован особым образом — этот вопрос мы
рассмотрим далее в этой главе, в подразделе «Свойства для доступа к атрибутам»
и в разделе «Типы методов».

ǰȕȐȞȐȈȓȐȏȈȞȐȧ
Если вы хотите присвоить атрибуты объекту во время его создания, вам понадобится
специальный метод инициализации ɏɏ‹‹–ɏɏ:
ʴʴʴ Žƒ••ƒ–ś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆƀś
ŜŜŜ’ƒ••
Так выглядят реальные определения классов в Python. Согласен, ɏɏ‹‹–ɏɏſƀ
и self смотрятся странно. ɏɏ‹‹–ɏɏſƀ — это особое имя метода, который инициа-
лизирует отдельный объект с помощью определения его класса1. Аргумент self
указывает на сам объект.
Когда вы указываете ɏɏ‹‹–ɏɏſƀ в определении класса, его первым параметром
должен быть объект с именем self. Несмотря на то что в Python self не является
зарезервированным словом, оно применяется довольно часто. Никому из тех, кто
будет читать ваш код позже (включая вас!), не придется гадать, что вы имели в виду,
когда использовали слово self.
Но даже в этом случае второе определение класса ƒ– создает объект, который
ничего не делает. Наша третья попытка покажет, насколько легко создать простой
объект в Python и присвоить значение одному из его атрибутов. В этот раз мы до-
бавим параметр ƒ‡ в метод инициализации:
ʴʴʴ Žƒ••ƒ–ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰƒ‡
ŜŜŜ
ʴʴʴ

1
Вы встретите множество примеров двойных подчеркиваний в именах Python. Для эконо-
мии времени некоторые люди называют их dunder.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Теперь мы можем создать объект класса ƒ–, передав строку для параметра ƒ‡:
ʴʴʴˆ—”„ƒŽŽʰƒ–ſɐ ”—’›ɐƀ

Эта строка кода делает следующее:


‰выполняет поиск определения класса ƒ–;
‰инстанцирует (создает) новый объект в памяти;
‰вызывает метод объекта ɏɏ‹‹–ɏɏſƀ, передавая только что созданный объект под
именем self и другой аргумент (ɐ ”—’›ɐ) в качестве значения параметра ƒ‡;
‰сохраняет в объекте значение переменной ƒ‡;
‰возвращает новый объект;
‰прикрепляет к объекту переменную furball.
Этот новый объект похож на любой другой объект Python. Вы можете использо-
вать его как элемент списка, кортежа, словаря или множества. Можете передать его
в функцию как аргумент или вернуть в качестве результата.
А что со значением ƒ‡, которое мы передали? Оно было сохранено как атрибут
объекта. Вы можете прочитать и записать его непосредственно:
ʴʴʴ’”‹–ſɐ—”Žƒ–‡•–ƒ††‹–‹‘śɐřˆ—”„ƒŽŽŜƒ‡ƀ
—”Žƒ–‡•–ƒ††‹–‹‘ś ”—’›

Помните, внутри определения класса ƒ– вы получаете доступ к атрибуту ƒ‡ с по-
мощью конструкции •‡ŽˆŜƒ‡. Когда вы создаете реальный объект и присваиваете
его переменной вроде furball, то ссылаетесь на этот атрибут как ˆ—”„ƒŽŽŜƒ‡.
Не обязательно иметь метод ɏɏ‹‹–ɏɏſƀ в описании каждого класса — он исполь-
зуется для того, чтобы различать объекты одного класса. Это не то, что в некоторых
других языках называется конструктором. Python уже создал объект для вас. Метод
ɏɏ‹‹–ɏɏſƀ следует рассматривать скорее как средство инициализации.

ǪȣȔȖȎȍȚȍșȖȏȌȈȚȤȔȕȖȋȖȖȚȌȍȓȤȕȣȝȖȉȢȍȒȚȖȊȐȏȖȌȕȖȋȖȒȓȈșșȈǵȖȗȖȔȕȐȚȍȟȚȖ
Ȋ3\WKRQȌȈȕȕȣȍȘȍȈȓȐȏȖȊȈȕȣȒȈȒȖȉȢȍȒȚȣȗȖȥȚȖȔțȐșȈȔȒȓȈșșȧȊȓȧȍȚșȧȖȉȢȍȒȚȖȔ
ǶȌȕȈȒȖȊȊȈȠȍȑȗȘȖȋȘȈȔȔȍȔȖȎȍȚșțȡȍșȚȊȖȊȈȚȤȚȖȓȤȒȖȖȌȐȕȖȉȢȍȒȚȌȓȧȒȈȎȌȖȋȖ
ȒȓȈșșȈ ǭșȓȐ ȒȓȈșș &DW țȎȍ ȖȗȘȍȌȍȓȍȕ ȒȈȒ Ȕȣ șȌȍȓȈȓȐ Ȋ ȥȚȖȑ ȋȓȈȊȍ ȚȖ ȊȚȖȘȖȑ
ȚȈȒȖȑȒȓȈșșșȖȏȌȈȚȤȕȍȗȖȓțȟȐȚșȧǶȕșȚȈȕȖȊȐȚșȧȟȍȔȚȖȊȘȖȌȍǫȖȘȞȈ²ȌȖȓȎȍȕ
ȖșȚȈȚȤșȧȚȖȓȤȒȖȖȌȐȕ

ǵȈșȓȍȌȖȊȈȕȐȍ
Предположим, вы пытаетесь решить какую-то задачу и узнаете, что уже существует
класс, создающий объекты, которые делают почти все из того, что вам нужно. Как по-
ступить? Вы можете модифицировать данный класс: однако при этом вы сделаете
его более сложным и, вполне вероятно, испортите то, что раньше работало.
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

Или можно написать новый класс, скопировав и вставив содержимое старого


класса, а затем дополнить его новым кодом. Но это значит, что вам придется под-
держивать больше кода, а части старого и нового классов, которые раньше работали
одинаково, могут оказаться непохожими друг на друга, поскольку теперь находятся
в разных местах.
Одним из решений проблемы является наследование — создание нового класса
из уже существующего, но с некоторыми дополнениями и изменениями. Это хоро-
ший способ использовать код повторно. Когда вы применяете наследование, новый
класс может автоматически использовать весь код старого класса, но вам при этом
не нужно его копировать.

ǵȈșȓȍȌȖȊȈȕȐȍȖȚȘȖȌȐȚȍȓȤșȒȖȋȖȒȓȈșșȈ
Вы определяете только то, что вам нужно добавить или изменить в новом классе,
и этот код переопределяет поведение старого класса. Оригинальный класс назы-
вается родительским классом, суперклассом или базовым классом, а новый класс
именуется потомком, подклассом или производным классом. Эти термины в объек-
тно-ориентированном программировании взаимозаменяемы.
Итак, попробуем что-нибудь унаследовать. В следующем примере мы определим
пустой класс, который называется ƒ”. Далее мы определим подкласс класса ƒ”,
который называется —‰‘1. Вы определяете подкласс с помощью все того же клю-
чевого слова Žƒ••, но указываете внутри скобок имя родительского класса Žƒ••
—‰‘ſƒ”ƀ, как показано ниже:
ʴʴʴ Žƒ••ƒ”ſƀś
ŜŜŜ’ƒ••
ŜŜŜ
ʴʴʴ Žƒ••—‰‘ſƒ”ƀś
ŜŜŜ’ƒ••
ŜŜŜ

Проверить, унаследован ли класс от другого класса, можно с помощью функции


‹••—„ Žƒ••ſƀ:
ʴʴʴ‹••—„ Žƒ••ſ—‰‘řƒ”ƀ
”—‡

Далее создадим объекты каждого класса:


ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ ƒ”ʰƒ”ſƀ
ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ›—‰‘ʰ—‰‘ſƀ

Производный класс выступает уточненной версией родительского класса:


если говорить в терминах объектно-ориентированных языков, —‰‘ является ƒ”.
Объект с именем ‰‹˜‡ɏ‡ɏƒɏ›—‰‘ — это экземпляр класса —‰‘, но он также наследу-
ет все то, что может делать класс ƒ”. В нашем случае классы ƒ” и —‰‘ абсолютно

1
Недорогая и не очень качественная машина 1980-х годов.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

бесполезны, поэтому попробуем новые определения, которые действительно могут


что-то сделать:
ʴʴʴ Žƒ••ƒ”ſƀś
ŜŜŜ†‡ˆ‡š Žƒ‹ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɑ ɐƒƒ”Šɑƀ
ŜŜŜ
ʴʴʴ Žƒ••—‰‘ſƒ”ƀś
ŜŜŜ’ƒ••
ŜŜŜ

Наконец, создадим по одному объекту каждого класса и вызовем их методы


‡š Žƒ‹:
ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ ƒ”ʰƒ”ſƀ
ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ›—‰‘ʰ—‰‘ſƀ
ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ ƒ”Ŝ‡š Žƒ‹ſƀ
ɐƒƒ”Š
ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ›—‰‘Ŝ‡š Žƒ‹ſƀ
ɐƒƒ”Š

Не сделав ничего особенного, класс —‰‘ унаследовал метод ‡š Žƒ‹ſƀ класса ƒ”.
Фактически класс —‰‘ говорит, что он является классом ƒ”, а это может привести
к кризису самоопределения. Посмотрим, как решить проблему.

ǻȚȈȒȖȋȖȗȘȐȍȔȈȒȈȒȕȈșȓȍȌȖȊȈȕȐȍȍșȚȤȖȗȘȍȌȍȓȍȕȕȣȍȗȘȍȐȔțȡȍșȚȊȈȕȖȐȕȖȋȌȈ
ȐȔȗȖȓȤȏțȦȚșȧșȓȐȠȒȖȔȟȈșȚȖǴȕȖȋȖȓȍȚȕȐȑȖȗȣȚȘȈȉȖȚȣȊȖȉȢȍȒȚȕȖȖȘȐȍȕȚȐȘȖ
ȊȈȕȕȖȔ ȗȘȖȋȘȈȔȔȐȘȖȊȈȕȐȐ ȗȖȒȈȏȈȓ ȟȚȖ ȟȘȍȏȔȍȘȕȖȍ țȊȓȍȟȍȕȐȍ ȕȈșȓȍȌȖȊȈȕȐȍȔ
ȔȖȎȍȚȏȈȚȘțȌȕȐȚȤțȗȘȈȊȓȍȕȐȍȗȘȖȋȘȈȔȔȈȔȐǪȔȍșȚȖȥȚȖȋȖȘȍȒȖȔȍȕȌțȍȚșȧșȌȍȓȈȚȤ
ȈȒȞȍȕȚȕȈȐșȗȖȓȤȏȖȊȈȕȐȐȌȘțȋȐȝȗȘȐȍȔȖȊȚȈȒȐȝȒȈȒȈȋȘȍȋȐȘȖȊȈȕȐȍȐȒȖȔȗȖȏȐȞȐȧ
ǰȝȔȣȘȈșșȔȖȚȘȐȔȚȈȒȎȍȊȥȚȖȑȋȓȈȊȍ

ǷȍȘȍȖȗȘȍȌȍȓȍȕȐȍȔȍȚȖȌȖȊ
Как вы только что увидели, новый класс изначально наследует все, что находится
в его родительском классе. Далее вы узнаете, как можно заменить, или переопреде-
лить, родительские методы. Класс —‰‘ должен как-то отличаться от класса ƒ”, ина-
че зачем вообще создавать новый класс. Изменим способ работы метода ‡š Žƒ‹ſƀ
для класса —‰‘:
ʴʴʴ Žƒ••ƒ”ſƀś
ŜŜŜ†‡ˆ‡š Žƒ‹ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɑ ɐƒƒ”Šɑƀ
ŜŜŜ
ʴʴʴ Žƒ••—‰‘ſƒ”ƀś
ŜŜŜ†‡ˆ‡š Žƒ‹ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɑ ɐƒ—‰‘Š— ŠŽ‹‡ƒƒ”ř„—–‘”‡—‰‘Ş‹•ŠŜɑƀ
ŜŜŜ
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

Теперь создадим объекты этих классов:


ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ ƒ”ʰƒ”ſƀ
ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ›—‰‘ʰ—‰‘ſƀ

Что они говорят?


ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ ƒ”Ŝ‡š Žƒ‹ſƀ
ɐƒƒ”Š
ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ›—‰‘Ŝ‡š Žƒ‹ſƀ
ɐƒ—‰‘Š— ŠŽ‹‡ƒƒ”ř„—–‘”‡—‰‘Ş‹•ŠŜ

В этих примерах мы переопределили метод ‡š Žƒ‹ſƀ. Переопределять можно лю-


бые методы, включая ɏɏ‹‹–ɏɏſƀ. Вот еще один пример — с классом ‡”•‘. Создадим
подклассы, которые представляют докторов (‡”•‘) и адвокатов ( ‡”•‘):
ʴʴʴ Žƒ••‡”•‘ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰƒ‡
ŜŜŜ
ʴʴʴ Žƒ••‡”•‘ſ‡”•‘ƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰɑ‘ –‘”ɑʫƒ‡
ŜŜŜ
ʴʴʴ Žƒ•• ‡”•‘ſ‡”•‘ƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰƒ‡ʫɑř•“—‹”‡ɑ
ŜŜŜ

В этих случаях метод инициализации ɏɏ‹‹–ɏɏſƀ принимает те же аргументы,


что и родительский класс ‡”•‘, но по-разному сохраняет значение переменной
ƒ‡ внутри объекта:
ʴʴʴ’‡”•‘ʰ‡”•‘ſɐ —††ɐƀ
ʴʴʴ†‘ –‘”ʰ‡”•‘ſɐ —††ɐƀ
ʴʴʴŽƒ™›‡”ʰ ‡”•‘ſɐ —††ɐƀ
ʴʴʴ’”‹–ſ’‡”•‘Ŝƒ‡ƀ
—††
ʴʴʴ’”‹–ſ†‘ –‘”Ŝƒ‡ƀ
‘ –‘” —††
ʴʴʴ’”‹–ſŽƒ™›‡”Ŝƒ‡ƀ
—††ř•“—‹”‡

ǬȖȉȈȊȓȍȕȐȍȔȍȚȖȌȈ
В производный класс можно добавить и метод, которого не было в родительском
классе. Вернемся к классам ƒ” и —‰‘ и определим новый метод ‡‡†ɏƒɏ’—•Šſƀ
только для класса —‰‘:
ʴʴʴ Žƒ••ƒ”ſƀś
ŜŜŜ†‡ˆ‡š Žƒ‹ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɑ ɐƒƒ”Šɑƀ
ŜŜŜ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ʴʴʴ Žƒ••—‰‘ſƒ”ƀś
ŜŜŜ†‡ˆ‡š Žƒ‹ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɑ ɐƒ—‰‘Š— ŠŽ‹‡ƒƒ”ř„—–‘”‡—‰‘Ş‹•ŠŜɑƀ
ŜŜŜ†‡ˆ‡‡†ɏƒɏ’—•Šſ•‡Žˆƀś
ŜŜŜ’”‹–ſɑŽ‹––އЇޒЇ”‡ţɑƀ
ŜŜŜ

Далее создадим объекты классов ƒ” и —‰‘:


ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ ƒ”ʰƒ”ſƀ
ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ›—‰‘ʰ—‰‘ſƀ

Объект класса —‰‘ может реагировать на вызов метода ‡‡†ɏƒɏ’—•Šſƀ:


ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ›—‰‘Ŝ‡‡†ɏƒɏ’—•Šſƀ
Ž‹––އЇޒЇ”‡ţ

А объект общего класса ƒ” — нет:


ʴʴʴ‰‹˜‡ɏ‡ɏƒɏ ƒ”Ŝ‡‡†ɏƒɏ’—•Šſƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
––”‹„—–‡””‘”śɐƒ”ɐ‘„Œ‡ –Šƒ•‘ƒ––”‹„—–‡ɐ‡‡†ɏƒɏ’—•Šɐ

К этому моменту класс —‰‘ может делать то, чего не может делать класс ƒ”,
и, таким образом, мы ясно видим отличительные особенности класса —‰‘.

ǷȖȓțȟȈȍȔȗȖȔȖȡȤȖȚșȊȖȍȋȖȘȖȌȐȚȍȓȧ
șȐșȗȖȓȤȏȖȊȈȕȐȍȔȔȍȚȖȌȈVXSHU
Мы видели, как производный класс может добавить или переопределить метод
родительского класса. Но что, если нужно будет вызвать этот родительский метод?
«Рад, что вы спросили», — говорит метод •—’‡”ſƀ. Сейчас мы определим новый класс
ƒ‹Ž‡”•‘, который представляет объект класса ‡”•‘ с адресом электронной по-
чты. Для начала запишем наше привычное определение класса ‡”•‘:
ʴʴʴ Žƒ••‡”•‘ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰƒ‡
ŜŜŜ

Обратите внимание на то, что вызов метода ɏɏ‹‹–ɏɏſƀ в следующем подклассе


имеет дополнительный параметр ‡ƒ‹Ž:
ʴʴʴ Žƒ••ƒ‹Ž‡”•‘ſ‡”•‘ƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ř‡ƒ‹Žƀś
ŜŜŜ•—’‡”ſƀŜɏɏ‹‹–ɏɏſƒ‡ƀ
ŜŜŜ•‡ŽˆŜ‡ƒ‹Žʰ‡ƒ‹Ž

Когда вы определяете метод ɏɏ‹‹–ɏɏſƀ для своего класса, вы заменяете метод


ɏɏ‹‹–ɏɏſƀ родительского класса, который больше не вызывается автоматически.
В результате вам нужно вызывать его явно. Происходит следующее:
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

‰метод •—’‡”ſƀ получает определение родительского класса ‡”•‘;


‰метод ɏɏ‹‹–ɏɏſƀ вызывает метод ‡”•‘Ŝɏɏ‹‹–ɏɏſƀ. Последний заботится о том,
чтобы передать аргумент self суперклассу, поэтому вам нужно просто дать ему
любые необязательные аргументы. В нашем случае единственным аргументом
класса ‡”•‘ſƀ будет ƒ‡;
‰строка •‡ŽˆŜ‡ƒ‹Ž ʰ ‡ƒ‹Ž — это новый код, который отличает класс ƒ‹Ž‡”•‘
от класса ‡”•‘.
Теперь создадим одну персону:
ʴʴʴ„‘„ʰƒ‹Ž‡”•‘ſɐ‘„ ”ƒ’’އ•ɐřɐ„‘„ɒˆ”ƒ’’އ•Ŝ ‘ɐƀ

Мы должны иметь доступ к атрибутам ƒ‡ и ‡ƒ‹Ž:


ʴʴʴ„‘„Ŝƒ‡
ɐ‘„ ”ƒ’’އ•ɐ
ʴʴʴ„‘„Ŝ‡ƒ‹Ž
ɐ„‘„ɒˆ”ƒ’’އ•Ŝ ‘ɐ

Почему бы нам просто не определить новый класс так, как показано далее?
ʴʴʴ Žƒ••ƒ‹Ž‡”•‘ſ‡”•‘ƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ř‡ƒ‹Žƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰƒ‡
ŜŜŜ•‡ŽˆŜ‡ƒ‹Žʰ‡ƒ‹Ž

Мы могли бы это сделать, но тогда потеряли бы возможность применять наследо-


вание. Мы использовали метод •—’‡”ſƀ, чтобы заставить ‡”•‘ делать свою работу
так же, как это делает обычный объект класса ‡”•‘. Есть и другое преимущество:
если определение класса ‡”•‘ в будущем изменится, с помощью метода •—’‡”ſƀ
мы сможем гарантировать, что атрибуты и методы, которые класс ƒ‹Ž‡”•‘ на-
следует от класса ‡”•‘, отреагируют на изменения.
Используйте метод •—’‡”ſƀ, когда потомок делает что-то по-своему, но все еще
нуждается в помощи родителя (как и в реальной жизни).

ǴȕȖȎȍșȚȊȍȕȕȖȍȕȈșȓȍȌȖȊȈȕȐȍ
Вы только что видели несколько примеров классов, у которых нет родительского
класса, и несколько примеров, у которых есть. Однако объекты могут наследовать
и от нескольких родительских классов.
Если ваш класс ссылается на метод или атрибут, которого у него нет, Python
будет искать его в родительском классе. Что, если у нескольких классов будут атри-
буты с одинаковыми именами? Кто победит?
В отличие от наследования у людей, когда доминантный ген побеждает незави-
симо от того, кому он принадлежит, наследование в Python зависит от порядка раз-
решения методов. Каждый класс Python имеет особый метод ”‘ſƀ, возвращающий
список классов, в которых будет выполнен поиск метода или атрибута для объекта
этого класса. Похожий атрибут с именем ɏɏ”‘ɏɏ представляет собой кортеж, содер-
жащий имена этих классов. Как и в плей-офф, когда действует принцип «внезапной
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

смерти», побеждает первый. Сейчас мы определим родительский класс ‹ƒŽ, два


класса-потомка ( ‘”•‡ и ‘‡›), а затем еще два класса, полученных из них1:
ʴʴʴ Žƒ••‹ƒŽś
ŜŜŜ†‡ˆ•ƒ›•ſ•‡Žˆƀś
”‡–—”ɐ •’‡ƒŠɐ
ŜŜŜ
ʴʴʴ Žƒ•• ‘”•‡ſ‹ƒŽƀś
ŜŜŜ†‡ˆ•ƒ›•ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ‡‹‰ŠŠɐ
ŜŜŜ
ʴʴʴ Žƒ••‘‡›ſ‹ƒŽƀś
ŜŜŜ†‡ˆ•ƒ›•ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ ‡‡ŞŠƒ™Šɐ
ŜŜŜ
ʴʴʴ Žƒ••—އſ‘‡›ř ‘”•‡ƀś
ŜŜŜ’ƒ••
ŜŜŜ
ʴʴʴ Žƒ•• ‹›ſ ‘”•‡ř‘‡›ƀś
ŜŜŜ’ƒ••
ŜŜŜ

Если нам понадобится метод или атрибут класса —އ, Python будет искать его
в следующих классах по порядку.
1. Сам объект (типа —އ).
2. Класс объекта (—އ).
3. Первый родительский класс этого класса (‘‡›).
4. Второй родительский класс этого класса ( ‘”•‡).
5. Прародительский класс этого класса (‹ƒŽ).
Для класса ‹› список выглядит примерно так же, только класс ‘”•‡ распо-
ложится перед классом ‘‡›:
ʴʴʴ—އŜ”‘ſƀ
ƃʳ Žƒ••ɐɏɏƒ‹ɏɏŜ—އɐʴřʳ Žƒ••ɐɏɏƒ‹ɏɏŜ‘‡›ɐʴř
ʳ Žƒ••ɐɏɏƒ‹ɏɏŜ ‘”•‡ɐʴřʳ Žƒ••ɐɏɏƒ‹ɏɏŜ‹ƒŽɐʴř
ʳ Žƒ••ɐ‘„Œ‡ –ɐʴƄ
ʴʴʴ ‹›Ŝ”‘ſƀ
ƃʳ Žƒ••ɐɏɏƒ‹ɏɏŜ ‹›ɐʴřʳ Žƒ••ɐɏɏƒ‹ɏɏŜ ‘”•‡ɐʴř
ʳ Žƒ••ɐɏɏƒ‹ɏɏŜ‘‡›ɐʴřʳ Žƒ••ɐɏɏƒ‹ɏɏŜ‹ƒŽɐʴř
Žƒ••ɐ‘„Œ‡ –ɐʴƄ

Так что же говорят эти прекрасные животные?


ʴʴʴ—އʰ—އſƀ
ʴʴʴŠ‹›ʰ ‹›ſƀ
ʴʴʴ—އŜ•ƒ›•ſƀ
ɐЇ‡ŞŠƒ™ɐ
ʴʴʴŠ‹›Ŝ•ƒ›•ſƀ
ɐ‡‹‰Šɐ

1
У мула (mule) папа — осел, а мама — лошадь. У лошака (hinny) папа — конь, а мама — ослица.
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

Мы перечислили родительские классы в порядке «папа, мама», чтобы они раз-


говаривали как «папы». Если бы у классов ‘”•‡ и ‘‡› не было метода •ƒ›•ſƀ,
классы —އ и ‹› использовали бы метод •ƒ›•ſƀ прародительского класса ‹ƒŽ
и возвратили бы значение ɐ •’‡ƒŠɐ.

ǷȘȐȔȍșȐ
Вы можете включить дополнительный родительский класс в определение вашего
класса, но только в качестве вспомогательного. Таким образом, он не будет иметь
общих методов с другими родительскими классами, что позволит избежать неодно-
значности при разрешении методов, о которой я говорил ранее.
Такой родительский класс называют классом-примесью или миксином. Приме-
си можно использовать для выполнения «сторонних» задач, таких, например, как
ведение журнала. Рассмотрим класс-примесь, который форматирует и выводит на
экран атрибуты объекта:
ʴʴʴ Žƒ••”‡––›‹š‹ſƀś
ŜŜŜ†‡ˆ†—’ſ•‡Žˆƀś
ŜŜŜ‹’‘”–’’”‹–
ŜŜŜ’’”‹–Ŝ’’”‹–ſ˜ƒ”•ſ•‡Žˆƀƀ
ŜŜŜ
ʴʴʴ Žƒ••Š‹‰ſ”‡––›‹š‹ƀś
ŜŜŜ’ƒ••
ŜŜŜ
ʴʴʴ–ʰŠ‹‰ſƀ
ʴʴʴ–Ŝƒ‡ʰɑ›ƒ”Žƒ–Š‘–‡’ɑ
ʴʴʴ–Ŝˆ‡ƒ–—”‡ʰɑ‹ Š‘”ɑ
ʴʴʴ–Ŝƒ‰‡ʰɑ‡Ž†”‹– Šɑ
ʴʴʴ–Ŝ†—’ſƀ
Ƈɐƒ‰‡ɐśɐ‡Ž†”‹– Šɐřɐˆ‡ƒ–—”‡ɐśɐ‹ Š‘”ɐřɐƒ‡ɐśɐ›ƒ”Žƒ–Š‘–‡’ɐƈ

ǪȏȈȡȐȚțVHOI
Помимо применения пробелов, Python критикуют и за то, что необходимо вклю-
чать self в качестве первого аргумента методов экземпляра класса (методов,
которые вы видели в предыдущих примерах). Python использует аргумент self,
чтобы найти атрибуты и методы правильного объекта. Например, я покажу, как
вы можете вызвать метод объекта и что Python при этом сделает за кулисами на
самом деле.
Помните класс ƒ” из предыдущих примеров? Снова вызовем метод ‡š Žƒ‹ſƀ:
ʴʴʴƒɏ ƒ”ʰƒ”ſƀ
ʴʴʴƒɏ ƒ”Ŝ‡š Žƒ‹ſƀ
ɐƒƒ”Š

Вот что происходит за кулисами Python.


‰Выполняется поиск класса (ƒ”) объекта ƒɏ ƒ”.
‰Объект ƒɏ ƒ” передается методу ‡š Žƒ‹ſƀ класса ƒ” как параметр self.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Ради развлечения вы и сами можете запустить пример таким образом, и он сра-


ботает точно так же, как и нормальный синтаксис (ƒɏ ƒ”Ŝ‡š Žƒ‹ſƀ):
ʴʴʴƒ”Ŝ‡š Žƒ‹ſ ƒ”ƀ
ɐƒƒ”Š

Тем не менее нет никаких причин использовать этот более длинный стиль.

ǬȖșȚțȗȒȈȚȘȐȉțȚȈȔ
В Python атрибуты объектов и методы обычно являются общедоступными, поэтому
предполагается, что тот, кто их использует, не станет этим злоупотреблять (это ино-
гда называют «установкой на взрослых людей»). Давайте сравним прямой доступ
и его альтернативы.

ǷȘȧȔȖȑȌȖșȚțȗ
Как вы уже видели, вы можете получать и задавать значения атрибутов напрямую:
ʴʴʴ Žƒ••— ś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř‹’—–ɏƒ‡ƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰ‹’—–ɏƒ‡
ŜŜŜ
ʴʴʴˆ‘™Žʰ— ſɐƒˆˆ›ɐƀ
ʴʴʴˆ‘™ŽŜƒ‡
ɐƒˆˆ›ɐ

Но что случится, если кто-то решит этим злоупотребить?


ʴʴʴˆ‘™ŽŜƒ‡ʰɐƒ’А‡ɐ
ʴʴʴˆ‘™ŽŜƒ‡
ɐƒ’А‡ɐ

В следующих двух подразделах показаны способы обеспечения определенной


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

ǫȍȚȚȍȘȣȐșȍȚȚȍȘȣ
Отдельные объектно-ориентированные языки поддерживают закрытые атрибуты
объектов, к которым нельзя получить доступ напрямую. Программистам часто при-
ходится писать геттеры и сеттеры, чтобы прочитать и записать значения таких
атрибутов.
В Python нет закрытых атрибутов, но вы можете написать геттеры и сеттеры для
атрибутов с обфусцированными именами, чтобы создать нечто подобное (Лучшим
решением будет использование свойств, они описаны в следующем подразделе.)
Далее в примере мы определим класс — , имеющий один атрибут экземпляра
Š‹††‡ɏƒ‡. Мы не хотим, чтобы кто-то мог обратиться к атрибуту напрямую, по-
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

этому определим два метода: геттер (‰‡–ɏƒ‡ſƀ) и сеттер (•‡–ɏƒ‡ſƀ). К каждому


из них обращается свойство с именем ƒ‡. Я добавил выражение ’”‹–ſƀ в оба
метода, чтобы показать момент его вызова:
ʴʴʴ Žƒ••— ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř‹’—–ɏƒ‡ƀś
ŜŜŜ•‡ŽˆŜŠ‹††‡ɏƒ‡ʰ‹’—–ɏƒ‡
ŜŜŜ†‡ˆ‰‡–ɏƒ‡ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɐ‹•‹†‡–Ї‰‡––‡”ɐƀ
ŜŜŜ”‡–—”•‡ŽˆŜŠ‹††‡ɏƒ‡
ŜŜŜ†‡ˆ•‡–ɏƒ‡ſ•‡Žˆř‹’—–ɏƒ‡ƀś
ŜŜŜ’”‹–ſɐ‹•‹†‡–Ї•‡––‡”ɐƀ
ŜŜŜ•‡ŽˆŜŠ‹††‡ɏƒ‡ʰ‹’—–ɏƒ‡

ʴʴʴ†‘ʰ— ſɐ‘ƒŽ†ɐƀ
ʴʴʴ†‘Ŝ‰‡–ɏƒ‡ſƀ
‹•‹†‡–Ї‰‡––‡”
ɐ‘ƒŽ†ɐ
ʴʴʴ†‘Ŝ•‡–ɏƒ‡ſɐ‘ƒɐƀ
‹•‹†‡–Ї•‡––‡”
ʴʴʴ†‘Ŝ‰‡–ɏƒ‡ſƀ
‹•‹†‡–Ї‰‡––‡”
ɐ‘ƒɐ

ǹȊȖȑșȚȊȈȌȓȧȌȖșȚțȗȈȒȈȚȘȐȉțȚȈȔ
Более питонским решением для закрытия атрибутов является использование
свойств.
Существует два способа сделать это. Первый — добавить конструкцию ƒ‡ ʰ ’”‘Ş
’‡”–›ſ‰‡–ɏƒ‡ř •‡–ɏƒ‡ƀ последней строкой в предыдущее определение клас-
са — :
ʴʴʴ Žƒ••— ſƀś
ʴʴʴ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř‹’—–ɏƒ‡ƀś
ʴʴʴ•‡ŽˆŜŠ‹††‡ɏƒ‡ʰ‹’—–ɏƒ‡
ʴʴʴ†‡ˆ‰‡–ɏƒ‡ſ•‡Žˆƀś
ʴʴʴ’”‹–ſɐ‹•‹†‡–Ї‰‡––‡”ɐƀ
ʴʴʴ”‡–—”•‡ŽˆŜŠ‹††‡ɏƒ‡
ʴʴʴ†‡ˆ•‡–ɏƒ‡ſ•‡Žˆř‹’—–ɏƒ‡ƀś
ʴʴʴ’”‹–ſɐ‹•‹†‡–Ї•‡––‡”ɐƀ
ʴʴʴ•‡ŽˆŜŠ‹††‡ɏƒ‡ʰ‹’—–ɏƒ‡
ʴʴʴƒ‡ʰ’”‘’‡”–›ſ‰‡–ɏƒ‡ř•‡–ɏƒ‡ƀ

Старый подход с геттерами и сеттерами тоже сработает:


ʴʴʴ†‘ʰ— ſɐ‘ƒŽ†ɐƀ
ʴʴʴ†‘Ŝ‰‡–ɏƒ‡ſƀ
‹•‹†‡–Ї‰‡––‡”
ɐ‘ƒŽ†ɐ
ʴʴʴ†‘Ŝ•‡–ɏƒ‡ſɐ‘ƒɐƀ
‹•‹†‡–Ї•‡––‡”
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ʴʴʴ†‘Ŝ‰‡–ɏƒ‡ſƀ
‹•‹†‡–Ї‰‡––‡”
ɐ‘ƒɐ

Но теперь вы также можете использовать свойство ƒ‡, чтобы получить и уста-


новить скрытое имя:
ʴʴʴ†‘ʰ— ſɐ‘ƒŽ†ɐƀ
ʴʴʴ†‘Ŝƒ‡
‹•‹†‡–Ї‰‡––‡”
ɐ‘ƒŽ†ɐ
ʴʴʴ†‘Ŝƒ‡ʰɐ‘ƒɐ
‹•‹†‡–Ї•‡––‡”
ʴʴʴ†‘Ŝƒ‡
‹•‹†‡–Ї‰‡––‡”
ɐ‘ƒɐ

Во втором методе вы добавляете декораторы и заменяете имена методов ‰‡–ɏƒ‡


и •‡–ɏƒ‡ на ƒ‡:
‰ɒ’”‘’‡”–› — размещается перед геттером;
‰ɒƒ‡Ŝ•‡––‡” — размещается перед сеттером.
В коде они выглядят так:
ʴʴʴ Žƒ••— ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř‹’—–ɏƒ‡ƀś
ŜŜŜ•‡ŽˆŜŠ‹††‡ɏƒ‡ʰ‹’—–ɏƒ‡
ŜŜŜɒ’”‘’‡”–›
ŜŜŜ†‡ˆƒ‡ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɐ‹•‹†‡–Ї‰‡––‡”ɐƀ
ŜŜŜ”‡–—”•‡ŽˆŜŠ‹††‡ɏƒ‡
ŜŜŜɒƒ‡Ŝ•‡––‡”
ŜŜŜ†‡ˆƒ‡ſ•‡Žˆř‹’—–ɏƒ‡ƀś
ŜŜŜ’”‹–ſɐ‹•‹†‡–Ї•‡––‡”ɐƀ
ŜŜŜ•‡ŽˆŜŠ‹††‡ɏƒ‡ʰ‹’—–ɏƒ‡

Вы все еще можете получить доступ к ƒ‡, как будто это атрибут:
ʴʴʴˆ‘™Žʰ— ſɐ ‘™ƒ”†ɐƀ
ʴʴʴˆ‘™ŽŜƒ‡
‹•‹†‡–Ї‰‡––‡”
ɐ ‘™ƒ”†ɐ
ʴʴʴˆ‘™ŽŜƒ‡ʰɐ‘ƒŽ†ɐ
‹•‹†‡–Ї•‡––‡”
ʴʴʴˆ‘™ŽŜƒ‡
‹•‹†‡–Ї‰‡––‡”
ɐ‘ƒŽ†ɐ

ǭșȓȐȒȚȖȚȖȐȌȖȋȈȌȈȍȚșȧȟȚȖȔȣȕȈȏȊȈȓȐȕȈȠȈȚȘȐȉțȚKLGGHQBQDPHșȟȐȚȈȚȤȐȏȈ
ȗȐșȈȚȤȍȋȖȖȕȊșȍȘȈȊȕȖȔȖȎȍȚȕȍȗȖșȘȍȌșȚȊȍȕȕȖȒȈȒIRZOKLGGHQBQDPHǪȗȖȌȘȈȏ
Ȍȍȓȍ©ǰșȒȈȎȍȕȐȍȐȔȍȕȌȓȧȉȍȏȖȗȈșȕȖșȚȐªȌȈȓȍȍȊȥȚȖȑȋȓȈȊȍȊȣțȊȐȌȐȚȍȖșȖȉȣȑ
șȗȖșȖȉ3\WKRQȗȖȏȊȖȓȧȦȡȐȑșȒȘȣȚȤȐȔȍȕȈȈȚȘȐȉțȚȖȊ
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

ǹȊȖȑșȚȊȈȌȓȧȊȣȟȐșȓȧȍȔȣȝȏȕȈȟȍȕȐȑ
В предыдущих примерах мы использовали свойство ƒ‡, чтобы обратиться к от-
дельному атрибуту (в нашем случае Š‹††‡ɏƒ‡), который хранится внутри объекта.
Свойство может возвращать и вычисляемое значение. Определим класс ‹” އ,
который имеет атрибут ”ƒ†‹—• и вычисляемое свойство †‹ƒ‡–‡”:
ʴʴʴ Žƒ••‹” އſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř”ƒ†‹—•ƀś
ŜŜŜ•‡ŽˆŜ”ƒ†‹—•ʰ”ƒ†‹—•
ŜŜŜɒ’”‘’‡”–›
ŜŜŜ†‡ˆ†‹ƒ‡–‡”ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɩƋ•‡ŽˆŜ”ƒ†‹—•
ŜŜŜ
Мы создаем объект класса ‹” އ, задав значение его атрибута ”ƒ†‹—•:
ʴʴʴ ʰ‹” އſɬƀ
ʴʴʴ Ŝ”ƒ†‹—•
ɬ
Мы можем обратиться к свойству †‹ƒ‡–‡” точно так же, как если бы это был
атрибут, подобный ”ƒ†‹—•:
ʴʴʴ Ŝ†‹ƒ‡–‡”
ɨɥ
А вот и самое интересное — мы можем изменить значение атрибута ”ƒ†‹—• в лю-
бой момент, и свойство †‹ƒ‡–‡” будет рассчитано на основе текущего значения
атрибута ”ƒ†‹—•:
ʴʴʴ Ŝ”ƒ†‹—•ʰ7
ʴʴʴ Ŝ†‹ƒ‡–‡”
ɨɫ
Если вы не укажете сеттер для атрибута, то не сможете устанавливать его значе-
ние извне. Это удобно для атрибутов, которые должны быть доступны только для
чтения:
ʴʴʴ Ŝ†‹ƒ‡–‡”ʰɩɥ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
––”‹„—–‡””‘”ś ƒɐ–•‡–ƒ––”‹„—–‡
У использования свойств вместо непосредственного доступа к атрибутам имеется
еще одно преимущество: если вы измените определение атрибута, вам нужно будет
поправить только код внутри определения класса вместо того, чтобы править все
вызовы.

ǰșȒȈȎȍȕȐȍȐȔȍȕȌȓȧȉȍȏȖȗȈșȕȖșȚȐ
В рассмотренном ранее примере с классом —  мы назвали наш (не полностью)
скрытый атрибут Š‹††‡ɏƒ‡. Python предлагает соглашения по именованию для
атрибутов, которые не должны быть видимы за пределами определения их классов:
имена начинаются с двух нижних подчеркиваний (ɏɏ).
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Переименуем атрибут Š‹††‡ɏƒ‡ в ɏɏƒ‡, как показано здесь:


ʴʴʴ Žƒ••— ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř‹’—–ɏƒ‡ƀś
ŜŜŜ•‡ŽˆŜɏɏƒ‡ʰ‹’—–ɏƒ‡
ŜŜŜɒ’”‘’‡”–›
ŜŜŜ†‡ˆƒ‡ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɐ‹•‹†‡–Ї‰‡––‡”ɐƀ
ŜŜŜ”‡–—”•‡ŽˆŜɏɏƒ‡
ŜŜŜɒƒ‡Ŝ•‡––‡”
ŜŜŜ†‡ˆƒ‡ſ•‡Žˆř‹’—–ɏƒ‡ƀś
ŜŜŜ’”‹–ſɐ‹•‹†‡–Ї•‡––‡”ɐƀ
ŜŜŜ•‡ŽˆŜɏɏƒ‡ʰ‹’—–ɏƒ‡
ŜŜŜ

Теперь проверим, работает ли все так, как нужно:


ʴʴʴˆ‘™Žʰ— ſɐ ‘™ƒ”†ɐƀ
ʴʴʴˆ‘™ŽŜƒ‡
‹•‹†‡–Ї‰‡––‡”
ɐ ‘™ƒ”†ɐ
ʴʴʴˆ‘™ŽŜƒ‡ʰɐ‘ƒŽ†ɐ
‹•‹†‡–Ї•‡––‡”
ʴʴʴˆ‘™ŽŜƒ‡
‹•‹†‡–Ї‰‡––‡”
ɐ‘ƒŽ†ɐ

Выглядит неплохо. И вы не можете получить доступ к атрибуту ɏɏƒ‡:


ʴʴʴˆ‘™ŽŜɏɏƒ‡
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
––”‹„—–‡””‘”śɐ— ɐ‘„Œ‡ –Šƒ•‘ƒ––”‹„—–‡ɐɏɏƒ‡ɐ

Это соглашение по именованию не делает атрибут полностью закрытым: Python


искажает имя, чтобы внешний код не наткнулся на этот атрибут. Если вам интересно
и вы обещаете никому не рассказывать1, я покажу вам, как будет выглядеть атрибут:
ʴʴʴˆ‘™ŽŜɏ— ɏɏƒ‡
ɐ‘ƒŽ†ɐ

Обратите внимание на то, что на экране не появилась надпись ‹•‹†‡ the getter.
Хотя эта защита неидеальна, искажение имен препятствует случайному или пред-
намеренному доступу к атрибуту.

ǨȚȘȐȉțȚȣȒȓȈșșȖȊȐȖȉȢȍȒȚȖȊ
Вы можете присвоить атрибуты классам, и они будут унаследованы их объектами-
потомками:
ʴʴʴ Žƒ•• ”—‹–ś
ŜŜŜ ‘Ž‘”ʰɐ”‡†ɐ
ŜŜŜ

1
Вы умеете хранить секреты? Я, кажется, нет.
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

ʴʴʴ„Ž—‡„‡””›ʰ ”—‹–ſƀ
ʴʴʴ ”—‹–Ŝ ‘Ž‘”
ɐ”‡†ɐ
ʴʴʴ„Ž—‡„‡””›Ŝ ‘Ž‘”
ɐ”‡†ɐ

Но если вы измените значение атрибута в объекте-потомке, атрибут класса не из-


менится:
ʴʴʴ„Ž—‡„‡””›Ŝ ‘Ž‘”ʰɐ„Ž—‡ɐ
ʴʴʴ„Ž—‡„‡””›Ŝ ‘Ž‘”
ɐ„Ž—‡ɐ
ʴʴʴ ”—‹–Ŝ ‘Ž‘”
ɐ”‡†ɐ

Если позже измените атрибут класса, на существующих объектах-потомках это


не отразится:
ʴʴʴ ”—‹–Ŝ ‘Ž‘”ʰɐ‘”ƒ‰‡ɐ
ʴʴʴ ”—‹–Ŝ ‘Ž‘”
ɐ‘”ƒ‰‡ɐ
ʴʴʴ„Ž—‡„‡””›Ŝ ‘Ž‘”
ɐ„Ž—‡ɐ
—–‹–™‹ŽŽƒˆˆ‡ –‡™‘‡•ś
ʴʴʴ‡™ɏˆ”—‹–ʰ ”—‹–ſƀ
ʴʴʴ‡™ɏˆ”—‹–Ŝ ‘Ž‘”
ɐ‘”ƒ‰‡ɐ

ǺȐȗȣȔȍȚȖȌȖȊ
Одни методы являются частью самого класса, другие — частью объектов, созданных
из этого класса, а какие-то не являются ни тем ни другим.
‰Если перед методом нет декоратора, то это метод объекта и его первым аргумен-
том должен быть self, который ссылается на объект.
‰Если у метода есть декоратор ɒ Žƒ••‡–Š‘†, то это метод класса и его первым
аргументом должен быть Ž• (имя может быть любым, кроме зарезервированного
слова Žƒ••), который ссылается на класс.
‰Если у метода есть декоратор ɒ•–ƒ–‹ ‡–Š‘†, то это статический метод и его
первым аргументом будет не объект и не класс.
В следующих подразделах мы рассмотрим эти вопросы более детально.

ǴȍȚȖȌȣȖȉȢȍȒȚȖȊ
Когда вы видите начальный аргумент self в методах внутри определения класса,
вы имеете дело с методом объекта: такие методы вы обычно пишете, когда создаете
собственный класс. Первый параметр метода экземпляра — это self, Python пере-
дает объект методу, когда вы его вызываете. Это единственные методы, которые мы
уже рассмотрели.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǴȍȚȖȌȣȒȓȈșșȖȊ
В противоположность ему метод класса влияет на весь класс целиком. Любое из-
менение, которое происходит с классом, влияет на все его объекты. Внутри опреде-
ления класса декоратор ɒ Žƒ••‡–Š‘† показывает, что следующая функция является
методом класса. Первым параметром метода также является сам класс. По традиции
этот параметр называется Ž•, поскольку слово Žƒ•• зарезервировано и не может
быть использовано в данной ситуации. Определим метод класса для Ǡ, который будет
подсчитывать количество созданных объектов:
ʴʴʴ Žƒ••ſƀś
ŜŜŜ ‘—–ʰɥ
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆƀś
ŜŜŜŜ ‘—–ʫʰɨ
ŜŜŜ†‡ˆ‡š Žƒ‹ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɑ ɐƒŠɑƀ
ŜŜŜɒ Žƒ••‡–Š‘†
ŜŜŜ†‡ˆ‹†•ſ Ž•ƀś
ŜŜŜ’”‹–ſɑŠƒ•ɑř Ž•Ŝ ‘—–řɑŽ‹––އ‘„Œ‡ –•Ŝɑƀ
ŜŜŜ
ʴʴʴ
ʴʴʴ‡ƒ•›ɏƒʰſƀ
ʴʴʴ„”‡‡œ›ɏƒʰſƀ
ʴʴʴ™Š‡‡œ›ɏƒʰſƀ
ʴʴʴŜ‹†•ſƀ
Šƒ•ɪŽ‹––އ‘„Œ‡ –•Ŝ

Обратите внимание на то, что мы вызвали метод Ŝ ‘—– (атрибут класса) вместо
•‡ŽˆŜ ‘—– (который является атрибутом объекта). В методе ‹†•ſƀ мы использова-
ли вызов Ž•Ŝ ‘—–, но с тем же успехом могли бы применить вызов Ŝ ‘—–.

ǹȚȈȚȐȟȍșȒȐȍȔȍȚȖȌȣ
Третий тип методов не влияет ни на классы, ни на объекты: он находится внутри
класса только для удобства, чтобы не располагаться где-то отдельно. Это статиче-
ский метод, которому предшествует декоратор ɒ•–ƒ–‹ ‡–Š‘†, не имеющий в каче-
стве начального параметра ни self, ни класс Žƒ••. Рассмотрим пример, который
является рекламой класса ‘›‘–‡‡ƒ’‘:
ʴʴʴ Žƒ••‘›‘–‡‡ƒ’‘ſƀś
ŜŜŜɒ•–ƒ–‹ ‡–Š‘†
ŜŜŜ†‡ˆ ‘‡” ‹ƒŽſƀś
ŜŜŜ’”‹–ſɐŠ‹•‘›‘–‡‡ƒ’‘Šƒ•„‡‡„”‘—‰Š––‘›‘—„› ‡ɐƀ
ŜŜŜ
ʴʴʴ
ʴʴʴ‘›‘–‡‡ƒ’‘Ŝ ‘‡” ‹ƒŽſƀ
Š‹•‘›‘–‡‡ƒ’‘Šƒ•„‡‡„”‘—‰Š––‘›‘—„› ‡

Обратите внимание на то, что нам не нужно создавать объект класса ‘›‘–‡‡ƒ’‘,
чтобы получить доступ к этому методу. И это замечательно.
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

ǻȚȐȕȈȧȚȐȗȐȏȈȞȐȧ
В Python имеется также реализация полиморфизма — это значит, что одна операция
может быть произведена над разными объектами, основываясь на имени метода и его
аргументах, независимо от их класса.
Используем уже знакомый нам инициализатор ɏɏ‹‹–ɏɏſƀ для всех трех классов
—‘–‡, но добавим две новые функции:

‰™Š‘ſƀ возвращает значение сохраненной строки person;


‰•ƒ›•ſƀ возвращает сохраненную строку ™‘”†•, имеющую особую пунктуацию.
Посмотрим на них в действии:
ʴʴʴ Žƒ••—‘–‡ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř’‡”•‘ř™‘”†•ƀś
ŜŜŜ•‡ŽˆŜ’‡”•‘ʰ’‡”•‘
ŜŜŜ•‡ŽˆŜ™‘”†•ʰ™‘”†•
ŜŜŜ†‡ˆ™Š‘ſ•‡Žˆƀś
ŜŜŜ”‡–—”•‡ŽˆŜ’‡”•‘
ŜŜŜ†‡ˆ•ƒ›•ſ•‡Žˆƀś
ŜŜŜ”‡–—”•‡ŽˆŜ™‘”†•ʫɐŜɐ
ŜŜŜ
ʴʴʴ Žƒ••—‡•–‹‘—‘–‡ſ—‘–‡ƀś
ŜŜŜ†‡ˆ•ƒ›•ſ•‡Žˆƀś
ŜŜŜ”‡–—”•‡ŽˆŜ™‘”†•ʫɐţɐ
ŜŜŜ
ʴʴʴ Žƒ••š Žƒƒ–‹‘—‘–‡ſ—‘–‡ƀś
ŜŜŜ†‡ˆ•ƒ›•ſ•‡Žˆƀś
ŜŜŜ”‡–—”•‡ŽˆŜ™‘”†•ʫɐŠɐ
ŜŜŜ
ʴʴʴ

Мы не меняли способ инициализации классов —‡•–‹‘—‘–‡ и š Žƒƒ–‹‘—‘–‡,


поэтому не переопределяли их методы ɏɏ‹‹–ɏɏſƀ. Далее Python автоматически вызы-
вает метод ɏɏ‹‹–ɏɏſƀ родительского класса —‘–‡, чтобы сохранить переменные объ-
екта person и ™‘”†•. Таким образом, мы можем получить доступ к атрибуту •‡ŽˆŜ™‘”†•
в объектах, созданных с помощью подклассов —‡•–‹‘—‘–‡ и š Žƒƒ–‹‘—‘–‡.
Создадим несколько объектов:
ʴʴʴŠ—–‡”ʰ—‘–‡ſɐŽ‡” —††ɐřɑ ɐŠ—–‹‰™ƒ„„‹–•ɑƀ
ʴʴʴ’”‹–ſŠ—–‡”Ŝ™Š‘ſƀřɐ•ƒ›•śɐřŠ—–‡”Ŝ•ƒ›•ſƀƀ
Ž‡” —††•ƒ›•ś ɐŠ—–‹‰™ƒ„„‹–•Ŝ

ʴʴʴŠ—–‡†ɨʰ—‡•–‹‘—‘–‡ſɐ—‰•—›ɐřɑŠƒ–ɐ•—’ř†‘ ɑƀ
ʴʴʴ’”‹–ſŠ—–‡†ɨŜ™Š‘ſƀřɐ•ƒ›•śɐřŠ—–‡†ɨŜ•ƒ›•ſƀƀ
—‰•—›•ƒ›•śŠƒ–ɐ•—’ř†‘ ţ

ʴʴʴŠ—–‡†ɩʰš Žƒƒ–‹‘—‘–‡ſɐƒˆˆ›— ɐřɑ –ɐ•”ƒ„„‹–•‡ƒ•‘ɑƀ


ʴʴʴ’”‹–ſŠ—–‡†ɩŜ™Š‘ſƀřɐ•ƒ›•śɐřŠ—–‡†ɩŜ•ƒ›•ſƀƀ
ƒˆˆ›— •ƒ›•ś –ɐ•”ƒ„„‹–•‡ƒ•‘Š
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Три разные версии метода •ƒ›•ſƀ обеспечивают разное поведение трех классов.
Так выглядит традиционный полиморфизм в объектно-ориентированных языках.
Python пошел немного дальше и позволяет вызывать методы ™Š‘ſƀ и •ƒ›•ſƀ для
любых объектов, в том числе и для этих методов. Определим класс ƒ„„Ž‹‰”‘‘,
который не имеет никакого отношения к нашим охотнику и его жертвам (потомкам
класса —‘–‡), созданным ранее:
ʴʴʴ Žƒ••ƒ„„Ž‹‰”‘‘ſƀś
ŜŜŜ†‡ˆ™Š‘ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ”‘‘ɐ
ŜŜŜ†‡ˆ•ƒ›•ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐƒ„„އɐ
ŜŜŜ
ʴʴʴ„”‘‘ʰƒ„„Ž‹‰”‘‘ſƀ

Теперь запустим методы ™Š‘ſƀ и •ƒ›•ſƀ разных объектов, один из которых („”‘‘)
совершенно не связан с остальными:
ʴʴʴ†‡ˆ™Š‘ɏ•ƒ›•ſ‘„Œƀś
ŜŜŜ’”‹–ſ‘„ŒŜ™Š‘ſƀřɐ•ƒ›•ɐř‘„ŒŜ•ƒ›•ſƀƀ
ŜŜŜ
ʴʴʴ™Š‘ɏ•ƒ›•ſŠ—–‡”ƀ
Ž‡” —††•ƒ›• ɐŠ—–‹‰™ƒ„„‹–•Ŝ
ʴʴʴ™Š‘ɏ•ƒ›•ſŠ—–‡†ɨƀ
—‰•—›•ƒ›•Šƒ–ɐ•—’ř†‘ ţ
ʴʴʴ™Š‘ɏ•ƒ›•ſŠ—–‡†ɩƀ
ƒˆˆ›— •ƒ›• –ɐ•”ƒ„„‹–•‡ƒ•‘Š
ʴʴʴ™Š‘ɏ•ƒ›•ſ„”‘‘ƀ
”‘‘•ƒ›•ƒ„„އ

Благодаря старинной поговорке «Если нечто выглядит как утка, плавает как утка
и крякает как утка, то, скорее всего, это и есть утка» подобное поведение иногда на-
зывают утиной типизацией (рис. 10.1). Кто мы такие, чтобы спорить с мудрецом,
рассуждающим об утках?

ǸȐșǻȚȐȕȈȧȚȐȗȐȏȈȞȐȧ²ȥȚȖȕȍȏȕȈȟȐȚȗȍȟȈȚȈȚȤȚȍȒșȚșȓȖȎȐȊȋțȉȣțȚȖȟȒȖȑ
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

ǴȈȋȐȟȍșȒȐȍȔȍȚȖȌȣ
Теперь вы можете создавать и использовать простые объекты. То, что мы изучим
в этом разделе, может вас удивить — в хорошем смысле этого слова.
Когда вы пишете что-то вроде a ʰ ɪ ʫ ɯ , откуда целочисленные объекты со
значениями ɪ и ɯ узнают, как реализовать операцию ʫ? А если вы введете конструк-
цию ƒ‡ ʰ ɑƒˆˆ›ɑ ʫ " " ʫ ɑ— ɑ, как Python узнает, что оператор ʫ теперь означает
конкатенацию строк? И что подскажет переменным a и ƒ‡, как применить ʰ, чтобы
получить результат? Вы можете получить доступ к этим операторам, используя спе-
циальные методы Python (или, что звучит более драматично, магические методы).
Имена этих методов начинаются и заканчиваются двойными подчеркиваниями
(ɏɏ). Почему? Как правило, такие имена не выбирают в качестве имен для пере-
менных. Вы уже видели один такой метод: ɏɏ‹‹–ɏɏſƀ инициализирует только что
созданный объект с помощью описания его класса и любых аргументов, которые
передаются в этот метод. Вы также видели (см. подраздел «Искажение имен для
безопасности»), как использование в именах двойного нижнего подчеркивания по-
могает исказить имена атрибутов класса и его методов.
Предположим, у вас есть простой класс ‘”† и вы хотите написать для него ме-
тод ‡“—ƒŽ•ſƀ, который сравнивает два слова, игнорируя регистр. Так и есть, объект
класса ‘”†, содержащий значение ɐŠƒɐ, будет считаться равным другому объекту,
который содержит значение ɐ ɐ.
В следующем примере показана наша первая попытка, где мы вызываем ‡“—ƒŽ•ſƀ —
обычный метод. •‡ŽˆŜ–‡š– — это текстовая строка, которую содержит объект класса
‘”†. Метод ‡“—ƒŽ•ſƀ сравнивает ее с текстовой строкой, содержащейся в объекте
™‘”†ɩ (другом объекте класса ‘”†):
ʴʴʴ Žƒ••‘”†ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř–‡š–ƀś
ŜŜŜ•‡ŽˆŜ–‡š–ʰ–‡š–
ŜŜŜ
ŜŜŜ†‡ˆ‡“—ƒŽ•ſ•‡Žˆř™‘”†ɩƀś
ŜŜŜ”‡–—”•‡ŽˆŜ–‡š–ŜŽ‘™‡”ſƀʰʰ™‘”†ɩŜ–‡š–ŜŽ‘™‡”ſƀ
ŜŜŜ

Далее создадим три объекта ‘”† с помощью трех разных текстовых строк:
ʴʴʴˆ‹”•–ʰ‘”†ſɐŠƒɐƀ
ʴʴʴ•‡ ‘†ʰ‘”†ſɐ ɐƀ
ʴʴʴ–Š‹”†ʰ‘”†ſɐ‡Šɐƀ

Когда строки ɐŠƒɐ и ɐ ɐ сравниваются в нижнем регистре, они должны быть


равными:
ʴʴʴˆ‹”•–Ŝ‡“—ƒŽ•ſ•‡ ‘†ƀ
”—‡

Но строка ɐ‡Šɐ не совпадет со строкой ɐŠƒɐ:


ʴʴʴˆ‹”•–Ŝ‡“—ƒŽ•ſ–Š‹”†ƀ
ƒŽ•‡
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Мы определили метод ‡“—ƒŽ•ſƀ для преобразования строки в нижний регистр


и сравнения. Но было бы неплохо, если б мы могли просто сказать first ʰʰ •‡ ‘†,
как в случае встроенных типов Python. Реализуем такую возможность. Изменим
имя метода ‡“—ƒŽ•ſƀ на особое имя ɏɏ‡“ɏɏſƀ (вы узнаете, зачем я это сделал, через
минуту):
ʴʴʴ Žƒ••‘”†ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř–‡š–ƀś
ŜŜŜ•‡ŽˆŜ–‡š–ʰ–‡š–
ŜŜŜ†‡ˆɏɏ‡“ɏɏſ•‡Žˆř™‘”†ɩƀś
ŜŜŜ”‡–—”•‡ŽˆŜ–‡š–ŜŽ‘™‡”ſƀʰʰ™‘”†ɩŜ–‡š–ŜŽ‘™‡”ſƀ
ŜŜŜ

Проверим, работает ли это:


ʴʴʴˆ‹”•–ʰ‘”†ſɐŠƒɐƀ
ʴʴʴ•‡ ‘†ʰ‘”†ſɐ ɐƀ
ʴʴʴ–Š‹”†ʰ‘”†ſɐ‡Šɐƀ
ʴʴʴˆ‹”•–ʰʰ•‡ ‘†
”—‡
ʴʴʴˆ‹”•–ʰʰ–Š‹”†
ƒŽ•‡

Магия! Все, что нам было нужно, — указать особое имя метода для проверки на
равенство ɏɏ‡“ɏɏſƀ. В табл. 10.1 и 10.2 приведены имена самых полезных магических
методов.
ǺȈȉȓȐȞȈǴȈȋȐȟȍșȒȐȍȔȍȚȖȌȣȌȓȧșȘȈȊȕȍȕȐȧ

__eq__(self, other) self == other


__ne__(self, other) self != other
__lt__(self, other) self < other
__gt__(self, other) self > other
__le__(self, other) self <= other
__ge__(self, other) self >= other

ǺȈȉȓȐȞȈǴȈȋȐȟȍșȒȐȍȔȍȚȖȌȣȌȓȧȊȣȟȐșȓȍȕȐȑ

__add__(self, other) self + other


__sub__(self, other) self — other
__mul__(self, other) self * other
__floordiv__(self, other) self // other
__truediv__(self, other) self / other
__mod__(self, other) self % other
__pow__(self, other) self ** other
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

Не обязательно использовать такие математические операторы, как ʫ (маги-


ческий метод ɏɏƒ††ɏɏſƀ) и ʬ (магический метод ɏɏ•—„ɏɏſƀ), только для работы
с числами. Например, строковые объекты используют ʫ для конкатенации и * для
дуплицирования. Существует множество других методов, задокументированных
онлайн по адресу KWWSELWO\S\GRFVVPQ. Наиболее распространенные из них пред-
ставлены в табл. 10.3.
ǺȈȉȓȐȞȈǬȘțȋȐȍȔȈȋȐȟȍșȒȐȍȔȍȚȖȌȣ

__str__(self) str(self)
__repr__(self) repr(self)
__len__(self) len(self)

Часто, помимо ɏɏ‹‹–ɏɏſƀ, вы будете применять и метод ɏɏ•–”ɏɏſƀ. Он нужен


для того, чтобы выводить данные на экран. Этот метод используется методами
’”‹–ſƀ , •–”ſƀ и строками форматирования, о которых вы можете прочитать
в главе 5. Интерактивный интерпретатор применяет функцию ɏɏ”‡’”ɏɏſƀ для
того, чтобы выводить на экран переменные. Если вы не определите хотя бы один
из этих методов, то увидите на экране ваш объект, преобразованный в строку по
умолчанию:
ʴʴʴˆ‹”•–ʰ‘”†ſɐŠƒɐƀ
ʴʴʴˆ‹”•–
ʳɏɏƒ‹ɏɏŜ‘”†‘„Œ‡ –ƒ–ɥšɨɥɥɭ„ƒɪ†ɥʴ
ʴʴʴ’”‹–ſˆ‹”•–ƀ
ʳɏɏƒ‹ɏɏŜ‘”†‘„Œ‡ –ƒ–ɥšɨɥɥɭ„ƒɪ†ɥʴ

Добавим в класс ‘”† методы ɏɏ•–”ɏɏſƀ и ɏɏ”‡’”ɏɏſƀ, чтобы он лучше смо-


трелся:
ʴʴʴ Žƒ••‘”†ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř–‡š–ƀś
ŜŜŜ•‡ŽˆŜ–‡š–ʰ–‡š–
ŜŜŜ†‡ˆɏɏ‡“ɏɏſ•‡Žˆř™‘”†ɩƀś
ŜŜŜ”‡–—”•‡ŽˆŜ–‡š–ŜŽ‘™‡”ſƀʰʰ™‘”†ɩŜ–‡š–ŜŽ‘™‡”ſƀ
ŜŜŜ†‡ˆɏɏ•–”ɏɏſ•‡Žˆƀś
ŜŜŜ”‡–—”•‡ŽˆŜ–‡š–
ŜŜŜ†‡ˆɏɏ”‡’”ɏɏſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ‘”†ſɑɐ•‡ŽˆŜ–‡š–ɐɑƀɐ
ŜŜŜ
ʴʴʴˆ‹”•–ʰ‘”†ſɐŠƒɐƀ
ʴʴʴˆ‹”•–ɤȜȥȣȢȟȰțȧșȦȥȳɏɏ”‡’”ɏɏ
‘”†ſɑŠƒɑƀ
ʴʴʴ’”‹–ſˆ‹”•–ƀɤȜȥȣȢȟȰțȧșȦȥȳɏɏ•–”ɏɏ
ha

Чтобы узнать о других специальных методах, обратитесь к документации Python


(KWWSELWO\S\GRFVVPQ).
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǨȋȘȍȋȐȘȖȊȈȕȐȍȐȒȖȔȗȖȏȐȞȐȧ
Наследование может сослужить хорошую службу, когда вы хотите, чтобы класс-
потомок бо' льшую часть времени вел себя как родительский класс (потомок является
родителем). Возможность создавать иерархии наследования довольно заманчива,
но иногда композиция или агрегирование имеет больше смысла. В чем разница?
При композиции один объект является частью другого. Утка является птицей (на-
следование), но имеет хвост (композиция). Хвост не похож на утку — он является
частью утки. В следующем примере создадим объекты bill и tail и предоставим
их новому объекту †— :
ʴʴʴ Žƒ••‹ŽŽſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř†‡• ”‹’–‹‘ƀś
ŜŜŜ•‡ŽˆŜ†‡• ”‹’–‹‘ʰ†‡• ”‹’–‹‘
ŜŜŜ
ʴʴʴ Žƒ••ƒ‹Žſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřއ‰–Šƀś
ŜŜŜ•‡ŽˆŜއ‰–Šʰއ‰–Š
ŜŜŜ
ʴʴʴ Žƒ••— ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř„‹ŽŽř–ƒ‹Žƀś
ŜŜŜ•‡ŽˆŜ„‹ŽŽʰ„‹ŽŽ
ŜŜŜ•‡ŽˆŜ–ƒ‹Žʰ–ƒ‹Ž
ŜŜŜ†‡ˆƒ„‘—–ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɐŠ‹•†— Šƒ•ƒɐř•‡ŽˆŜ„‹ŽŽŜ†‡• ”‹’–‹‘řɐ„‹ŽŽƒ†ƒɐř
•‡ŽˆŜ–ƒ‹ŽŜއ‰–Šřɐ–ƒ‹Žɐƀ
ŜŜŜ
ʴʴʴȔɏ–ƒ‹Žʰƒ‹ŽſɐŽ‘‰ɐƀ
ʴʴʴȔɏ„‹ŽŽʰ‹ŽŽſɐ™‹†‡‘”ƒ‰‡ɐƀ
ʴʴʴ†— ʰ— ſȔɏ„‹ŽŽřȔɏ–ƒ‹Žƀ
ʴʴʴ†— Ŝƒ„‘—–ſƀ
Š‹•†— Šƒ•ƒ™‹†‡‘”ƒ‰‡„‹ŽŽƒ†ƒŽ‘‰–ƒ‹Ž

Агрегирование выражает более свободные отношения между объектами: один из


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

DzȖȋȌȈȐșȗȖȓȤȏȖȊȈȚȤȖȉȢȍȒȚȣ
ȈȒȖȋȌȈ²ȟȚȖȚȖȌȘțȋȖȍ
Рассмотрим несколько рекомендаций, которые помогут вам понять, где лучше раз-
местить свой код и данные — в классе, в модуле (их мы рассмотрим в главе 11) или
в чем-то совершенно ином.
‰Объекты наиболее полезны, когда вам нужно иметь несколько отдельных экзем-
пляров с одинаковым поведением (методы), но разным внутренним состоянием
(атрибуты).
‰Классы, в отличие от модулей, поддерживают наследование.
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

‰Если вам нужен только один объект, модуль может быть лучшим выбором.
Независимо от того, сколько обращений к модулю имеется в программе, загру-
зится только одна копия. (Программистам на Java и С++: можете использовать
модули в Python как синглтоны.)
‰Если у вас есть несколько переменных, которые содержат разные значения
и могут быть переданы в качестве аргументов в несколько функций, лучше всего
определить их как классы. Например, вы можете использовать словарь с ключами
•‹œ‡ и ‘Ž‘”, чтобы представить цветное изображение. Вы можете создать раз-
ные словари для каждого изображения в программе и передавать их в качестве
аргументов в функции • ƒŽ‡ſƀ и –”ƒ•ˆ‘”ſƀ. Правда, по мере добавления новых
ключей и функций разбираться со всем этим станет трудно. Поэтому более пред-
почтительно определить класс ƒ‰‡ с атрибутами •‹œ‡ или ‘Ž‘” и методами
• ƒŽ‡ſƀ и –”ƒ•ˆ‘”ſƀ. Тогда все данные и методы для работы с цветными изо-
бражениями будут определены в одном месте.
‰Используйте самые простые решения. Словарь, список или кортеж проще, ком-
пактнее и быстрее, чем модуль, который, в свою очередь, проще, чем класс.
Совет от Гвидо ван Россума: «Избегайте усложнения структур данных. Кортежи
лучше объектов (можно воспользоваться именованными кортежами). Пред-
почитайте простые поля функциям, геттерам и сеттерам. (Встроенные типы
данных — ваши друзья.) Используйте больше чисел, строк, кортежей, списков,
множеств, словарей. Взгляните также на библиотеку ‘ŽŽ‡ –‹‘•, особенно на
класс †‡“—‡».
‰Более новой альтернативой является класс данных, он рассматривается далее
в этой главе.

ǰȔȍȕȖȊȈȕȕȣȍȒȖȘȚȍȎȐ
Поскольку Гвидо только что упомянул их, а я еще не говорил, самое время рас-
смотреть именованные кортежи. Именованный кортеж — это подкласс кортежей,
с помощью которых вы можете получить доступ к значениям по имени (используя
конструкцию ŜȜȠȳ) и позиции (используя конструкцию ƃȥȠșȭșȡȜșƄ).
Рассмотрим пример из предыдущего раздела и преобразуем класс —  в имено-
ванный кортеж, сохранив bill и tail как простые строковые аргументы. Функцию
ƒ‡†–—’އ можно вызвать, передав ей два аргумента:

‰имя;
‰строку, содержащую имена полей, разделенные пробелами.
Именованные кортежи не поддерживаются Python автоматически: чтобы их ис-
пользовать, вам понадобится загрузить отдельный модуль. Мы сделаем это в первой
строке следующего примера:
ʴʴʴˆ”‘ ‘ŽŽ‡ –‹‘•‹’‘”–ƒ‡†–—’އ
ʴʴʴ— ʰƒ‡†–—’އſɐ— ɐřɐ„‹ŽŽ–ƒ‹Žɐƀ
ʴʴʴ†— ʰ— ſɐ™‹†‡‘”ƒ‰‡ɐřɐŽ‘‰ɐƀ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ʴʴʴ†— 
— ſ„‹ŽŽʰɐ™‹†‡‘”ƒ‰‡ɐř–ƒ‹ŽʰɐŽ‘‰ɐƀ
ʴʴʴ†— Ŝ„‹ŽŽ
ɐ™‹†‡‘”ƒ‰‡ɐ
ʴʴʴ†— Ŝ–ƒ‹Ž
ɐŽ‘‰ɐ

Именованный кортеж можно сделать также из словаря:


ʴʴʴ’ƒ”–•ʰƇɐ„‹ŽŽɐśɐ™‹†‡‘”ƒ‰‡ɐřɐ–ƒ‹ŽɐśɐŽ‘‰ɐƈ
ʴʴʴ†— ɩʰ— ſƋƋ’ƒ”–•ƀ
ʴʴʴ†— ɩ
— ſ„‹ŽŽʰɐ™‹†‡‘”ƒ‰‡ɐř–ƒ‹ŽʰɐŽ‘‰ɐƀ

В предыдущем коде обратите внимание на конструкцию **parts. Это аргумент —


ключевое слово. Он извлекает ключи и значения словаря parts и передает их в каче-
стве аргументов в — ſƀ, что приводит к тому же эффекту, как и:
ʴʴʴ†— ɩʰ— ſ„‹ŽŽʰɐ™‹†‡‘”ƒ‰‡ɐř–ƒ‹ŽʰɐŽ‘‰ɐƀ

Именованные кортежи неизменяемы, но вы можете заменить одно или несколько


полей и вернуть другой именованный кортеж:
ʴʴʴ†— ɪʰ†— ɩŜɏ”‡’Žƒ ‡ſ–ƒ‹Žʰɐƒ‰‹ˆ‹ ‡–ɐř„‹ŽŽʰɐ ”—•Š‹‰ɐƀ
ʴʴʴ†— ɪ
— ſ„‹ŽŽʰɐ ”—•Š‹‰ɐř–ƒ‹Žʰɐƒ‰‹ˆ‹ ‡–ɐƀ

Мы могли бы определить †—  как словарь:


ʴʴʴ†— ɏ†‹ –ʰƇɐ„‹ŽŽɐśɐ™‹†‡‘”ƒ‰‡ɐřɐ–ƒ‹ŽɐśɐŽ‘‰ɐƈ
ʴʴʴ†— ɏ†‹ –
Ƈɐ–ƒ‹ŽɐśɐŽ‘‰ɐřɐ„‹ŽŽɐśɐ™‹†‡‘”ƒ‰‡ɐƈ

Вы можете добавить поля в словарь:


ʴʴʴ†— ɏ†‹ –ƃɐ ‘Ž‘”ɐƄʰɐ‰”‡‡ɐ
ʴʴʴ†— ɏ†‹ –
Ƈɐ ‘Ž‘”ɐśɐ‰”‡‡ɐřɐ–ƒ‹ŽɐśɐŽ‘‰ɐřɐ„‹ŽŽɐśɐ™‹†‡‘”ƒ‰‡ɐƈ

Но не в именованный кортеж:
ʴʴʴ†— Ŝ ‘Ž‘”ʰɐ‰”‡‡ɐ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
––”‹„—–‡””‘”śɐ— ɐ‘„Œ‡ –Šƒ•‘ƒ––”‹„—–‡ɐ ‘Ž‘”ɐ

Вспомним плюсы использования именованных кортежей.


‰Они выглядят и действуют как неизменяемый объект.
‰Они более эффективны, чем объекты, с точки зрения времени и занимаемого
места.
‰Вы можете получить доступ к атрибутам, используя точки, а не квадратные скоб-
ки, характерные для словарей.
‰Вы можете использовать их как ключ словаря.
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

DzȓȈșșȣȌȈȕȕȣȝ
Многие люди создают объекты для хранения данных (с помощью атрибутов объ-
ектов), а не для задания определенного поведения (с помощью методов). Вы уже
видели, как именованные кортежи могут стать альтернативным хранилищем данных.
В Python 3.7 появились классы данных.
Перед вами простой старый объект, имеющий один атрибут ƒ‡:
ʴʴ Žƒ••‡‡›Žƒ••ſƀś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰƒ‡
ŜŜŜ
ʴʴʴ–‡‡›ʰ‡‡›Žƒ••ſɐ‹–•›ɐƀ
ʴʴʴ–‡‡›Ŝƒ‡
ɐ‹–•›ɐ

Реализация той же функциональности с помощью классов данных будет выгля-


деть несколько иначе:
ʴʴʴˆ”‘†ƒ–ƒ Žƒ••‡•‹’‘”–†ƒ–ƒ Žƒ••
ʴʴʴɒ†ƒ–ƒ Žƒ••
ŜŜŜ Žƒ••‡‡›ƒ–ƒŽƒ••ś
ŜŜŜƒ‡ś•–”
ŜŜŜ
ʴʴʴ–‡‡›ʰ‡‡›ƒ–ƒŽƒ••ſɐ„‹–•›ɐƀ
ʴʴʴ–‡‡›Ŝƒ‡
ɐ„‹–•›ɐ

Помимо декоратора ɒ†ƒ–ƒ Žƒ••, вам нужно определить атрибуты класса с помо-
щью аннотаций переменных (KWWSVZZZS\WKRQRUJGHYSHSVSHS). Это выглядит
как ȜȠȳś ȦȜȣ или ȜȠȳś ȦȜȣ = țȡȔȫșȡȜș, например ‘Ž‘”ś str или ‘Ž‘”ś str ʰ ɑ”‡†ɑ.
Типом может быть любой тип объектов в Python, включая созданные вами классы,
а не только встроенные, такие как str или int.
Когда вы создаете объект класса данных, вы предоставляете аргументы в том по-
рядке, в котором они указаны в классе, или используете именованные аргументы,
передавая их в любом порядке:
ʴʴʴˆ”‘†ƒ–ƒ Žƒ••‡•‹’‘”–†ƒ–ƒ Žƒ••
ʴʴʴɒ†ƒ–ƒ Žƒ••
ŜŜŜ Žƒ••‹ƒŽŽƒ••ś
ŜŜŜƒ‡ś•–”
ŜŜŜŠƒ„‹–ƒ–ś•–”
ŜŜŜ–‡‡–Šś‹–ʰɥ
ŜŜŜ
ʴʴʴ•‘™ƒʰ‹ƒŽŽƒ••ſɐ›‡–‹ɐřɐ ‹ƒŽƒ›ƒ•ɐřɫɭƀ
ʴʴʴ†— ʰ‹ƒŽŽƒ••ſŠƒ„‹–ƒ–ʰɐŽƒ‡ɐřƒ‡ʰɐ†— ɐƀ
ʴʴʴ•‘™ƒ
‹ƒŽŽƒ••ſƒ‡ʰɐ›‡–‹ɐřŠƒ„‹–ƒ–ʰɐ ‹ƒŽƒ›ƒ•ɐř–‡‡–Šʰɫɭƀ
ʴʴʴ†— 
‹ƒŽŽƒ••ſƒ‡ʰɐ†— ɐřŠƒ„‹–ƒ–ʰɐŽƒ‡ɐř–‡‡–Šʰɥƀ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

В классе ‹ƒŽŽƒ•• определено значение по умолчанию для атрибута teeth,


поэтому вам не нужно предоставлять его значение при создании объекта †— .
Вы можете обращаться к атрибутам этого объекта точно так же, как и к атрибутам
других объектов:
ʴʴʴ†— ŜŠƒ„‹–ƒ–
ɐŽƒ‡ɐ
ʴʴʴ•‘™ƒŜ–‡‡–Š
ɫɭ

О классах данных можно говорить еще долго. Обратитесь к этому руководству


(KWWSVUHDOS\WKRQFRPS\WKRQGDWDFODVVHV) или прочтите официальную (довольно объ-
емную) документацию (KWWSVZZZS\WKRQRUJGHYSHSVSHS).

DWWUV
Вы уже видели, как создаются классы и как в них добавляются атрибуты, а также
как много текста для этого требуется набрать: надо определить метод-инициализатор
ɏɏ‹‹–ɏɏſƀ, присвоить значения его аргументов атрибутам класса и создать мето-
ды, в имени которых присутствует двойное подчеркивание, например ɏɏ•–”ɏɏſƀ.
Именованные кортежи и классы данных предлагают альтернативное решение, кото-
рое можно встретить в стандартной библиотеке, — если вам нужно создать простую
коллекцию данных, проще всего воспользоваться этими вариантами.
В статье The One Python Library Everyone Needs (KWWSVJO\SKWZLVWHGPDWUL[FRP
DWWUVKWPO) сравниваются простые классы, именованные кортежи и классы
данных. В ней по множеству причин рекомендуется использовать сторонний пакет
attrs (KWWSVRUHLOO\5GZO[), который позволяет меньше набирать, меньше проверять
данные и т. д. Взгляните сами и решите для себя, что вам больше нравится — эта
библиотека или встроенные решения.

ǿȐȚȈȑȚȍȌȈȓȍȍ
В следующей главе мы обратимся к более высокому уровню структурирования
кода — к модулям и пакетам.

ǻȗȘȈȎȕȍȕȐȧ
10.1. Создайте класс Š‹‰, не имеющий содержимого, и выведите его на экран.
Затем создайте объект ‡šƒ’އ этого класса и также выведите его. Совпада-
ют ли выведенные значения?
10.2. Создайте новый класс с именем Š‹‰ɩ и присвойте переменной letters зна-
чение ɐƒ„ ɐ. Выведите на экран значение letters.
10.3. Создайте еще один класс, который, конечно же, называется Š‹‰ɪ. В этот раз
присвойте значение ɐš›œɐ атрибуту объекта letters. Выведите на экран зна-
ǫȓȈȊȈǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ  

чение атрибута letters. Понадобилось ли вам создавать объект класса, чтобы


сделать это?
10.4. Создайте класс އ‡–, имеющий атрибуты объекта ƒ‡, •›„‘Ž и —„‡”.
Создайте объект этого класса со значениями ɐ ›†”‘‰‡ɐ, ɐ ɐ и ɨ.
10.5. Создайте словарь со следующими ключами и значениями: ɐƒ‡ɐś ɐ ›†”‘‰‡ɐ,
ɐ•›„‘Žɐś ɐ ɐ, ɐ—„‡”ɐś ɨ. Далее создайте объект с именем Š›†”‘‰‡ класса
އ‡– с помощью этого словаря.
10.6. Для класса އ‡– определите метод с именем †—’ſƀ, который выводит на
экран значения атрибутов объекта (ƒ‡, •›„‘Ž и —„‡”). Создайте объект
Š›†”‘‰‡ из этого нового определения и используйте метод †—’ſƀ, чтобы вы-
вести на экран его атрибуты.
10.7. Вызовите функцию ’”‹–ſŠ›†”‘‰‡ƀ. В определении класса އ‡– измените
имя метода †—’ на ɏɏ•–”ɏɏ, создайте новый объект Š›†”‘‰‡ и затем снова вы-
зовите метод ’”‹–ſŠ›†”‘‰‡ƀ.
10.8. Модифицируйте класс އ‡–, сделав атрибуты ƒ‡, •›„‘Ž и —„‡” приват-
ными. Определите свойство получателя для каждого атрибута, возвращающее
его значение.
10.9. Определите три класса: ‡ƒ”, ƒ„„‹– и  –‘–Š‘”’‡. Для каждого из них опре-
делите всего один метод — ‡ƒ–•ſƀ. Он должен возвращать значения ɐ„‡””‹‡•ɐ
(для ‡ƒ”), ɐ Ž‘˜‡”ɐ (для ƒ„„‹–) или ɐ ƒ’‡”•ɐ (для  –‘–Š‘”’‡). Создайте
по одному объекту каждого класса и выведите на экран то, что ест указанное
животное.
10.10. Определите три класса: ƒ•‡”, Žƒ™ и ƒ”–Š‘‡. Каждый из них имеет только
один метод — †‘‡•ſƀ. Он возвращает значения ɐ†‹•‹–‡‰”ƒ–‡ɐ (для ƒ•‡”),
ɐ ”—•Šɐ (для Žƒ™) или ɐ”‹‰ɐ (для ƒ”–Š‘‡). Далее определите класс ‘„‘–,
который содержит по одному объекту каждого из этих классов. Определите
метод †‘‡•ſƀ для класса ‘„‘–, который выводит на экран все, что делают его
компоненты.
ƋƓƈƊƈ
ǴȖȌțȓȐȗȈȒȍȚȣȐȗȘȖȋȘȈȔȔȣ

Вы уже прошли путь от встроенных типов данных до более крупных структур


данных и кода. В этой главе вы доберетесь до самого главного и узнаете, как писать
работающие и объемные программы на Python. Вы напишете свои модули, а также
научитесь использовать чужие, взятые из стандартной библиотеки Python и других
источников.
Текст этой книги организован в виде иерархической структуры: слова, пред-
ложения, абзацы и главы. Иначе читать его стало бы невозможно уже через пару
страниц1. Код имеет подобную организацию: типы данных можно сравнить со сло-
вами, операторы и выражения — с предложениями, функции можно представить
абзацами, а модули — главами. Продолжу аналогию: когда я говорю, что какую-то
тему более подробно мы рассмотрим, например, в главе 8, в программировании это
была бы отсылка к коду другого модуля.

ǴȖȌțȓȐȐȖȗȍȘȈȚȖȘLPSRUW
Сейчас мы будем создавать код из нескольких файлов и применять его. Модуль — это
просто файл, содержащий код Python. Вам не нужно делать ничего особенного —
любой код, написанный на Python, может быть использован другими как модуль.
На код других модулей мы ссылаемся с помощью оператора ‹’‘”–. Это делает
код и переменные импортированного модуля доступными для вашей программы.

ǰȔȗȖȘȚȐȘțȍȔȔȖȌțȓȤ
Простейший вариант использования оператора ‹’‘”– выглядит как ‹’‘”– ȠȢȘȧȟȰ,
где ȠȢȘȧȟȰ — это имя другого файла Python без расширения Ŝ’›.
Предположим, вы с друзьями хотите съесть на обед что-то из фастфуда, но
не желаете долго выбирать, поскольку все равно последнее слово останется за тем,
кто будет громче всех кричать. Пусть выбирает компьютер! Напишем модуль всего
с одной функцией, которая будет возвращать случайное блюдо, и основную програм-
му, которая вызовет эту функцию и выведет результат на экран. Модуль (ˆƒ•–Ŝ’›)
показан в примере 11.1.

1
Как минимум читать было бы гораздо сложнее.
ǫȓȈȊȈǴȖȌțȓȐȗȈȒȍȚȣȐȗȘȖȋȘȈȔȔȣ  

ǷȘȐȔȍȘIDVWS\
ˆ”‘”ƒ†‘‹’‘”– Š‘‹ ‡

’Žƒ ‡•ʰƃɑ ‘ƒŽ†•ɑřɑ ɑřɑ—”‰‡”‹‰ɑřɑƒ ‘‡ŽŽɑř


ɑ‡†›•ɑřɑ”„›•ɑřɑ‹œœƒ —–ɑƄ

†‡ˆ’‹ ſƀśɤȥȠȢȦȤȜȦșȥȦȤȢȞȧȘȢȞȧȠșȡȦȔȪȜȜ
ɑɑɑ‡–—””ƒ†‘ˆƒ•–ˆ‘‘†’Žƒ ‡ɑɑɑ
”‡–—” Š‘‹ ‡ſ’Žƒ ‡•ƀ

А в примере 11.2 показана основная программа, которая его импортирует (на-


зовем ее Ž— ŠŜ’›).

ǷȘȐȔȍȘOXQFKS\
‹’‘”–ˆƒ•–

’Žƒ ‡ʰˆƒ•–Ŝ’‹ ſƀ


’”‹–ſɑ‡–ɐ•‰‘–‘ɑř’Žƒ ‡ƀ

Если вы поместите оба этих файла в один каталог и укажете Python запустить
файл Ž— ŠŜ’› в качестве основной программы, он обратится к модулю fast и за-
пустит его функцию ’‹ ſƀ. Мы написали эту версию функции ’‹ ſƀ так, чтобы
она возвращала случайный результат из списка строк. Таким образом, основная
программа выведет:
ɛpython [Link]
‡–ɐ•‰‘–‘—”‰‡”‹‰
ɛpython [Link]
‡–ɐ•‰‘–‘‹œœƒ —–
ɛpython [Link]
‡–ɐ•‰‘–‘”„›•

Мы использовали импортирование дважды.


‰Основная программа Ž— ŠŜ’› импортировала наш новый модуль fast.
‰Файл модуля ˆƒ•–Ŝ’› импортировал функцию Š‘‹ ‡ из стандартного модуля
Python ”ƒ†‘.
Мы также использовали импортирование двумя разными способами.
В первом случае мы импортировали модуль fast целиком, но для этого нам нуж-
но было поставить fast в качестве префикса для ’‹ ſƀ. Если мы ставим префикс
fast перед именем вызываемой функции, то все содержимое файла ˆƒ•–Ŝ’› после
оператора ‹’‘”– становится доступным основной программе. Уточняя содержимое
модуля с помощью его имени, мы избегаем возникновения любых неприятных кон-
фликтов имен: в каком-то другом модуле также может быть функция ’‹ ſƀ, и мы
не вызовем ее по ошибке.
Во втором случае мы находимся внутри функции и знаем, что существует только
одна функция с именем Š‘‹ ‡, поэтому импортируем функцию Š‘‹ ‡ſƀ непосред-
ственно из модуля ”ƒ†‘.
Мы могли бы написать модуль ˆƒ•–Ŝ’› так, как это показано в примере 11.3, им-
портировав модуль ”ƒ†‘ внутри функции ’‹ ſƀ, а не в начале файла.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǷȘȐȔȍȘIDVWS\
’Žƒ ‡•ʰƃɑ ‘ƒŽ†•ɑřɑ ɑřɑ—”‰‡”‹‰ɑřɑƒ ‘‡ŽŽɑř
ɑ‡†›•ɑřɑ”„›•ɑřɑ‹œœƒ —–ɑƄ

†‡ˆ’‹ ſƀś
‹’‘”–”ƒ†‘
”‡–—””ƒ†‘Ŝ Š‘‹ ‡ſ’Žƒ ‡•ƀ

Как и вообще в программировании, лучше выбирать стиль, который кажется


вам наиболее понятным. Имя функции со стоящим перед ним именем модуля
”ƒ†‘Ŝ Š‘‹ ‡ использовать безопаснее, однако в таком случае придется набирать
немного больше текста.
Вам следует рассмотреть возможность импортировать код вне функции, если
импортированный код может быть использован более одного раза, и изнутри функ-
ции, если вы знаете, что его применение будет лимитировано. Кто-то предпочитает
размещать все операторы ‹’‘”– в верхней части файла, чтобы явно обозначить все
зависимости кода. Оба варианта работают.

ǰȔȗȖȘȚȐȘțȍȔȔȖȌțȓȤșȌȘțȋȐȔȐȔȍȕȍȔ
В нашей основной программе Ž— ŠŜ’› мы вызывали ‹’‘”– fast. Но что, если:
‰у вас есть другой модуль с таким же именем;
‰вы хотите использовать более короткое или простое имя;
‰ваши пальцы прищемило дверью и вы хотите набирать меньше текста?
В такой ситуации можно импортировать, используя псевдоним, как показано
в примере 11.4. Используем псевдоним f.

ǷȘȐȔȍȘIDVWS\
‹’‘”–ˆƒ•–ƒ•ˆ
’Žƒ ‡ʰˆŜ’‹ ſƀ
’”‹–ſɑ‡–ɐ•‰‘–‘ɑř’Žƒ ‡ƀ

ǰȔȗȖȘȚȐȘțȍȔȚȖȓȤȒȖșȈȔȖȍȕȍȖȉȝȖȌȐȔȖȍ
С помощью Python можно импортировать одну или несколько частей модуля.
Со второй ситуацией вы уже имели дело: из модуля ”ƒ†‘ нам нужна была только
функция Š‘‹ ‡ſƀ.
Как и с модулями, вы можете дать псевдоним каждой части, которую импорти-
руете.
Теперь несколько раз перепишем файл Ž— ŠŜ’›. Сначала импортируем функцию
’‹ ſƀ из модуля fast с ее исходным именем (пример 11.5).

ǷȘȐȔȍȘIDVWS\
ˆ”‘ˆƒ•–‹’‘”–’‹ 
’Žƒ ‡ʰ’‹ ſƀ
’”‹–ſɑ‡–ɐ•‰‘–‘ɑř’Žƒ ‡ƀ
ǫȓȈȊȈǴȖȌțȓȐȗȈȒȍȚȣȐȗȘȖȋȘȈȔȔȣ  

Теперь импортируем ее под именем ™Š‘ɏ ƒ”‡• (пример 11.6).


ǷȘȐȔȍȘIDVWS\
ˆ”‘ˆƒ•–‹’‘”–’‹ ƒ•™Š‘ɏ ƒ”‡•
’Žƒ ‡ʰ™Š‘ɏ ƒ”‡•ſƀ
’”‹–ſɑ‡–ɐ•‰‘–‘ɑř’Žƒ ‡ƀ

ǷȈȒȍȚȣ
Мы проделали путь от отдельных строк кода до многострочных функций, автоном-
ных программ и нескольких модулей в одном каталоге. Если модулей у вас немного,
можно разместить их в одной папке.
Для того чтобы еще больше промасштабировать приложения Python, вы можете
организовать модули в иерархии файлов и модулей, которые называют ȣȔȞșȦȔȠȜ.
Пакет — это обычный подкаталог, содержащий файлы с расширением Ŝ’›. Внутри
каталогов можно создавать другие подкаталоги, которые, в свою очередь, могут
иметь свои подкаталоги.
Мы только что написали модуль для выбора места, где можно поесть фастфуд.
Давайте добавим похожий модуль для выдачи жизненного совета. Итак, создадим
еще одну основную программу с названием “—‡•–‹‘•Ŝ’› в текущем каталоге.
Теперь создадим подкаталог с именем Š‘‹ ‡• и поместим туда два модуля — ˆƒ•–Ŝ’›
и ƒ†˜‹ ‡Ŝ’›. Каждый модуль имеет функцию, которая возвращает строку.
Основная программа “—‡•–‹‘•Ŝ’› будет содержать дополнительное утверждение
‹’‘”– и еще одну строку (пример 11.7).

ǷȘȐȔȍȘTXHVWLRQVS\
ˆ”‘•‘—” ‡•‹’‘”–ˆƒ•–řƒ†˜‹ ‡

’”‹–ſɑ‡–ɐ•‰‘–‘ɑřˆƒ•–Ŝ’‹ ſƀƀ
’”‹–ſɑŠ‘—ކ™‡–ƒ‡‘—–ţɑřƒ†˜‹ ‡Ŝ‰‹˜‡ſƀƀ
Утверждение ˆ”‘ •‘—” ‡• заставляет Python искать каталог с именем •‘—” ‡•,
начиная с вашего текущего каталога. Внутри каталога •‘—” ‡• он ищет файлы
ˆƒ•–Ŝ’› и ƒ†˜‹ ‡Ŝ’›.
Код первого модуля Š‘‹ ‡•ŵˆƒ•–Ŝ’› не изменился, просто файл переместился
в каталог Š‘‹ ‡• (пример 11.8).
ǷȘȐȔȍȘFKRLFHVIDVWS\
ˆ”‘”ƒ†‘‹’‘”– Š‘‹ ‡

’Žƒ ‡•ʰƃɑ ‘ƒŽ†•ɑřɑ ɑřɑ—”‰‡”‹‰ɑřɑƒ ‘‡ŽŽɑř


ɑ‡†›•ɑřɑ”„›•ɑřɑ‹œœƒ —–ɑƄ

†‡ˆ’‹ ſƀś
ɑɑɑ‡–—””ƒ†‘ˆƒ•–ˆ‘‘†’Žƒ ‡ɑɑɑ
”‡–—” Š‘‹ ‡ſ’Žƒ ‡•ƀ
Второй модуль Š‘‹ ‡•ŵƒ†˜‹ ‡Ŝ’› новый, но работает практически так же, как
и его собрат, посвященный фастфуду (пример 11.9).
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ǷȘȐȔȍȘFKRLFHVDGYLFHS\
ˆ”‘”ƒ†‘‹’‘”– Š‘‹ ‡

ƒ•™‡”•ʰƃɑ‡•Šɑřɑ‘Šɑřɑ‡’Ž›Šƒœ›ɑřɑ‘””›ř™Šƒ–ţɑƄ

†‡ˆ‰‹˜‡ſƀś
ɑɑɑ‡–—””ƒ†‘ƒ†˜‹ ‡ɑɑɑ
”‡–—” Š‘‹ ‡ſƒ•™‡”•ƀ

ǭșȓȐ ȊȍȘșȐȧ ȊȈȠȍȋȖ 3\WKRQ ȕȐȎȍ ȟȍȔ  ȗȖȕȈȌȖȉȐȚșȧ ȍȡȍ ȒȖȍȟȚȖ șȌȍȓȈȚȤ
ȊȗȖȌȒȈȚȈȓȖȋȍVRXUFHVȟȚȖȉȣȖȕșȚȈȓȗȈȒȍȚȖȔ3\WKRQ²șȖȏȌȈȚȤȜȈȑȓșȐȔȍȕȍȔ
BBLQLWBBS\ȅȚȖȔȖȎȍȚȉȣȚȤȌȈȎȍȗțșȚȖȑȜȈȑȓȕȖȌȓȧȉȖȓȍȍșȚȈȘȣȝȊȍȘșȐȑ3\WKRQ
ȍȋȖȗȘȐșțȚșȚȊȐȍȕȍȖȉȝȖȌȐȔȖȟȚȖȉȣșȖȌȍȘȎȈȡȐȑȍȋȖȒȈȚȈȓȖȋșȟȐȚȈȓșȧȗȈȒȍȚȖȔ
ȅȚȖȍȡȍȖȌȐȕȘȈșȗȘȖșȚȘȈȕȍȕȕȣȑȊȖȗȘȖșȕȈșȖȉȍșȍȌȖȊȈȕȐȧȝ

Запустите основную программу “—‡•–‹‘•Ŝ’› (из вашего текущего каталога, а не


из •‘—” ‡•), чтобы увидеть, что произойдет:
$ python [Link]
‡–ɐ•‰‘–‘ 
Š‘—ކ™‡–ƒ‡‘—–ţ‡•Š
$ python [Link]
‡–ɐ•‰‘–‘‡†›•
Š‘—ކ™‡–ƒ‡‘—–ţ‡’Ž›Šƒœ›
$ python [Link]
‡–ɐ•‰‘–‘ ‘ƒŽ†•
Š‘—ކ™‡–ƒ‡‘—–ţ‡’Ž›Šƒœ›

ǷțȚȤȗȖȐșȒȈȔȖȌțȓȧ
Я только что сказал, что Python просматривает ваш текущий каталог для поиска
подкаталога Š‘‹ ‡• и его модулей. На самом деле он выполняет поиск не только
там, и вы можете сами выбирать места поиска нужных файлов. Ранее мы импорти-
ровали функцию Š‘‹ ‡ſƀ из модуля стандартной библиотеки ”ƒ†‘. Его не было
в текущем каталоге, поэтому Python надо было искать и в другом месте.
Чтобы узнать, где интерпретатор Python ищет файлы, импортируйте стандарт-
ный модуль sys и используйте его список path, в котором содержатся имена ката-
логов и файлы ZIP-архивов.
Вы можете получить доступ к этому списку и изменить его. Вот так выглядит зна-
чение переменной •›•Ŝ’ƒ–Š в Python 3.3 в моей версии операционной системы Mac:
ʴʴʴ‹’‘”–•›•
ʴʴʴˆ‘”’Žƒ ‡‹•›•Ŝ’ƒ–Šś
ŜŜŜ’”‹–ſ’Žƒ ‡ƀ
ŜŜŜ

ŵ‹„”ƒ”›ŵ ”ƒ‡™‘”•ŵ›–Š‘Ŝˆ”ƒ‡™‘”ŵ‡”•‹‘•ŵɪŜɪŵŽ‹„ŵ’›–Š‘ɪɪŜœ‹’
ŵ‹„”ƒ”›ŵ ”ƒ‡™‘”•ŵ›–Š‘Ŝˆ”ƒ‡™‘”ŵ‡”•‹‘•ŵɪŜɪŵŽ‹„ŵ’›–Š‘ɪŜɪ
ŵ‹„”ƒ”›ŵ ”ƒ‡™‘”•ŵ›–Š‘Ŝˆ”ƒ‡™‘”ŵ‡”•‹‘•ŵɪŜɪŵŽ‹„ŵ’›–Š‘ɪŜɪŵ’Žƒ–ކƒ”™‹
ŵ‹„”ƒ”›ŵ ”ƒ‡™‘”•ŵ›–Š‘Ŝˆ”ƒ‡™‘”ŵ‡”•‹‘•ŵɪŜɪŵŽ‹„ŵ’›–Š‘ɪŜɪŵŽ‹„ކ›Ž‘ƒ†
ŵ‹„”ƒ”›ŵ ”ƒ‡™‘”•ŵ›–Š‘Ŝˆ”ƒ‡™‘”ŵ‡”•‹‘•ŵɪŜɪŵŽ‹„ŵ’›–Š‘ɪŜɪŵ•‹–‡Ş’ƒ ƒ‰‡•
ǫȓȈȊȈǴȖȌțȓȐȗȈȒȍȚȣȐȗȘȖȋȘȈȔȔȣ  

Эта начальная пустая строка вывода является пустой строкой ɐɐ, обозначающей
текущий каталог. Если строка ɐɐ находится первой в •›•Ŝ’ƒ–Š, Python сначала вы-
полнит поиск в текущем каталоге, когда вы попробуете что-то импортировать: ‹’‘”–
fast выглядит как ˆƒ•–Ŝ’›. Python обычно действует именно так. Кроме того, если
создать подкаталог •‘—” ‡• и поместить туда файлы с кодом, их можно импортиро-
вать командами ‹’‘”– •‘—” ‡• и ˆ”‘ •‘—” ‡• ‹’‘”– fast.
Использован будет первый найденный модуль. Это означает, что, если вы опре-
делите модуль с именем ”ƒ†‘ и он будет найден раньше оригинального модуля,
вы не получите доступ к элементу ”ƒ†‘ стандартной библиотеки.
Вы можете изменить путь, по которому производится поиск, внутри вашего кода.
Предположим, вы хотите, чтобы Python искал файлы в каталоге ŵ›ŵ‘†—އ• перед
тем, как обратиться к другим местам:
ʴʴʴ‹’‘”–•›•
ʴʴʴ•›•Ŝ’ƒ–ŠŜ‹•‡”–ſɥřɑŵ›ŵ‘†—އ•ɑƀ

ǶȚȕȖșȐȚȍȓȤȕȣȑȐȈȉșȖȓȦȚȕȣȑȐȔȗȖȘȚ
К этому моменту в наших примерах мы импортировали собственные модули из:
‰текущего каталога;
‰подкаталога Š‘‹ ‡•;
‰стандартной библиотеки Python.
Этот подход хорошо работает до тех пор, пока у вас нет локального модуля
с тем же именем, что и у стандартного модуля. Какой именно из них вам нужен?
Python поддерживает абсолютный и относительный импорт. В рассмотренных
примерах вы видели абсолютный импорт. Если вы введете команду ‹’‘”– rougarou,
то для каждого указанного каталога Python будет искать файл с именем ”‘—‰ƒ”‘—Ŝ’›
(модуль) или каталог с именем rougarou (пакет).
‰Если файл ”‘—‰ƒ”‘—Ŝ’› находится в том же каталоге, что и вызывающая сторона,
вы можете импортировать его относительно текущей локации с помощью коман-
ды ˆ”‘ Ŝ ‹’‘”– rougarou.
‰Если он находится в каталоге более высокого уровня: ˆ”‘ ŜŜ ‹’‘”– rougarou.
‰Если находится в каталоге того же уровня с именем ”‡ƒ–—”‡•: ˆ”‘ ŜŜ ”‡ƒ–—”‡•
‹’‘”– rougarou.
Нотации Ŝ и ŜŜ были позаимствованы из ОС семейства Unix — там эти сокраще-
ния используются для обозначения текущего и родительского каталогов.
Подробнее о проблемах импорта в Python вы можете прочитать в статье Traps
for the Unwary in Python’s Import System (KWWSS\WKRQQRWHVFXULRXVHIILFLHQF\RUJHQODWHVW
S\WKRQBFRQFHSWVLPSRUWBWUDSVKWPO).

ǷȈȒȍȚȣȗȘȖșȚȘȈȕșȚȊȐȔȍȕ
Вы уже знаете, что можно упаковать модули Python как:
‰единый модуль (файл с расширением Ŝ’›);
‰пакет (каталог, содержащий модули и, возможно, другие пакеты).
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Вы также можете разбить пакет на несколько каталогов с помощью пакетов


пространств имен. Предположим, вы ходите создать пакет ”‹––‡”•, который будет
содержать модули Python для каждого опасного существа (реального или вымыш-
ленного). Кроме того, в модулях будут содержаться вспомогательная информация
и заметки по выживанию. Со временем пакет может разрастись, поэтому вы решаете
разделить модули по географическому расположению существ. Один из вариантов
решения проблемы — создание подпакета для каждой локации и перемещение
в него существующих файлов модулей Ŝ’›. Однако это может нарушить работу
других модулей, которые импортируют данные файлы. Вместо этого можно сделать
следующее:
‰создать новые каталоги для каждой локации на уровень выше пакета ”‹––‡”•;
‰создать «двоюродные» ”‹––‡”•-каталоги ниже этих новых «родителей»;
‰переместить существующие модули в соответствующие каталоги.
Этот подход нужно проиллюстрировать. Предположим, мы начали работу с такой
раскладкой файлов:
”‹––‡”•
 ”‘—‰ƒ”‘—Ŝ’›
 ™‡†‹‰‘Ŝ’›

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


ˆ”‘ ”‹––‡”•‹’‘”–™‡†‹‰‘ř”‘—‰ƒ”‘—

Теперь, если мы решим выделить локации north и south, файлы будут разме-
щаться вот так:
north
  ”‹––‡”•
 ™‡†‹‰‘Ŝ’›
south
  ”‹––‡”•
 ”‘—‰ƒ”‘—Ŝ’›

Если оба каталога, north и south, будут находиться в вашем пути поиска модуля,
вы сможете импортировать модули так же, как если бы они все еще находились
в пакете, состоящем из одного каталога:
ˆ”‘ ”‹––‡”•‹’‘”–™‡†‹‰‘ř”‘—‰ƒ”‘—

ǴȖȌțȓȐȗȘȖȚȐȊȖȉȢȍȒȚȖȊ
В каких случаях нужно размещать код в модуле, а в каких — в объекте?
У модуля и объекта много общего. Объект или модуль с именем thing, содержащий
переменную с именем stuff, позволяет вам получить доступ к этой переменной с по-
мощью конструкции –Š‹‰Ŝ•–—ˆˆ. Переменная stuff может быть определена при соз-
дании модуля или класса, или же ее значение может быть присвоено позже. Все классы,
функции и глобальные переменные модуля доступны и за его пределами.
Объекты могут использовать свойства и двойные нижние подчеркивания (ɏɏ …)
в именах для того, чтобы спрятать свои данные или управлять доступом к ним.
ǫȓȈȊȈǴȖȌțȓȐȗȈȒȍȚȣȐȗȘȖȋȘȈȔȔȣ  

Это значит, что вы можете сделать следующее:


ʴʴʴ‹’‘”–ƒ–Š
ʴʴʴƒ–ŠŜ’‹
ɪŜɨɫɨɬɰɩɭɬɪɬɯɰɮɰɪ
ʴʴʴƒ–ŠŜ’‹ʰɪŜɥ
ʴʴʴƒ–ŠŜ’‹
ɪŜɥ

Неужели мы только что испортили вычисления для всех, кто пользуется этим
компьютером? Да! На самом деле нет, я шучу1. Это действие не повлияло на модуль
ƒ–Š. Вы изменили только значение pi для копии модуля ƒ–Š, которая импортиру-
ется вашей вызывающей программой, и все улики вашего преступления исчезнут
по ее завершении.
Для любого импортированного вами модуля создается только одна копия, даже
если вы импортируете его несколько раз. Этим можно пользоваться для сохране-
ния глобальных объектов, представляющих интерес для вашей программы: так же
как и с классом, который тоже имеет всего одну копию, хотя из него можно создать
много объектов.

ǬȖșȚȖȐȕșȚȊȈșȚȈȕȌȈȘȚȕȖȑȉȐȉȓȐȖȚȍȒȐ3\WKRQ
Одно из основных преимуществ Python заключается в том, что у него есть соб-
ственный «запас мощности» — большая стандартная библиотека модулей, которые
выполняют множество полезных задач и располагаются отдельно друг от друга
во избежание разрастания ядра языка. Нередко, когда вы собираетесь писать код,
сначала стоит проверить, нет ли уже стандартного модуля, который делает то, что
вы хотите. Python также предоставляет авторитетную документацию для модулей
наряду с руководством для пользователей (KWWSGRFVS\WKRQRUJOLEUDU\). Сайт Дага
Хеллмана Python Module of the Week (KWWSELWO\S\PRWZ) и его книга The Python
Standard Library by Example («Стандартная библиотека Python в примерах»), вы-
пущенная издательством Addison-Wesley Professional, также являются очень по-
лезными руководствами.
В следующих главах книги вы познакомитесь со множеством стандартных моду-
лей, предназначенных для работы с сетью, системами, базами данных и т. д. В этом
разделе я говорю о стандартных модулях, которые имеют более общие варианты
использования.

ǶȉȘȈȉȈȚȣȊȈȍȔȖȚșțȚșȚȊțȦȡȐȍȒȓȦȟȐ
șȗȖȔȖȡȤȦȜțȕȒȞȐȑVHWGHIDXOW ȐGHIDXOWGLFW
Вы уже знаете, что попытка получить доступ к словарю с помощью несуществу-
ющего ключа генерирует исключение. Избежать этого помогает функция словаря
‰‡–ſƀ для возврата значения по умолчанию. Функция •‡–†‡ˆƒ—Ž–ſƀ похожа на

1
Или не шучу? Муа-ха-ха!
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

функцию ‰‡–ſƀ, но кроме того, она присваивает элемент словарю, если заданный
ключ отсутствует:
ʴʴʴ’‡”‹‘†‹ ɏ–ƒ„އʰƇɐ ›†”‘‰‡ɐśɨřɐ ‡Ž‹—ɐśɩƈ
ʴʴʴ’”‹–ſ’‡”‹‘†‹ ɏ–ƒ„އƀ
Ƈɐ ‡Ž‹—ɐśɩřɐ ›†”‘‰‡ɐśɨƈ

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


ʴʴʴ ƒ”„‘ʰ’‡”‹‘†‹ ɏ–ƒ„އŜ•‡–†‡ˆƒ—Ž–ſɐƒ”„‘ɐřɨɩƀ
ʴʴʴ ƒ”„‘
ɨɩ
ʴʴʴ’‡”‹‘†‹ ɏ–ƒ„އ
Ƈɐ ‡Ž‹—ɐśɩřɐƒ”„‘ɐśɨɩřɐ ›†”‘‰‡ɐśɨƈ

Если мы попытаемся присвоить другое значение по умолчанию уже существу-


ющему ключу, будет возвращено оригинальное значение и ничто не изменится:
ʴʴʴЇދ—ʰ’‡”‹‘†‹ ɏ–ƒ„އŜ•‡–†‡ˆƒ—Ž–ſɐ ‡Ž‹—ɐřɰɫɮƀ
ʴʴʴЇދ—
ɩ
ʴʴʴ’‡”‹‘†‹ ɏ–ƒ„އ
Ƈɐ ‡Ž‹—ɐśɩřɐƒ”„‘ɐśɨɩřɐ ›†”‘‰‡ɐśɨƈ

Функция †‡ˆƒ—Ž–†‹ –ſƀ похожа на предыдущую, но она определяет значение по


умолчанию для новых ключей заранее, при создании словаря. В этом примере мы пере-
даем функцию int, которая будет вызываться как ‹–ſƀ и возвращать значение ɥ:
ʴʴʴˆ”‘ ‘ŽŽ‡ –‹‘•‹’‘”–†‡ˆƒ—Ž–†‹ –
ʴʴʴ’‡”‹‘†‹ ɏ–ƒ„އʰ†‡ˆƒ—Ž–†‹ –ſ‹–ƀ

Теперь любое отсутствующее значение будет заменяться целым числом int со


значением ɥ:
ʴʴʴ’‡”‹‘†‹ ɏ–ƒ„އƃɐ ›†”‘‰‡ɐƄʰɨ
ʴʴʴ’‡”‹‘†‹ ɏ–ƒ„އƃɐ‡ƒ†ɐƄ
ɥ
ʴʴʴ’‡”‹‘†‹ ɏ–ƒ„އ
†‡ˆƒ—Ž–†‹ –ſʳ Žƒ••ɐ‹–ɐʴřƇɐ‡ƒ†ɐśɥřɐ ›†”‘‰‡ɐśɨƈƀ

Аргументом †‡ˆƒ—Ž–†‹ –ſƀ является функция, возвращающая значение, которое


будет присвоено отсутствующему ключу. В следующем примере функция ‘ɏ‹†‡ƒſƀ
вызывается всякий раз, когда нужно вернуть значение:
ʴʴʴˆ”‘ ‘ŽŽ‡ –‹‘•‹’‘”–†‡ˆƒ—Ž–†‹ –
ʴʴʴ
ʴʴʴ†‡ˆ‘ɏ‹†‡ƒſƀś
ŜŜŜ”‡–—”ɐ —Šţɐ
ŜŜŜ
ʴʴʴ„‡•–‹ƒ”›ʰ†‡ˆƒ—Ž–†‹ –ſ‘ɏ‹†‡ƒƀ
ʴʴʴ„‡•–‹ƒ”›ƃɐɐƄʰɐ„‘‹ƒ„އ‘™ƒɐ
ʴʴʴ„‡•–‹ƒ”›ƃɐɐƄʰɐƒ•‹Ž‹•ɐ
ʴʴʴ„‡•–‹ƒ”›ƃɐɐƄ
ɐ„‘‹ƒ„އ‘™ƒɐ
ʴʴʴ„‡•–‹ƒ”›ƃɐɐƄ
ǫȓȈȊȈǴȖȌțȓȐȗȈȒȍȚȣȐȗȘȖȋȘȈȔȔȣ  

ɐƒ•‹Ž‹•ɐ
ʴʴʴ„‡•–‹ƒ”›ƃɐɐƄ
ɐ —Šţɐ

Вы можете использовать функции ‹–ſƀ, Ž‹•–ſƀ или †‹ –ſƀ, чтобы возвращать


пустые значения по умолчанию: ‹–ſƀ возвращает ɥ, Ž‹•–ſƀ возвращает пустой спи-
сок ƃƄ, †‹ –ſƀ возвращает пустой словарь Ƈƈ. Если вы опустите аргумент, исходное
значение нового ключа будет равно ‘‡.
Кстати, вы можете использовать Žƒ„†ƒ для того, чтобы определить функцию по
умолчанию внутри вызова:
ʴʴʴ„‡•–‹ƒ”›ʰ†‡ˆƒ—Ž–†‹ –ſŽƒ„†ƒśɐ —Šţɐƀ
ʴʴʴ„‡•–‹ƒ”›ƃɐɐƄ
ɐ —Šţɐ

Использовать int — это один из способов создать собственный счетчик:


ʴʴʴˆ”‘ ‘ŽŽ‡ –‹‘•‹’‘”–†‡ˆƒ—Ž–†‹ –
ʴʴʴˆ‘‘†ɏ ‘—–‡”ʰ†‡ˆƒ—Ž–†‹ –ſ‹–ƀ
ʴʴʴˆ‘”ˆ‘‘†‹ƃɐ•’ƒɐřɐ•’ƒɐřɐ‡‰‰•ɐřɐ•’ƒɐƄś
ŜŜŜˆ‘‘†ɏ ‘—–‡”ƃˆ‘‘†Ƅʫʰɨ
ŜŜŜ
ʴʴʴˆ‘”ˆ‘‘†ř ‘—–‹ˆ‘‘†ɏ ‘—–‡”Ŝ‹–‡•ſƀś
ŜŜŜ’”‹–ſˆ‘‘†ř ‘—–ƀ
ŜŜŜ
‡‰‰•ɨ
•’ƒɪ

Если бы в предыдущем примере ˆ‘‘†ɏ ‘—–‡” был обычным словарем, а не


†‡ˆƒ—Ž–†‹ –, Python генерировал бы исключение всякий раз при попытке увеличить
элемент словаря ˆ‘‘†ɏ ‘—–‡”ƃˆ‘‘†Ƅ, ведь тот не инициализирован. Нам понадо-
билось бы сделать дополнительную работу, как показано здесь:
ʴʴʴ†‹ –ɏ ‘—–‡”ʰƇƈ
ʴʴʴˆ‘”ˆ‘‘†‹ƃɐ•’ƒɐřɐ•’ƒɐřɐ‡‰‰•ɐřɐ•’ƒɐƄś
ŜŜŜ‹ˆ‘–ˆ‘‘†‹†‹ –ɏ ‘—–‡”ś
ŜŜŜ†‹ –ɏ ‘—–‡”ƃˆ‘‘†Ƅʰɥ
ŜŜŜ†‹ –ɏ ‘—–‡”ƃˆ‘‘†Ƅʫʰɨ
ŜŜŜ
ʴʴʴˆ‘”ˆ‘‘†ř ‘—–‹†‹ –ɏ ‘—–‡”Ŝ‹–‡•ſƀś
ŜŜŜ’”‹–ſˆ‘‘†ř ‘—–ƀ
ŜŜŜ
•’ƒɪ
‡‰‰•ɨ

ǷȖȌșȟȐȚȣȊȈȍȔȥȓȍȔȍȕȚȣșȗȖȔȖȡȤȦȜțȕȒȞȐȐ&RXQWHU
Если говорить о счетчиках, то в стандартной библиотеке имеется счетчик, который
справляется с задачей из предыдущего примера, и не только с ней:
ʴʴʴˆ”‘ ‘ŽŽ‡ –‹‘•‹’‘”–‘—–‡”
ʴʴʴ„”‡ƒˆƒ•–ʰƃɐ•’ƒɐřɐ•’ƒɐřɐ‡‰‰•ɐřɐ•’ƒɐƄ
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

ʴʴʴ„”‡ƒˆƒ•–ɏ ‘—–‡”ʰ‘—–‡”ſ„”‡ƒˆƒ•–ƀ
ʴʴʴ„”‡ƒˆƒ•–ɏ ‘—–‡”
‘—–‡”ſƇɐ•’ƒɐśɪřɐ‡‰‰•ɐśɨƈƀ

Функция ‘•–ɏ ‘‘ſƀ возвращает все элементы в убывающем порядке или


только те элементы, количество которых больше, чем заданный аргумент ‘—–:
ʴʴʴ„”‡ƒˆƒ•–ɏ ‘—–‡”Ŝ‘•–ɏ ‘‘ſƀ
ƃſɐ•’ƒɐřɪƀřſɐ‡‰‰•ɐřɨƀƄ
ʴʴʴ„”‡ƒˆƒ•–ɏ ‘—–‡”Ŝ‘•–ɏ ‘‘ſɨƀ
ƃſɐ•’ƒɐřɪƀƄ

Счетчики можно объединять. Для начала снова взглянем на содержимое „”‡ƒˆƒ•–ɏ


‘—–‡”:
ʴʴʴ„”‡ƒˆƒ•–ɏ ‘—–‡”
ʴʴʴ‘—–‡”ſƇɐ•’ƒɐśɪřɐ‡‰‰•ɐśɨƈƀ

Создадим новый список с именем Ž— Š и счетчик соответственно с именем


Ž— Šɏ ‘—–‡”:
ʴʴʴŽ— Šʰƃɐ‡‰‰•ɐřɐ‡‰‰•ɐřɐ„ƒ ‘ɐƄ
ʴʴʴŽ— Šɏ ‘—–‡”ʰ‘—–‡”ſŽ— Šƀ
ʴʴʴŽ— Šɏ ‘—–‡”
‘—–‡”ſƇɐ‡‰‰•ɐśɩřɐ„ƒ ‘ɐśɨƈƀ

Счетчики можно объединить с помощью оператора ʫ:


ʴʴʴ„”‡ƒˆƒ•–ɏ ‘—–‡”ʫŽ— Šɏ ‘—–‡”
‘—–‡”ſƇɐ•’ƒɐśɪřɐ‡‰‰•ɐśɪřɐ„ƒ ‘ɐśɨƈƀ

Как нетрудно догадаться, счетчики можно вычитать друг из друга с помощью


оператора Ş. Например, «что мы будем есть на завтрак, но не на обед?».
ʴʴʴ„”‡ƒˆƒ•–ɏ ‘—–‡”ŹŽ— Šɏ ‘—–‡”
‘—–‡”ſƇɐ•’ƒɐśɪƈƀ

О’кей. А теперь узнаем, что мы можем съесть на обед, но не можем на завтрак:


ʴʴʴŽ— Šɏ ‘—–‡”Ź„”‡ƒˆƒ•–ɏ ‘—–‡”
‘—–‡”ſƇɐ„ƒ ‘ɐśɨřɐ‡‰‰•ɐśɨƈƀ

По аналогии с множествами, показанными в главе 8, вы можете получить общие


элементы с помощью оператора пересечения ĺ:
ʴʴʴ„”‡ƒˆƒ•–ɏ ‘—–‡”厗 Šɏ ‘—–‡”
‘—–‡”ſƇɐ‡‰‰•ɐśɨƈƀ

В результате пересечения был получен общий элемент ɐ‡‰‰•ɐ с наименьшим ко-


личеством. Это имеет смысл: на завтрак было только одно яйцо, поэтому указанное
(наименьшее) количество является общим.
Наконец, вы можете получить все элементы с помощью оператора объедине-
ния Ŷ:
ʴʴʴ„”‡ƒˆƒ•–ɏ ‘—–‡”ŶŽ— Šɏ ‘—–‡”
‘—–‡”ſƇɐ•’ƒɐśɪřɐ‡‰‰•ɐśɩřɐ„ƒ ‘ɐśɨƈƀ
ǫȓȈȊȈǴȖȌțȓȐȗȈȒȍȚȣȐȗȘȖȋȘȈȔȔȣ  

Элемент ɐ‡‰‰•ɐ снова оказался общим для обоих счетчиков. В отличие от сло-
жения объединение не складывает счетчики, а выбирает тот, который имеет наи-
большее значение.

ǻȗȖȘȧȌȖȟȐȊȈȍȔȗȖȒȓȦȟțșȗȖȔȖȡȤȦ2UGHUHG'LFW
Перед вами пример, запущенный с помощью интерпретатора Python 2:
ʴʴʴ“—‘–‡•ʰƇ
ŜŜŜɐ‘‡ɐśɐ™‹•‡‰—›řŠ—Šţɐř
ŜŜŜɐƒ””›ɐśɐ™Šɐř
ŜŜŜɐ—”Ž›ɐśɐ›—›—Šɐř
ŜŜŜƈ
ʴʴʴˆ‘”•–‘‘‰‡‹“—‘–‡•ś
ŜŜŜ’”‹–ſ•–‘‘‰‡ƀ
ŜŜŜ
ƒ””›
—”Ž›
‘‡

ǵȈȟȐȕȈȧșȊȍȘșȐȐ3\WKRQșȓȖȊȈȘȐșȖȝȘȈȕȧȦȚȖȟȍȘȍȌȕȖșȚȤȒȓȦȟȍȑȊȒȖȚȖȘȖȑ
ȖȕȐȉȣȓȐȌȖȉȈȊȓȍȕȣǪȘȈȕȕȐȝȊȍȘșȐȧȝȔȖȎȕȖȐșȗȖȓȤȏȖȊȈȚȤ2UGHUHG'LFWȗȖșȒȖȓȤȒț
ȗȖȘȧȌȖȒȒȓȦȟȍȑȊȖȉȣȟȕȣȝșȓȖȊȈȘȧȝȕȍȖȗȘȍȌȍȓȍȕǷȘȐȔȍȘȣȐȏȥȚȖȋȖȗȖȌȘȈȏȌȍȓȈ
ȈȒȚțȈȓȤȕȣȚȖȓȤȒȖȊȚȖȔșȓțȟȈȍȍșȓȐȊȍȘșȐȧȊȈȠȍȋȖ3\WKRQȕȐȎȍ

Функция ”†‡”‡†‹ –ſƀ запоминает порядок, в котором добавлялись ключи,


и возвращает их в том же порядке с помощью итератора. Попробуем создать словарь
”†‡”‡†‹ – из последовательности кортежей вида «ключ — значение»:
ʴʴʴˆ”‘ ‘ŽŽ‡ –‹‘•‹’‘”–”†‡”‡†‹ –
ʴʴʴ“—‘–‡•ʰ”†‡”‡†‹ –ſƃ
ŜŜŜſɐ‘‡ɐřɐ™‹•‡‰—›řŠ—Šţɐƀř
ŜŜŜſɐƒ””›ɐřɐ™Šɐƀř
ŜŜŜſɐ—”Ž›ɐřɐ›—›—Šɐƀř
ŜŜŜƄƀ
ʴʴʴ
ʴʴʴˆ‘”•–‘‘‰‡‹“—‘–‡•ś
ŜŜŜ’”‹–ſ•–‘‘‰‡ƀ
ŜŜŜ
‘‡
ƒ””›
—”Ž›

ǹȚȍȒȖȟȍȘȍȌȤ GHTXH
†‡“—‡ (произносится как «дэк») — это двусторонняя очередь, которая имеет функции
как стека, так и очереди. Она полезна, когда нужно добавить или удалить элементы
с любого конца последовательности. В следующем примере мы будем двигаться
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

с обоих концов слова к его середине, чтобы проверить, является ли оно палиндро-
мом. Функция ’‘’އˆ–ſƀ удаляет крайний слева элемент и возвращает его, функ-
ция ’‘’ſƀ удаляет крайний справа элемент и возвращает его. Вместе они движутся
с концов слова к его середине. Эти действия продолжатся до тех пор, пока совпадают
крайние символы и пока не будет достигнута середина:
ʴʴʴ†‡ˆ’ƒŽ‹†”‘‡ſ™‘”†ƀś
ŜŜŜˆ”‘ ‘ŽŽ‡ –‹‘•‹’‘”–†‡“—‡
ŜŜŜ†“ʰ†‡“—‡ſ™‘”†ƀ
ŜŜŜ™Š‹Ž‡އſ†“ƀʴɨś
ŜŜŜ‹ˆ†“Ŝ’‘’އˆ–ſƀŠʰ†“Ŝ’‘’ſƀś
ŜŜŜ”‡–—” ƒŽ•‡
ŜŜŜ”‡–—””—‡
ŜŜŜ
ŜŜŜ
ʴʴʴ’ƒŽ‹†”‘‡ſɐƒɐƀ
”—‡
ʴʴʴ’ƒŽ‹†”‘‡ſɐ”ƒ ‡ ƒ”ɐƀ
”—‡
ʴʴʴ’ƒŽ‹†”‘‡ſɐɐƀ
”—‡
ʴʴʴ’ƒŽ‹†”‘‡ſɐ”ƒ†ƒ”ɐƀ
”—‡
ʴʴʴ’ƒŽ‹†”‘‡ſɐŠƒŽ‹„—–ɐƀ
ƒŽ•‡

Я воспользовался этим примером, чтобы проще проиллюстрировать работу †‡“—‡.


Если же вы действительно хотите создать программу для определения палиндромов,
гораздо удобнее сравнивать строку с ее «перевернутой» копией. В Python строковой
функции ”‡˜‡”•‡ſƀ не существует, но можно записать строку в обратном порядке
с помощью слайса, как показано здесь:
ʴʴʴ†‡ˆƒ‘–Ї”ɏ’ƒŽ‹†”‘‡ſ™‘”†ƀś
ŜŜŜ”‡–—”™‘”†ʰʰ™‘”†ƃśśŞɨƄ
ŜŜŜ
ʴʴʴƒ‘–Ї”ɏ’ƒŽ‹†”‘‡ſɐ”ƒ†ƒ”ɐƀ
”—‡
ʴʴʴƒ‘–Ї”ɏ’ƒŽ‹†”‘‡ſɐŠƒŽ‹„—–ɐƀ
ƒŽ•‡

ǰȚȍȘȐȘțȍȔȗȖșȚȘțȒȚțȘȈȔȒȖȌȈ
șȗȖȔȖȡȤȦȔȖȌțȓȧLWHUWRROV
Модуль itertools (KWWSVGRFVS\WKRQRUJOLEUDU\LWHUWRROVKWPO ) содержит особые
функции итератора. Все они возвращают один элемент при каждом вызове из
цикла for… in и запоминают свое состояние между вызовами.
Функция Šƒ‹ſƀ проходит по своим аргументам, как если бы они были единым
итерабельным объектом:
ʴʴʴ‹’‘”–‹–‡”–‘‘Ž•
ʴʴʴˆ‘”‹–‡‹‹–‡”–‘‘Ž•Ŝ Šƒ‹ſƃɨřɩƄřƃɐƒɐřɐ„ɐƄƀś
ǫȓȈȊȈǴȖȌțȓȐȗȈȒȍȚȣȐȗȘȖȋȘȈȔȔȣ  

ŜŜŜ’”‹–ſ‹–‡ƀ
ŜŜŜ
ɨ
ɩ
a
b

Функция › އſƀ является бесконечным итератором, проходящим в цикле по


своим аргументам:
ʴʴʴ‹’‘”–‹–‡”–‘‘Ž•
ʴʴʴˆ‘”‹–‡‹‹–‡”–‘‘Ž•Ŝ › އſƃɨřɩƄƀś
ŜŜŜ’”‹–ſ‹–‡ƀ
ŜŜŜ
ɨ
ɩ
ɨ
ɩ
Ŝ
Ŝ
Ŝ

…И т. д.
Функция ƒ ——Žƒ–‡ſƀ подсчитывает накопленные значения. По умолчанию она
высчитывает сумму:
ʴʴʴ‹’‘”–‹–‡”–‘‘Ž•
ʴʴʴˆ‘”‹–‡‹‹–‡”–‘‘Ž•Ŝƒ ——Žƒ–‡ſƃɨřɩřɪřɫƄƀś
ŜŜŜ’”‹–ſ‹–‡ƀ
ŜŜŜ
ɨ
ɪ
6
ɨɥ

В качестве второго аргумента функции ƒ ——Žƒ–‡ſƀ вы можете передать функцию,


и она будет использована вместо сложения. Функция должна принимать два аргу-
мента и возвращать одно значение. В этом примере высчитывается произведение:
ʴʴʴ‹’‘”–‹–‡”–‘‘Ž•
ʴʴʴ†‡ˆ—Ž–‹’Ž›ſƒř„ƀś
ŜŜŜ”‡–—”ƒƋ„
ŜŜŜ
ʴʴʴˆ‘”‹–‡‹‹–‡”–‘‘Ž•Ŝƒ ——Žƒ–‡ſƃɨřɩřɪřɫƄř—Ž–‹’Ž›ƀś
ŜŜŜ’”‹–ſ‹–‡ƀ
ŜŜŜ
ɨ
ɩ
6
ɩɫ

Модуль itertools имеет гораздо больше функций. Некоторые из них, предна-


значенные, в частности, для комбинаций и перестановок, могут сэкономить много
времени, если это будет нужно.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

DzȘȈșȐȊȖȊȣȊȖȌȐȔȌȈȕȕȣȍȕȈȥȒȘȈȕ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐSSULQW
Во всех наших примерах использовалась функция ’”‹–ſƀ (или просто имя пере-
менной в интерактивном интерпретаторе) для вывода информации на экран. Иногда
прочитать результаты бывает трудно. Нам нужен pretty printer (красивый прин-
тер), такой как ’’”‹–ſƀ:
ʴʴʴˆ”‘’’”‹–‹’‘”–’’”‹–
ʴʴʴ“—‘–‡•ʰ”†‡”‡†‹ –ſƃ
ŜŜŜſɐ‘‡ɐřɐ™‹•‡‰—›řŠ—Šţɐƀř
ŜŜŜſɐƒ””›ɐřɐ™Šɐƀř
ŜŜŜſɐ—”Ž›ɐřɐ›—›—Šɐƀř
ŜŜŜƄƀ
ʴʴʴ

Старая добрая функция ’”‹–ſƀ просто выводит всю информацию:


ʴʴʴ’”‹–ſ“—‘–‡•ƀ
”†‡”‡†‹ –ſƃſɐ‘‡ɐřɐ™‹•‡‰—›řŠ—Šţɐƀřſɐƒ””›ɐřɐ™Šɐƀř
ſɐ—”Ž›ɐřɐ›—›—ŠɐƀƄƀ

А функция ’’”‹–ſƀ пытается выровнять элементы для лучшей читаемости:


ʴʴʴ’’”‹–ſ“—‘–‡•ƀ
Ƈɐ‘‡ɐśɐ™‹•‡‰—›řŠ—Šţɐř
ɐƒ””›ɐśɐ™Šɐř
ɐ—”Ž›ɐśɐ›—›—Šɐƈ

ǸȈȉȖȚȈȍȔșȖșȓțȟȈȑȕȣȔȐȟȐșȓȈȔȐ
В начале этой главы мы воспользовались функцией ”ƒ†‘Ŝ Š‘‹ ‡ſƀ. Она возвраща-
ет значение из последовательности (списка, кортежа, словаря или строки), которая
была передана в качестве аргумента:
ʴʴʴˆ”‘”ƒ†‘‹’‘”– Š‘‹ ‡
ʴʴʴ Š‘‹ ‡ſƃɩɪřɰřɫɭřɐ„ƒ ‘ɐřɥšɨɩɪƒ„ Ƅƀ
ɨɨɰɫɭɯɫ
ʴʴʴ Š‘‹ ‡ſſɐƒɐřɐ‘‡ɐřɐƒ†Şƒɐřɐ–™‘ɐƀƀ
ɐ‘‡ɐ
ʴʴʴ Š‘‹ ‡ſ”ƒ‰‡ſɨɥɥƀƀ
ɭɯ
ʴʴʴ Š‘‹ ‡ſɐƒŽ’Šƒ„‡–ɐƀ
ɐŽɐ

Используем функцию •ƒ’އſƀ для того, чтобы получить больше одного значения
за один раз:
ʴʴʴˆ”‘”ƒ†‘‹’‘”–•ƒ’އ
ʴʴʴ•ƒ’އſƃɩɪřɰřɫɭřɐ„ƒ ‘ɐřɥšɨɩɪƒ„ Ƅřɪƀ
ƃɨɨɰɫɭɯɫřɩɪřɰƄ
ʴʴʴ•ƒ’އſſɐƒɐřɐ‘‡ɐřɐƒ†Şƒɐřɐ–™‘ɐƀřɩƀ
ƃɐ–™‘ɐřɐƒ†ŞƒɐƄ
ʴʴʴ•ƒ’އſ”ƒ‰‡ſɨɥɥƀřɫƀ
ǫȓȈȊȈǴȖȌțȓȐȗȈȒȍȚȣȐȗȘȖȋȘȈȔȔȣ  

ƃɬɫřɯɩřɨɥřɮɯƄ
ʴʴʴ•ƒ’އſɐƒŽ’Šƒ„‡–ɐřɮƀ
ƃɐŽɐřɐ‡ɐřɐƒɐřɐ–ɐřɐ’ɐřɐƒɐřɐ„ɐƄ
Чтобы получить случайное целое число из любого диапазона, можно обратиться
к функциям Š‘‹ ‡ſƀ или •ƒ’އſƀ, передав в них возвращаемое значение функции
”ƒ‰‡ſƀ. Можно воспользоваться также функциями ”ƒ†‹–ſƀ или ”ƒ†”ƒ‰‡ſƀ:
ʴʴʴˆ”‘”ƒ†‘‹’‘”–”ƒ†‹–
ʴʴʴ”ƒ†‹–ſɪɯřɮɫƀ
ɮɨ
ʴʴʴ”ƒ†‹–ſɪɯřɮɫƀ
ɭɥ
ʴʴʴ”ƒ†‹–ſɪɯřɮɫƀ
ɭɨ
Функция ”ƒ†”ƒ‰‡ſƀ, как и функция ”ƒ‰‡ſƀ, имеет аргументы для начального
значения (включительно), конечного (не включительно), а также для необязатель-
ного целочисленного параметра шага:
ʴʴʴˆ”‘”ƒ†‘‹’‘”–”ƒ†”ƒ‰‡
ʴʴʴ”ƒ†”ƒ‰‡ſɪɯřɮɫƀ
ɭɬ
ʴʴʴ”ƒ†”ƒ‰‡ſɪɯřɮɫřɨɥƀ
ɭɯ
ʴʴʴ”ƒ†”ƒ‰‡ſɪɯřɮɫřɨɥƀ
ɫɯ
Итак, получим случайное вещественное число (число с плавающей точкой)
между ɥŜɥ и ɨŜɥ:
ʴʴʴˆ”‘”ƒ†‘‹’‘”–”ƒ†‘
ʴʴʴ”ƒ†‘ſƀ
ɥŜɥɮɨɰɪɪɰɪɪɨɩɭɰɩɨɰɯ
ʴʴʴ”ƒ†‘ſƀ
ɥŜɮɫɥɪɩɫɪɭɮɪɯɩɭɩɮɨ
ʴʴʴ”ƒ†‘ſƀ
ɥŜɰɮɨɭɬɨɮɯɫɭɮɮɬɥɨɯ

ǵțȎȕȖȉȖȓȤȠȍȒȖȌȈ
Иногда стандартная библиотека не имеет того, что вам нужно, или делает что-то
не так, как вы хотите. В таком случае стоит вспомнить о том, что существует целый
мир стороннего программного обеспечения Python с открытым исходным кодом.
Отлично зарекомендовали себя следующие ресурсы:
‰PyPi (известный также как Cheese Shop («Магазин сыра») после старой пародии
Monty Python) (KWWSS\SLS\WKRQRUJ);
‰github (KWWSVJLWKXEFRP3\WKRQ);
‰readthedocs (KWWSVUHDGWKHGRFVRUJ).
Небольшие фрагменты кода вы можете найти по адресу KWWSFRGHDFWLYHVWDWHFRP
UHFLSHVODQJVS\WKRQ.
  ǿȈșȚȤ, ‡ ǶșȕȖȊȣ3\WKRQ

Почти везде в этой книге код Python использует функции стандартных библиотек
Python. Но кое-где представлены и внешние пакеты: в главе 1 я упоминал requests,
а в главе 18 рассматривал его более подробно. В приложении Б показано, как уста-
навливать стороннее программное обеспечение Python, и дана другая подробная
информация.

ǿȐȚȈȑȚȍȌȈȓȍȍ
Следующая глава посвящена аспектам манипуляции данными в Python. Вы позна-
комитесь с типами bytes и bytearray, обработаете символы Unicode в строке, а также
научитесь выполнять поиск в строке с помощью регулярных выражений.

ǻȗȘȈȎȕȍȕȐȧ
11.1. Создайте файл с именем œ‘‘Ŝ’›. В нем объявите функцию Š‘—”•ſƀ, которая
выводит на экран строку ɐ’‡ ɰŞɬ †ƒ‹Ž›ɐ. Далее используйте интерактивный
интерпретатор, чтобы импортировать модуль œ‘‘ и вызвать его функцию
Š‘—”•ſƀ.
11.2. В интерактивном интерпретаторе импортируйте модуль œ‘‘ под именем
‡ƒ‰‡”‹‡ и вызовите его функцию Š‘—”•ſƀ.
11.3. Оставаясь в интерпретаторе, импортируйте непосредственно функцию Š‘—”•ſƀ
из модуля œ‘‘ и вызовите ее.
11.4. Импортируйте функцию Š‘—”•ſƀ под именем info и вызовите ее.
11.5. Создайте словарь с именем plain, содержащий пары «ключ — значение» ɐƒɐś ɨ,
ɐ„ɐś ɩ и ɐ ɐśɪ, а затем выведите его на экран.
11.6. Создайте ”†‡”‡†‹ – с именем ˆƒ › из пар «ключ — значение», приведенных
в упражнении 11.5, и выведите его на экран. Изменился ли порядок ключей?
11.7. Создайте †‡ˆƒ—Ž–†‹ – с именем †‹ –ɏ‘ˆɏŽ‹•–• и передайте ему аргумент
list. Создайте список †‹ –ɏ‘ˆɏŽ‹•–•ƃɐƒɐƄ и присоедините к нему значение
ɐ•‘‡–Š‹‰ for ƒɐ за одну операцию. Выведите на экран †‹ –ɏ‘ˆɏŽ‹•–•ƃɐƒɐƄ.
ǿǨǹǺȄ,,
3\WKRQȕȈȗȘȈȒȚȐȒȍ
ƋƓƈƊƈ
ǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ

Если достаточно долго мучить данные, они


признаются [в чем угодно].
Рональд Коуз

До сих пор мы в основном говорили о самом языке Python — его типах данных,
структурах кода, синтаксисе и т. д. Остальная часть книги посвящена применению
Python для решения реальных задач.
В текущей главе вы познакомитесь со многими практическими приемами для
управления данными: в мире баз данных это иногда называют манипулированием
данными или ETL (extract/transform/load, то есть «извлечение/преобразование/
загрузка»). И хоть в книгах по программированию данная тема обычно не рассма-
тривается отдельно, программистам все равно приходится тратить много времени
на то, чтобы привести данные в нужную для своих целей форму.
За последние несколько лет специальность, связанная с «наукой о данных», стала
очень популярной. В статье Harvard Business Review профессия специалиста, работа-
ющего с данными, названа «самой сексуальной в XXI веке». Если речь о востребо-
ванности и достойной оплате, тогда ладно, но и рутины в этой профессии более чем
достаточно. Наука о данных выходит за пределы обычных требований ETL к базам
данных и зачастую включает в себя машинное обучение — для того чтобы можно было
находить идеи, недоступные человеческому взору. Я начну с рассмотрения простых
форматов данных, а затем перейду к самым полезным инструментам науки о данных.
Форматы данных делятся на две категории: текстовые и бинарные. Строки
в Python используются для текстовых данных, и как раз в этой главе содержится
информация о строках, которую мы пропустили ранее:
‰символы Unicode;
‰регулярные выражения.
Затем мы перейдем к бинарным данным и рассмотрим еще два типа, встроенных
в Python:
‰bytes для неизменяемых восьмибитных значений;
‰bytearrays для изменяемых.
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

ǺȍȒșȚȖȊȣȍșȚȘȖȒȐ8QLFRGH
С основами строк в Python вы познакомились в главе 5. Пришло время более по-
дробно рассмотреть формат Unicode.
Строки в Python 3 представляют собой последовательности символов Unicode,
а не массивы байтов. Это, безусловно, самое значительное изменение в языке по
сравнению с Python 2.
Все текстовые примеры до сих пор имели формат ASCII (American Standard
Code for Information Interchange). Этот формат был определен в 1960-х годах, когда
компьютеры были размером с холодильник и считали лишь немногим лучше его.
Основной единицей хранения информации был байт, который мог хранить
256 уникальных значений в своих 8 битах. По разным причинам формат ASCII ис-
пользовал только 7 бит (128 уникальных значений): 26 символов верхнего регистра,
26 символов нижнего регистра, десять цифр, некоторые знаки препинания, символы
пробела и непечатаемые символы.
Однако в мире существует больше букв, чем предоставляет формат ASCII.
..
Вы могли заказать в кафе хот-дог, но не Gewurztraminer1. Предпринималось мно-
жество попыток вместить больше букв и символов в 8 доступных бит, и время от
времени вы будете сталкиваться с такими форматами. Вот некоторые из них:
‰Latin-1 или ISO 8859-1;
‰Windows code page 1252.
Каждый из этих форматов использует все 8 бит, но даже их бывает недостаточ-
но, особенно если нужно воспользоваться неевропейскими языками. Unicode — это
действующий международный стандарт, определяющий символы всех языков мира
плюс математические и другие символы. Еще и эмодзи!

Unicode предоставляет уникальный номер каждому


символу, независимо от платформы, программы
и языка.

Консорциум Unicode

Страница Unicode Code Charts (KWWSZZZXQLFRGHRUJFKDUWV) содержит ссылки на


все определенные на данный момент наборы символов с изображениями. В послед-
ней версии (12.0) определяется более 137 000 символов, каждый из которых имеет
уникальное имя и идентификационный номер. Python 3.8 может работать со всеми
этими символами. Они разбиты на восьмибитные наборы, которые называются
плоскостями. Первые 256 плоскостей называются основными многоязычными уров-
нями. Обратитесь к странице о плоскостях в «Википедии» (KWWSVUXZLNLSHGLDRUJZLNL
ǷȓȖșȒȖșȚȤB ȆȕȐȒȖȌ ), чтобы получить более подробную информацию.

..
1
Название вина в Германии пишется через u, но теряет эту букву в Эльзасе по пути во
Францию.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǹȚȘȖȒȐȜȖȘȔȈȚȈ8QLFRGHȊ3\WKRQ
Если вы знаете Unicode ID или название символа, то можете использовать его
в строке Python. Вот несколько примеров.
‰Символ Ɏ— и расположенные за ним четыре шестнадцатеричных числа1 опреде-
ляют символ, находящийся в одной из 256 многоязычных плоскостей Unicode.
Два первых числа являются номером плоскости (от ɥɥ до ), а следующие два —
индексом символа внутри плоскости. Плоскость с номером ɥɥ — это старый до-
брый формат ASCII, и позиции символов в нем такие же, как и в ASCII.
‰Для символов более высоких плоскостей нужно больше битов. Управляющая
последовательность для них выглядит как Ɏ: за ней следуют восемь шестнадца-
теричных символов, крайний слева из которых должен быть равен ɥ.
‰Для всех символов конструкция ɎƇ ȜȠȳ ƈ позволяет указать символ с помощью
его стандартного имени. Имена перечислены по адресу KWWSZZZXQLFRGHRUJFKDUWV
FKDULQGH[KWPO.

Модуль —‹ ‘†‡†ƒ–ƒ содержит функции, которые преобразуют символы в обоих


направлениях:
‰Ž‘‘—’ſƀ принимает не зависящее от регистра имя и возвращает символ Unicode;
‰ƒ‡ſƀ принимает символ Unicode и возвращает его имя в верхнем регистре.
В следующем примере мы напишем проверочную функцию, которая принимает
символ Unicode, ищет его имя, а затем ищет символ, соответствующий полученному
имени (он должен совпасть с оригинальным):
ʴʴʴ†‡ˆ—‹ ‘†‡ɏ–‡•–ſ˜ƒŽ—‡ƀś
ŜŜŜ‹’‘”–—‹ ‘†‡†ƒ–ƒ
ŜŜŜƒ‡ʰ—‹ ‘†‡†ƒ–ƒŜƒ‡ſ˜ƒŽ—‡ƀ
ŜŜŜ˜ƒŽ—‡ɩʰ—‹ ‘†‡†ƒ–ƒŜŽ‘‘—’ſƒ‡ƀ
ŜŜŜ’”‹–ſɐ˜ƒŽ—‡ʰɑʩ•ɑřƒ‡ʰɑʩ•ɑř˜ƒŽ—‡ɩʰɑʩ•ɑɐʩſ˜ƒŽ—‡řƒ‡ř˜ƒŽ—‡ɩƀƀ
ŜŜŜ

Попробуем проверить несколько символов, начиная с простой буквы формата


ASCII:
ʴʴʴ—‹ ‘†‡ɏ–‡•–ſɐɐƀ
˜ƒŽ—‡ʰɑɑřƒ‡ʰɑ  ɑř˜ƒŽ—‡ɩʰɑɑ

Знак препинания, доступный в ASCII:


ʴʴʴ—‹ ‘†‡ɏ–‡•–ſɐɛɐƀ
˜ƒŽ—‡ʰɑɛɑřƒ‡ʰɑ ɑř˜ƒŽ—‡ɩʰɑɛɑ

Символ валюты из Unicode:


ʴʴʴ—‹ ‘†‡ɏ–‡•–ſɐɎ—ɥɥƒɩɐƀ
˜ƒŽ—‡ʰɑɝɑřƒ‡ʰɑ ɑř˜ƒŽ—‡ɩʰɑɝɑ

1
Числа шестнадцатеричной системы счисления, содержащие символы от 0 до 9 и от A до F.
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

Еще один символ валюты из Unicode:


ʴʴʴ—‹ ‘†‡ɏ–‡•–ſɐɎ—ɩɥƒ ɐƀ
˜ƒŽ—‡ʰɑɚɑřƒ‡ʰɑ ɑř˜ƒŽ—‡ɩʰɑɚɑ

Единственная проблема, с которой вы можете столкнуться, — это ограничения


на шрифт для отображения текста. Немногие шрифты имеют изображения для всех
символов Unicode — в таком случае вместо отсутствующих символов отображается
символ-заполнитель. Например, так выглядит символ Unicode , содержа-
щийся в пиктографических шрифтах:
ʴʴʴ—‹ ‘†‡ɏ–‡•–ſɐɎ—ɩɭɥɪɐƀ
˜ƒŽ—‡ʰɑ۹ɑřƒ‡ʰɑɑř˜ƒŽ—‡ɩʰɑ۹"

Предположим, мы хотим сохранить в строке слово ƒˆ². Одно из решений со-


стоит в том, чтобы скопировать его из файла или с сайта и понадеяться, что это
сработает:
ʴʴʴ’Žƒ ‡ʰɐ ƒˆ²ɐ
ʴʴʴ’Žƒ ‡
ɐ ƒˆ²ɐ

Это сработало, поскольку я скопировал слово из источника, использующего


кодировку UTF-8 (которую мы рассмотрим далее), и вставил его.
Как же нам указать, что последний символ — это ²? Если вы посмотрите на
индекс символа ǥ , то увидите, что имя    ř     имеет
индекс 00Е9. Проверим функциями ƒ‡ſƀ и Ž‘‘—’ſƀ, с которыми мы только что
работали.
Сначала передадим код символа, чтобы получить его имя:
ʴʴʴ—‹ ‘†‡†ƒ–ƒŜƒ‡ſɐɎ—ɥɥ‡ɰɐƀ
ɐ   ɐ

Теперь найдем код для заданного имени:


ʴʴʴ—‹ ‘†‡†ƒ–ƒŜŽ‘‘—’ſɐ  ř ɐƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
‡›””‘”śɑ—†‡ˆ‹‡† Šƒ”ƒ –‡”ƒ‡ɐ  ř ɐɑ

ǰȔȍȕȈȗȍȘȍȟȐșȓȍȕȕȣȍȊșȗȐșȒȍ8QLFRGH&KDUDFWHU1DPH,QGH[ȉȣȓȐȗȍȘȍȜȖȘȔȈ
ȚȐȘȖȊȈȕȣȌȓȧțȌȖȉșȚȊȈȖȚȖȉȘȈȎȍȕȐȧǬȓȧȚȖȋȖȟȚȖȉȣȗȘȍȖȉȘȈȏȖȊȈȚȤȐȝȊȕȈșȚȖ
ȧȡȐȍȐȔȍȕȈșȐȔȊȖȓȖȊ8QLFRGH ȒȖȚȖȘȣȍȐșȗȖȓȤȏțȦȚșȧȊ3\WKRQ țȌȈȓȐȚȍȏȈȗȧȚțȦ
Ȑ ȗȍȘȍȔȍșȚȐȚȍ Țț ȟȈșȚȤ ȐȔȍȕȐ ȒȖȚȖȘȈȧ ȕȈȝȖȌȐȚșȧ ȗȖșȓȍ ȕȍȍ Ȋ șȈȔȖȍ ȕȈȟȈȓȖ
ǹȖȖȚȊȍȚșȚȊȍȕȕȖȊȕȈȠȍȔȗȘȐȔȍȘȍ(:,7+$&87(/$7,160$///(77(5ȕțȎȕȖȐȏ
ȔȍȕȐȚȤȕȈ/$7,160$///(77(5(:,7+$&87(
ʴʴʴ—‹ ‘†‡†ƒ–ƒŜŽ‘‘—’ſɐ   ɐƀ
ɐ²ɐ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Теперь мы можем указать символ ² и по коду, и по имени:


ʴʴʴ’Žƒ ‡ʰɐ ƒˆɎ—ɥɥ‡ɰɐ
ʴʴʴ’Žƒ ‡
ɐ ƒˆ²ɐ
ʴʴʴ’Žƒ ‡ʰɐ ƒˆɎƇ   ƈɐ
ʴʴʴ’Žƒ ‡
ɐ ƒˆ²ɐ

В предыдущем фрагменте вы вставили символ ² непосредственно в строку, но


также строку можно построить, добавив:
ʴʴʴ—ɏ—Žƒ—–ʰɐɎƇ     ƈɐ
ʴʴʴ—ɏ—Žƒ—–
ɐõɐ
ʴʴʴ†”‹ʰɐ ‡™ɐʫ—ɏ—Žƒ—–ʫɐ”œ–”ƒ‹‡”ɐ
ʴʴʴ’”‹–ſɐ‘™  ƒˆ‹ƒŽŽ›Šƒ˜‡›ɐř†”‹řɐ‹ƒɐř’Žƒ ‡ƀ
‘™  ƒˆ‹ƒŽŽ›Šƒ˜‡› ‡™ø”œ–”ƒ‹‡”‹ƒ ƒˆ²

Строковая функция އſƀ считает количество символов в кодировке Unicode,


а не байты:
ʴʴʴއſɐɛɐƀ
ɨ
ʴʴʴއſɐɎɥɥɥɨˆɫɮ„ɐƀ
ɨ

ǯȕȈȧȟȐșȓȖȊȖȑȐȌȍȕȚȐȜȐȒȈȚȖȘșȐȔȊȖȓȈȊ8QLFRGHȔȖȎȕȖȐșȗȖȓȤȏȖȊȈȚȤșȚȈȕȌȈȘȚȕȣȍ
ȜțȕȒȞȐȐRUG ȐFKU ȌȓȧȚȖȋȖȟȚȖȉȣȉȣșȚȘȖȊȣȗȖȓȕȧȚȤȗȘȍȖȉȘȈȏȖȊȈȕȐȧȔȍȎȌț
ȞȍȓȖȟȐșȓȍȕȕȣȔȐȐȌȍȕȚȐȜȐȒȈȚȖȘȈȔȐȐȖȌȕȖșȐȔȊȖȓȤȕȣȔȐșȚȘȖȒȈȔȐ8QLFRGH
ʴʴʴ Š”ſɩɪɪƀ
ɐ²ɐ
ʴʴʴ Š”ſɥš‡ɰƀ
ɐ²ɐ
ʴʴʴ Š”ſɥšɨˆ ɭƀ
ɐ ɐ

DzȖȌȐȘȖȊȈȕȐȍȐȌȍȒȖȌȐȘȖȊȈȕȐȍ
șȗȖȔȖȡȤȦȒȖȌȐȘȖȊȒȐ87)
Вам не нужно волноваться о том, как Python хранит каждый символ Unicode, когда
вы выполняете обычную обработку строки.
Но когда вы обмениваетесь данными с внешним миром, вам может понадобиться
следующее:
‰способ закодировать строку в байты;
‰способ декодировать байты обратно в строку.
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

Если бы в Unicode было менее 65 536 символов, мы могли бы хранить ID каж-


дого из них в 2 байтах. Однако символов больше, и если кодировать каждый ID
с помощью 3 или 4 байт, объем памяти и дискового пространства, необходимых для
обычных текстовых строк, увеличится в четыре раза.
Кен Томпсон и Роб Пайк, чьи имена знакомы работающим с Unix, однажды
вечером на салфетке в одной из столовых Нью-Джерси разработали UTF-8 — дина-
мическую схему кодирования. Она использует для символа Unicode от 1 до 4 байт:
‰1 байт для ASCII;
‰2 байта для большинства языков, основанных на латинице (но не кириллице);
‰3 байта для других основных языков;
‰4 байта для остальных языков, включая некоторые азиатские языки и символы.
UTF-8 — это стандартная текстовая кодировка для Python, Linux и HTML. Она ох-
ватывает множество символов, работает быстро и хорошо. Гораздо удобнее работать
с кодировкой UTF-8, чем постоянно переключаться с одной кодировки на другую.

ǭșȓȐȊȣșȖȏȌȈȍȚȍșȚȘȖȒț3\WKRQȗțȚȍȔȒȖȗȐȘȖȊȈȕȐȧȐȊșȚȈȊȒȐȐȏȌȘțȋȖȋȖȐșȚȖȟ
ȕȐȒȈȕȈȗȘȐȔȍȘȚȈȒȖȋȖȒȈȒȊȍȉșȚȘȈȕȐȞȈțȉȍȌȐȚȍșȤȟȚȖȐșȚȖȟȕȐȒȉȣȓȏȈȒȖȌȐ
ȘȖȊȈȕșȗȖȔȖȡȤȦ87)ǵȍȘȍȌȒȖȔȖȎȍȚȖȒȈȏȈȚȤșȧȟȚȖȚȍȒșȚȉȣȓȏȈȠȐȜȘȖȊȈȕ
șȗȖȔȖȡȤȦȒȖȌȐȘȖȊȖȒ/DWLQȐȓȐ:LQGRZVȈȥȚȖȗȘȐȒȖȗȐȘȖȊȈȕȐȐȊșȚȘȖȒț
3\WKRQȊȣȏȣȊȈȍȚȋȍȕȍȘȈȞȐȦȐșȒȓȦȟȍȕȐȑȐȏȏȈȕȍȒȖȘȘȍȒȚȕȖȑȗȖșȓȍȌȖȊȈȚȍȓȤȕȖșȚȐ
ȉȈȑȚȖȊ

DzȖȌȐȘȖȊȈȕȐȍ
Вы кодируете строку байтами. Первый аргумент строковой функции ‡ ‘†‡ſƀ — это
имя кодировки. Возможные варианты представлены в табл. 12.1.
ǺȈȉȓȐȞȈDzȖȌȐȘȖȊȒȐ

ǰȔȧȒȖȌȐȘȖȊȒȐ ǶȗȐșȈȕȐȍ
'ascii' Старая добрая семибитная кодировка ASCII
'utf-8' Восьмибитная кодировка переменной длины, самый предпочтительный
вариант в большинстве случаев
'latin-1' Также известна как ISO 8859-1
'cp-1252' Стандартная кодировка Windows
'unicode-escape' Буквенный формат Python Unicode, выглядит как \uxxxx или \Uxxxxxxxx

С помощью кодировки UTF-8 вы можете закодировать все что угодно. Присвоим


строку Unicode ɐɎ—ɩɭɥɪɐ переменной •‘™ƒ:
ʴʴʴ•‘™ƒʰɐɎ—ɩɭɥɪɐ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

•‘™ƒ — это строка Python Unicode, содержащая один символ независимо от


того, сколько байтов может потребоваться для ее сохранения:
ʴʴʴއſ•‘™ƒƀ
ɨ

Теперь закодируем этот символ последовательностью байтов:


ʴʴʴ†•ʰ•‘™ƒŜ‡ ‘†‡ſɐ—–ˆŞɯɐƀ

Как я упоминал ранее, кодировка UTF-8 имеет переменную длину. В данном случае
было использовано три байта для того, чтобы закодировать один символ •‘™ƒ:
ʴʴʴއſ†•ƀ
ɪ
ʴʴʴ†•
„ɐɎš‡ɩɎšɰɯɎšɯɪɐ

Функция އſƀ возвращает число байтов — ɪ, поскольку †• является переменной


bytes.
Вы можете использовать отличные от UTF-8 кодировки, но тогда вы получите
ошибку, если строка Unicode не сможет быть обработана другой кодировкой. Напри-
мер, если вы используете кодировку ƒ• ‹‹, произойдет сбой, если только вы не пре-
доставите строку, состоящую из корректных символов ASCII:
ʴʴʴ†•ʰ•‘™ƒŜ‡ ‘†‡ſɐƒ• ‹‹ɐƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
‹ ‘†‡ ‘†‡””‘”śɐƒ• ‹‹ɐ ‘†‡  ƒɐ–‡ ‘†‡ Šƒ”ƒ –‡”ɐɎ—ɩɭɥɪɐ
‹’‘•‹–‹‘ɥś‘”†‹ƒŽ‘–‹”ƒ‰‡ſɨɩɯƀ

Функция ‡ ‘†‡ſƀ принимает второй аргумент, который помогает избежать воз-


никновения исключений, связанных с кодировкой. Его значение по умолчанию, как
можно было видеть в предыдущем примере, равно ɐ•–”‹ –ɐ: такое значение приводит
к исключению ‹ ‘†‡ ‘†‡””‘”, когда обнаруживается символ, не входящий в ко-
дировку ASCII. Существуют и другие кодировки. Используйте значение ɐ‹‰‘”‡ɐ,
чтобы исключить все, что не может быть закодировано:
ʴʴʴ•‘™ƒŜ‡ ‘†‡ſɐƒ• ‹‹ɐřɐ‹‰‘”‡ɐƀ
„ɐɐ

Используйте значение ɐ”‡’Žƒ ‡ɐ, чтобы заменить неизвестные символы симво-


лами ţ:
ʴʴʴ•‘™ƒŜ‡ ‘†‡ſɐƒ• ‹‹ɐřɐ”‡’Žƒ ‡ɐƀ
„ɐţɐ

Используйте значение ɐ„ƒ •Žƒ•Š”‡’Žƒ ‡ɐ, чтобы создать строку, содержащую


символы Python Unicode, такие как —‹ ‘†‡Ş‡• ƒ’‡:
ʴʴʴ•‘™ƒŜ‡ ‘†‡ſɐƒ• ‹‹ɐřɐ„ƒ •Žƒ•Š”‡’Žƒ ‡ɐƀ
„ɐɎɎ—ɩɭɥɪɐ

Вы можете использовать этот вариант, если вам нужна печатная версия escape-
последовательности Unicode.
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

Используйте ɐšŽ Šƒ””‡ˆ”‡’Žƒ ‡ɐ , чтобы создавать безопасные для HTML


строки:
ʴʴʴ•‘™ƒŜ‡ ‘†‡ſɐƒ• ‹‹ɐřɐšŽ Šƒ””‡ˆ”‡’Žƒ ‡ɐƀ
„ɐĺɤɰɮɪɨŚɐ

Подробнее о преобразованиях HTML мы поговорим в подразделе «Сущности


HTML» на с. 250.

ǬȍȒȖȌȐȘȖȊȈȕȐȍ
Мы декодируем байтовые строки в текстовые строки Unicode. Когда мы получаем текст
из какого-то внешнего источника (файлов, баз данных, сайтов, сетевых API и т. д.),
он закодирован в виде байтовой строки. Самое сложное — узнать, какая кодировка
была использована, чтобы можно было декодировать и получить строку Unicode.
Проблема в следующем: ничто в байтовой строке не говорит нам о том, какая
кодировка была использована. Я уже упоминал опасность копирования/вставки
с сайтов. Вероятно, и вы встречали сайты со странными символами в тех местах, где
должны быть обычные символы ASCII.
Создадим строку Unicode, которая называется ’Žƒ ‡ и имеет значение ɐ ƒˆ²ɐ:
ʴʴʴ’Žƒ ‡ʰɐ ƒˆɎ—ɥɥ‡ɰɐ
ʴʴʴ’Žƒ ‡
ɐ ƒˆ²ɐ
ʴʴʴ–›’‡ſ’Žƒ ‡ƀ
ʳ Žƒ••ɐ•–”ɐʴ

Закодируем ее в формат UTF-8 с помощью переменной bytes, которая называ-


ется ’Žƒ ‡ɏ„›–‡•:
ʴʴʴ’Žƒ ‡ɏ„›–‡•ʰ’Žƒ ‡Ŝ‡ ‘†‡ſɐ—–ˆŞɯɐƀ
ʴʴʴ’Žƒ ‡ɏ„›–‡•
„ɐ ƒˆɎš ɪɎšƒɰɐ
ʴʴʴ–›’‡ſ’Žƒ ‡ɏ„›–‡•ƀ
ʳ Žƒ••ɐ„›–‡•ɐʴ

Обратите внимание на то, что переменная ’Žƒ ‡ɏ„›–‡• содержит 5 байт. Первые
три такие же, как в ASCII (преимущество UTF-8), а последние два кодируют символ
ɐ²ɐ. Теперь декодируем эту байтовую строку обратно в строку Unicode:
ʴʴʴ’Žƒ ‡ɩʰ’Žƒ ‡ɏ„›–‡•Ŝ†‡ ‘†‡ſɐ—–ˆŞɯɐƀ
ʴʴʴ’Žƒ ‡ɩ
ɐ ƒˆ²ɐ

Это сработало, поскольку мы закодировали и декодировали строку с помощью


кодировки UTF-8. Что, если бы мы указали декодировать ее с помощью какой-нибудь
другой кодировки?
ʴʴʴ’Žƒ ‡ɪʰ’Žƒ ‡ɏ„›–‡•Ŝ†‡ ‘†‡ſɐƒ• ‹‹ɐƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
‹ ‘†‡‡ ‘†‡””‘”śɐƒ• ‹‹ɐ ‘†‡  ƒɐ–†‡ ‘†‡„›–‡ɥš ɪ‹’‘•‹–‹‘ɪś
‘”†‹ƒŽ‘–‹”ƒ‰‡ſɨɩɯƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Декодер ASCII сгенерировал исключение, поскольку байтовое значение ɥš ɪ


некорректно в ASCII. Существуют и другие восьмибитные кодировки, где значе-
ния между 128 (80 в шестнадцатеричной системе) и 255 (FF в шестнадцатеричной
системе) корректны, но не совпадают со значениями UTF-8:
ʴʴʴ’Žƒ ‡ɫʰ’Žƒ ‡ɏ„›–‡•Ŝ†‡ ‘†‡ſɐŽƒ–‹Şɨɐƀ
ʴʴʴ’Žƒ ‡ɫ
ɐ ƒˆ!ɔɐ
ʴʴʴ’Žƒ ‡ɬʰ’Žƒ ‡ɏ„›–‡•Ŝ†‡ ‘†‡ſɐ™‹†‘™•Şɨɩɬɩɐƀ
ʴʴʴ’Žƒ ‡ɬ
ɐ ƒˆ!ɔɐ

Ох.
Мораль этой истории: по возможности используйте кодировку UTF-8. Она рабо-
тает и поддерживается везде, она способна выразить любой символ Unicode, и с ее
помощью можно быстро кодировать и декодировать.

ǺȖ ȟȚȖ Ȋȣ ȔȖȎȍȚȍ țȒȈȏȈȚȤ ȓȦȉȖȑ șȐȔȊȖȓ 8QLFRGH ȕȍ ȏȕȈȟȐȚ ȟȚȖ ȒȖȔȗȤȦȚȍȘ
șȔȖȎȍȚȐȝȊșȍ ȖȚȖȉȘȈȏȐȚȤȅȚȖȏȈȊȐșȐȚ ȖȚȠȘȐȜȚȈȒȖȚȖȘȣȑȊȣȐșȗȖȓȤȏțȍȚȍ ²
ȊȗȖȓȕȍȊȍȘȖȧȚȕȖȊȘȍȏțȓȤȚȈȚȍȊȣțȊȐȌȐȚȍȐȏȖȉȘȈȎȍȕȐȍȏȈȗȖȓȕȐȚȍȓȤȐȓȐȊȖȊșȍ
ȕȐȟȍȋȖDzȖȔȗȈȕȐȧ$SSOHșȖȏȌȈȓȈȠȘȐȜȚ/DVW5HVRUW)RQW KWWSVZZZXQLFRGHRUJ
SROLFLHVODVWUHVRUWIRQWBHXODKWPO Ȍȓȧ8QLFRGH&RQVRUWLXPȐȐșȗȖȓȤȏțȍȚȍȋȖȊșȊȖȐȝ
ȖȗȍȘȈȞȐȖȕȕȣȝ șȐșȚȍȔȈȝ ǵȈ șȚȘȈȕȐȞȍ KWWSVHQZLNLSHGLDRUJZLNL)DOOEDFNBIRQW
Ȋ©ǪȐȒȐȗȍȌȐȐªȔȖȎȕȖȕȈȑȚȐȉȖȓȍȍȗȖȌȘȖȉȕțȦȐȕȜȖȘȔȈȞȐȦǹțȡȍșȚȊțȍȚȚȈȒȎȍ
ȠȘȐȜȚ 8QLIRQW KWWSXQLIRXQGU\FRPXQLIRQWLQGH[KWPO  șȖȌȍȘȎȈȡȐȑ șȐȔȊȖȓȣ
ȊȌȐȈȗȈȏȖȕȍȖȚ?XȌȖ?XIIIIȈȚȈȒȎȍȕȍȒȖȚȖȘȣȍȌȘțȋȐȍ

ǹțȡȕȖșȚȐ+70/
В Python 3.4 появился еще один способ выполнять преобразования в Unicode и об-
ратно — с помощью символов-мнемоников HTML1. Этот подход может быть проще,
чем поиск имен Unicode, особенно если вы работаете в Интернете:
ʴʴʴ‹’‘”–Š–Ž
ʴʴʴŠ–ŽŜ—‡• ƒ’‡ſɑ凉”ƒ˜‡Śɑƀ
ɐ±ɐ

Такое преобразование также подходит для мнемоников, пронумерованных как


в десятичной, так и в шестнадцатеричной системах счисления:
ʴʴʴ‹’‘”–Š–Ž
ʴʴʴŠ–ŽŜ—‡• ƒ’‡ſɑĺɤɩɪɪŚɑƀ
ɐ²ɐ
ʴʴʴŠ–ŽŜ—‡• ƒ’‡ſɑĺɤš‡ɰŚɑƀ
ɐ²ɐ

1
По адресу [Link]
вы можете найти таблицу символов-мнемоников в HTML5.
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

Вы даже можете импортировать именованную сущность, содержащую соот-


ветствия, как словарь, и выполнить преобразование самостоятельно. Отбросьте
начальный символ ɐĺɐ в ключе словаря (можно также отбросить и последний
символ ɐŚɐ: кажется, сработает в обоих случаях):
ʴʴʴˆ”‘Š–ŽŜ‡–‹–‹‡•‹’‘”–Š–Žɬ
ʴʴʴŠ–Žɬƃɑ‡‰”ƒ˜‡ɑƄ
ɐ±ɐ
ʴʴʴŠ–Žɬƃɑ‡‰”ƒ˜‡ŚɑƄ
ɐ±ɐ

Чтобы выполнить обратное преобразование (из одного символа Python Unicode


в символ-мнемоник HTML), сначала нужно получить десятичное значение символа
с помощью функции ‘”†ſƀ:
ʴʴʴ‹’‘”–Š–Ž
ʴʴʴ Šƒ”ʰɐɎ—ɥɥ‡ɰɐ
ʴʴʴ†‡ ɏ˜ƒŽ—‡ʰ‘”†ſ Šƒ”ƀ
ʴʴʴŠ–ŽŜ‡–‹–‹‡•Ŝ ‘†‡’‘‹–ɩƒ‡ƃ†‡ ɏ˜ƒŽ—‡Ƅ
ɐ‡ƒ —–‡ɐ

Для строк Unicode, содержащих больше одного символа, используйте следующее


преобразование, состоящее из двух этапов:
ʴʴʴ’Žƒ ‡ʰɐ ƒˆɎ—ɥɥ‡ɰɐ
ʴʴʴ„›–‡ɏ˜ƒŽ—‡ʰ’Žƒ ‡Ŝ‡ ‘†‡ſɐƒ• ‹‹ɐřɐšŽ Šƒ””‡ˆ”‡’Žƒ ‡ɐƀ
ʴʴʴ„›–‡ɏ˜ƒŽ—‡
„ɐ ƒˆĺɤɩɪɪŚɐ
ʴʴʴ„›–‡ɏ˜ƒŽ—‡Ŝ†‡ ‘†‡ſƀ
ɐ ƒˆĺɤɩɪɪŚɐ

Выражение ’Žƒ ‡Ŝ‡ ‘†‡ſɐƒ• ‹‹ɐř ɐšŽ Šƒ””‡ˆ”‡’Žƒ ‡ɐƀ вернуло символы
ASCII, приведенные к типу bytes (поскольку они были закодированы). Следующее
выражение „›–‡ɏ˜ƒŽ—‡Ŝ†‡ ‘†‡ſƀ необходимо для того, чтобы преобразовать пере-
менную „›–‡ɏ˜ƒŽ—‡ в строку, совместимую с HTML.

ǵȖȘȔȈȓȐȏȈȞȐȧ
Некоторые символы Unicode могут быть представлены более чем одним кодом
Unicode. Они выглядят одинаково, но их сравнение даст отрицательный результат, по-
скольку они содержат разные последовательности байтов. Например, возьмем символ
с акутом ɐ²ɐ в слове ɐ ƒˆ²ɐ. Создадим односимвольную ɐ²ɐ несколькими способами:
ʴʴʴ‡ƒ —–‡ɨʰɐ²ɐɤ ŞɯřȥȞȢȣȜȤȢȖȔȡ
ʴʴʴ‡ƒ —–‡ɩʰɐɎ—ɥɥ‡ɰɐɤȞȢȘ‹ ‘†‡
ʴʴʴ‡ƒ —–‡ɪʰɎɤȜȠȳ‹ ‘†‡
ŜŜŜɐɎƇ   ƈɐ
ʴʴʴ‡ƒ —–‡ɫʰ Š”ſɩɪɪƀɤȘșȥȳȦȜȫȡȢșȕȔȝȦȢȖȢșțȡȔȫșȡȜș
ʴʴʴ‡ƒ —–‡ɬʰ Š”ſɥš‡ɰƀɤȬșȥȦȡȔȘȪȔȦșȤȜȫȡȢșȕȔȝȦȢȖȢșțȡȔȫșȡȜș
ʴʴʴ‡ƒ —–‡ɨř‡ƒ —–‡ɩř‡ƒ —–‡ɪř‡ƒ —–‡ɫř‡ƒ —–‡ɬ
ſɐ²ɐřɐ²ɐřɐ²ɐřɐ²ɐřɐ²ɐƀ
ʴʴʴ‡ƒ —–‡ɨʰʰ‡ƒ —–‡ɩʰʰ‡ƒ —–‡ɪʰʰ‡ƒ —–‡ɫʰʰ‡ƒ —–‡ɬ
”—‡
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Выполним несколько проверок:


ʴʴʴ‹’‘”–—‹ ‘†‡†ƒ–ƒ
ʴʴʴ—‹ ‘†‡†ƒ–ƒŜƒ‡ſ‡ƒ —–‡ɨƀ
ɐ   ɐ
ʴʴʴ‘”†ſ‡ƒ —–‡ɨƀɤȞȔȞȘșȥȳȦȜȫȡȢșȪșȟȢșȫȜȥȟȢ
ɩɪɪ
ʴʴʴɥš‡ɰɤȬșȥȦȡȔȘȪȔȦșȤȜȫȡȢșȪșȟȢșȫȜȥȟȢ‹ ‘†‡
ɩɪɪ

Теперь создадим символ e с акутом, объединив простой символ e и акут:


ʴʴʴ‡ƒ —–‡ɏ ‘„‹‡†ɨʰɑ‡Ɏ—ɥɪɥɨɑ
ʴʴʴ‡ƒ —–‡ɏ ‘„‹‡†ɩʰɑ‡ɎƇ   ƈɑ
ʴʴʴ‡ƒ —–‡ɏ ‘„‹‡†ɪʰɑ‡ɑʫɑɎ—ɥɪɥɨɑ
ʴʴʴ‡ƒ —–‡ɏ ‘„‹‡†ɨř‡ƒ —–‡ɏ ‘„‹‡†ɩř‡ƒ —–‡ɏ ‘„‹‡†ɪ
ſɐ²ɐřɐ²ɐřɐ²ɐƀƀ
ʴʴʴ‡ƒ —–‡ɏ ‘„‹‡†ɨʰʰ‡ƒ —–‡ɏ ‘„‹‡†ɩʰʰ‡ƒ —–‡ɏ ‘„‹‡†ɪ
”—‡
ʴʴʴއſ‡ƒ —–‡ɏ ‘„‹‡†ɨƀ
ɩ

Мы создали символ Unicode из двух других, и он выглядит так же, как и ориги-
нальный символ ɐ²ɐ. Но, как говорят на «Улице Сезам», один из них не похож на
другой:
ʴʴʴ‡ƒ —–‡ɨʰʰ‡ƒ —–‡ɏ ‘„‹‡†ɨ
ƒŽ•‡

Если у вас две разные строки Unicode, полученные из разных источников — одна
использует ‡ƒ —–‡ɨ, а вторая ‡ƒ —–‡ɏ ‘„‹‡†ɨ, — выглядеть они будут одинаково,
но поведут себя по-разному.
Исправить это можно с помощью функции ‘”ƒŽ‹œ‡ſƀ, которая содержится
в модуле —‹ ‘†‡†ƒ–ƒ:
ʴʴʴ‹’‘”–—‹ ‘†‡†ƒ–ƒ
ʴʴʴ‡ƒ —–‡ɏ‘”ƒŽ‹œ‡†ʰ—‹ ‘†‡†ƒ–ƒŜ‘”ƒŽ‹œ‡ſɐ ɐř‡ƒ —–‡ɏ ‘„‹‡†ɨƀ
ʴʴʴއſ‡ƒ —–‡ɏ‘”ƒŽ‹œ‡†ƀ
ɨ
ʴʴʴ‡ƒ —–‡ɏ‘”ƒŽ‹œ‡†ʰʰ‡ƒ —–‡ɨ
”—‡
ʴʴʴ—‹ ‘†‡†ƒ–ƒŜƒ‡ſ‡ƒ —–‡ɏ‘”ƒŽ‹œ‡†ƀ
ɐ   ɐ

ɐ ɐ означает normal form, composed (нормальная форма, составной символ).

ǷȖȌȘȖȉȕȈȧȐȕȜȖȘȔȈȞȐȧ
Если хотите узнать больше, эти ссылки будут вам полезны:
‰Unicode HOWTO (KWWSELWO\XQLFRGHKRZWR);
‰Pragmatic Unicode (KWWSELWO\SUDJPDWLFXQL);
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

‰The Absolute Minimum Every Software Developer Absolutely, Positively Must Know
About Unicode and Character Sets (No Excuses!) (KWWSELWO\MVSROVN\).

ǺȍȒșȚȖȊȣȍșȚȘȖȒȐȘȍȋțȓȧȘȕȣȍȊȣȘȈȎȍȕȐȧ
В главе 5 мы затронули операции со строками. Вооружившись этой вводной инфор-
мацией, вы, вероятно, использовали простые «подстановочные» шаблоны в команд-
ной строке, такие как команда UNIX ls ƋŜ’›, что означает перечисление всех имен
файлов, заканчивающихся на Ŝ’›.
Пришло время рассмотреть более сложный механизм проверки на совпадение
с шаблоном — регулярные выражения. Этот механизм поставляется в стандартном
модуле re, который мы импортируем. Вы определяете строковый шаблон, совпадения
для которого вам нужно найти, и строку-источник, в которой следует выполнить
поиск. Простой пример использования выглядит так:
ʴʴʴ‹’‘”–”‡
ʴʴʴ”‡•—Ž–ʰ”‡Ŝƒ– Šſɐ‘—ɐřɐ‘—‰ ”ƒ‡•–‡‹ɐƀ

В этом примере строка ɐ‘—ɐ является искомым шаблоном, а ɐ‘—‰ ”ƒ‡•–‡‹ɐ —


источником, строкой, которую вы хотите проверить. Функция ƒ– Šſƀ проверяет,
начинается ли источник с шаблона.
Для более сложных проверок вам нужно скомпилировать шаблон, чтобы уско-
рить поиск:
ʴʴʴ‹’‘”–”‡
ʴʴʴ›‘—’ƒ––‡”ʰ”‡Ŝ ‘’‹Ž‡ſɐ‘—ɐƀ

Далее вы можете выполнить проверку с помощью скомпилированного шаблона:


ʴʴʴ‹’‘”–”‡
ʴʴʴ”‡•—Ž–ʰ›‘—’ƒ––‡”Ŝƒ– Šſɐ‘—‰ ”ƒ‡•–‡‹ɐƀ

ǷȖșȒȖȓȤȒțȊ3\WKRQșȥȚȐȔȟȈșȚȖȗȘȐȝȖȌȐȚșȧȐȔȍȚȤȌȍȓȖȕȈȗȖȔȕȦȍȡȍȘȈȏȜțȕȒȞȐȧ
PDWFK ȐȡȍȚșȚȘȖȒțȠȈȉȓȖȕȚȖȓȤȒȖȊȕȈȟȈȓȍșȚȘȖȒȐȐșȚȖȟȕȐȒȈȈȜțȕȒȞȐȧVHDUFK 
ȐȡȍȚȠȈȉȓȖȕȊȓȦȉȖȔȔȍșȚȍȐșȚȖȟȕȐȒȈ

Функция ƒ– Šſƀ — не единственный способ сравнить шаблон и источник,


существует еще несколько методов (каждый из них мы рассмотрим в следующих
подразделах):
‰•‡ƒ” Šſƀ возвращает первое совпадение, если таковое имеется;
‰ˆ‹†ƒŽŽſƀ возвращает список всех непересекающихся совпадений, если таковые
имеются;
‰•’Ž‹–ſƀ разбивает источник на совпадения с шаблоном и возвращает список всех
фрагментов строки;
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰•—„ſƀ принимает аргумент для замены и заменяет все части источника, совпавшие
с шаблоном, на значение этого аргумента.

ǪȉȖȓȤȠȍȑȟȈșȚȐȗȘȐȔȍȘȖȊȘȍȋțȓȧȘȕȣȝȊȣȘȈȎȍȕȐȑȗȖȒȈȏȈȕȕȣȝȏȌȍșȤȐșȗȖȓȤȏțȍȚșȧ
ȒȖȌȐȘȖȊȒȈ$6&,,ȕȖșȚȘȖȒȖȊȣȍȜțȕȒȞȐȐ3\WKRQȊȒȓȦȟȈȧȜțȕȒȞȐȐȌȓȧȘȈȉȖȚȣșȘȍ
ȋțȓȧȘȕȣȔȐȊȣȘȈȎȍȕȐȧȔȐȘȈȉȖȚȈȦȚșȓȦȉȖȑșȚȘȖȒȖȑ3\WKRQȐȓȦȉȣȔȐșȐȔȊȖȓȈȔȐ
ȐȏȒȖȌȐȘȖȊȒȐ8QLFRGH

ǰȡȍȔȚȖȟȕȖȍȕȈȟȈȓȤȕȖȍșȖȊȗȈȌȍȕȐȍ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐPDWFK
Начинается ли строка ɐ‘—‰ ”ƒ‡•–‡‹ɐ со слова ɐ‘—ɐ? Рассмотрим пример
кода с комментариями:
ʴʴʴ‹’‘”–”‡
ʴʴʴ•‘—” ‡ʰɐ‘—‰ ”ƒ‡•–‡‹ɐ
ʴʴʴʰ”‡Ŝƒ– Šſɐ‘—ɐř•‘—” ‡ƀɤȨȧȡȞȪȜȳȡȔȫȜȡȔșȦȤȔȕȢȦȔȦȰȥȡȔȫȔȟȔȜȥȦȢȫȡȜȞȔ
ʴʴʴ‹ˆśɤȨȧȡȞȪȜȳȖȢțȖȤȔȭȔșȦȢȕȮșȞȦŚȘșȟȔȝȦșȱȦȢřȫȦȢȕȯȧȖȜȘșȦȰřȫȦȢȥȢȖȣȔȟȢ
ŜŜŜ’”‹–ſŜ‰”‘—’ſƀƀ
ŜŜŜ
‘—
ʴʴʴʰ”‡Ŝƒ– Šſɐɋ‘—ɐř•‘—” ‡ƀɤȳȞȢȤȰȖȡȔȫȔȟșȥȦȤȢȞȜȘșȟȔșȦȦȢȚșȥȔȠȢș
ʴʴʴ‹ˆś
ŜŜŜ’”‹–ſŜ‰”‘—’ſƀƀ
ŜŜŜ
‘—

А что насчет ɐ ”ƒɐ?


ʴʴʴʰ”‡Ŝƒ– Šſɐ ”ƒɐř•‘—” ‡ƀ
ʴʴʴ‹ˆś
ŜŜŜ’”‹–ſŜ‰”‘—’ſƀƀ
ŜŜŜ

В этот раз функция ƒ– Šſƀ не вернула ничего, и оператор if не запустил опе-
ратор print.
Как я упоминал в разделе «Новое: I am the Walrus» на с. 89, в Python 3.8 этот
пример можно сократить с помощью так называемого оператора-«моржа»:
ʴʴʴ‹’‘”–”‡
ʴʴʴ•‘—” ‡ʰɐ‘—‰ ”ƒ‡•–‡‹ɐ
ʴʴʴ‹ˆśʰ”‡Ŝƒ– Šſɐ ”ƒɐř•‘—” ‡ƀś
ŜŜŜ’”‹–ſŜ‰”‘—’ſƀƀ
ŜŜŜ

Теперь используем функцию •‡ƒ” Šſƀ для того, чтобы найти шаблон ”ƒ в лю-
бом месте источника:
ʴʴʴ‹’‘”–”‡
ʴʴʴ•‘—” ‡ʰɐ‘—‰ ”ƒ‡•–‡‹
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

ʴʴʴʰ”‡Ŝ•‡ƒ” Šſɐ ”ƒɐř•‘—” ‡ƀ


ʴʴʴ‹ˆś
ŜŜŜ’”‹–ſŜ‰”‘—’ſƀƀ
ŜŜŜ
”ƒ

Изменим шаблон и попробуем найти первое совпадение с помощью функции


ƒ– Šſƀ:
ʴʴʴʰ”‡Ŝƒ– ŠſɐŜƋ ”ƒɐř•‘—” ‡ƀ
ʴʴʴ‹ˆśɤȨȧȡȞȪȜȳƒ– ŠȖȢțȖȤȔȭȔșȦȢȕȮșȞȦ
ŜŜŜ’”‹–ſŜ‰”‘—’ſƀƀ
ŜŜŜ
‘—‰ ”ƒ

Кратко объясню, как работает наш новый шаблон ɐŜƋ ”ƒɐ:


‰символ Ŝ означает любой отдельный символ;
‰символ * означает ноль или более предыдущих элементов. Если объединить сим-
волы ŜƋ, они будут означать любое количество символов (даже ноль);
‰ ”ƒ — это фраза, которую мы хотим найти в любом месте строки.
Функция ƒ– Šſƀ вернула строку, в которой нашлось совпадение с шабло-
ном ŜƋ ”ƒś ɐ‘—‰ ”ƒɐ.

ǰȡȍȔȗȍȘȊȖȍșȖȊȗȈȌȍȕȐȍșȗȖȔȖȡȤȦȜțȕȒȞȐȐVHDUFK
Вы можете использовать функцию •‡ƒ” Šſƀ, чтобы найти шаблон ɐ ”ƒɐ в любом
месте строки-источника ɐ‘—‰ ”ƒ‡•–‡‹ɐ, не прибегая к использованию символа
подстановки ŜƋ:
ʴʴʴ‹’‘”–”‡
ʴʴʴ•‘—” ‡ʰɐ‘—‰ ”ƒ‡•–‡‹ɐ
ʴʴʴʰ”‡Ŝ•‡ƒ” Šſɐ ”ƒɐř•‘—” ‡ƀ
ʴʴʴ‹ˆśɤȨȧȡȞȪȜȳ•‡ƒ” ŠȖȢțȖȤȔȭȔșȦȢȕȮșȞȦ
ŜŜŜ’”‹–ſŜ‰”‘—’ſƀƀ
ŜŜŜ
”ƒ

ǰȡȍȔȊșȍșȖȊȗȈȌȍȕȐȧȐșȗȖȓȤȏțȧȜțȕȒȞȐȦILQGDOO
В предыдущих примерах мы искали только одно совпадение. Но что, если нуж-
но узнать, сколько раз строка, содержащая один символ n, встречается в строке-
источнике?
ʴʴʴ‹’‘”–”‡
ʴʴʴ•‘—” ‡ʰɐ‘—‰ ”ƒ‡•–‡‹ɐ
ʴʴʴʰ”‡Ŝˆ‹†ƒŽŽſɐɐř•‘—” ‡ƀ
ʴʴʴɤˆ‹†ƒŽŽ”‡–—”•ƒŽ‹•–
ƃɐɐřɐɐřɐɐřɐɐƄ
ʴʴʴ’”‹–ſɐ ‘—†ɐřއſƀřɐƒ– Ї•ɐƀ
‘—†ɫƒ– Ї•
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

А что насчет строки ɐɐ, за которой следует любой символ?


ʴʴʴ‹’‘”–”‡
ʴʴʴ•‘—” ‡ʰɐ‘—‰ ”ƒ‡•–‡‹ɐ
ʴʴʴʰ”‡Ŝˆ‹†ƒŽŽſɐŜɐř•‘—” ‡ƀ
ʴʴʴ
ƃɐ‰ɐřɐɐřɐ•ɐƄ

Обратите внимание на то, что в совпадения не была записана последняя стро-


ка ɐɐ. Мы должны указать, что символ после ɐɐ является опциональным, с по-
мощью ţ:
ʴʴʴ‹’‘”–”‡
ʴʴʴ•‘—” ‡ʰɐ‘—‰ ”ƒ‡•–‡‹ɐ
ʴʴʴʰ”‡Ŝˆ‹†ƒŽŽſɐŜţɐř•‘—” ‡ƀ
ʴʴʴ
ƃɐ‰ɐřɐɐřɐ•ɐřɐɐƄ

ǸȈȏȉȐȊȈȍȔșȖȊȗȈȌȍȕȐȧșȗȖȔȖȡȤȦȜțȕȒȞȐȐVSOLW
В следующем примере показано, как разбить строку на список с помощью шаблона,
а не простой строки:
ʴʴʴ‹’‘”–”‡
ʴʴʴ•‘—” ‡ʰɐ‘—‰ ”ƒ‡•–‡‹ɐ
ʴʴʴʰ”‡Ŝ•’Ž‹–ſɐɐř•‘—” ‡ƀ
ʴʴʴɤȨȧȡȞȪȜȳ•’Ž‹–ȖȢțȖȤȔȭȔșȦȥȣȜȥȢȞ
ƃɐ‘—ɐřɐ‰ ”ƒɐřɐ‡ɐřɐ•–‡‹ɐřɐɐƄ

ǯȈȔȍȕȧȍȔșȖȊȗȈȌȍȕȐȧșȗȖȔȖȡȤȦȜțȕȒȞȐȐVXE
Этот метод похож на метод ”‡’Žƒ ‡ſƀ, но предназначен не для простых строк, а для
шаблонов:
ʴʴʴ‹’‘”–”‡
ʴʴʴ•‘—” ‡ʰɐ‘—‰ ”ƒ‡•–‡‹ɐ
ʴʴʴʰ”‡Ŝ•—„ſɐɐřɐţɐř•‘—” ‡ƀ
ʴʴʴɤ•—„”‡–—”•ƒ•–”‹‰
ɐ‘—ţ‰ ”ƒţ‡ţ•–‡‹ţɐ

ȀȈȉȓȖȕȣșȗȍȞȐȈȓȤȕȣȍșȐȔȊȖȓȣ
Многие описания регулярных выражений начинаются с подробной информации
о том, как их определить. Я считаю это неправильным. Регулярных выражений
не так уж и мало, поэтому в памяти приходится удерживать слишком большое ко-
личество деталей. К тому же регулярные выражения используют так много знаков
препинания, что выглядят как ругающиеся персонажи мультфильмов.
Теперь, когда вы знаете о нужных функциях (ƒ– Šſƀ , •‡ƒ” Šſƀ , ˆ‹†ƒŽŽſƀ
и •—„ſƀ), рассмотрим детали построения регулярных выражений. Создаваемые вами
шаблоны подойдут к любой из этих функций.
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

Самые простые знаки вы уже видели:


‰совпадения с любыми неспециальными символами;
‰любой отдельный символ, кроме Ɏ, — это символ Ŝ;
‰любое число включений предыдущего символа, включая ɥ, — это символ *;
‰опциональное значение (ɥ или ɨ) включений предыдущего символа — это символ ţ.
Специальные символы показаны в табл. 12.2.
ǺȈȉȓȐȞȈǹȗȍȞȐȈȓȤȕȣȍșȐȔȊȖȓȣ

ȀȈȉȓȖȕ ǹȖȊȗȈȌȍȕȐȧ
\d Цифровой символ
\D Нецифровой символ
\w Буквенный или цифровой символ или знак подчеркивания
\W Любой символ, кроме буквенного или цифрового символа или знака подчеркивания
\s Пробельный символ
\S Непробельный символ
\b Граница слова
\B Не граница слова

Модуль string содержит заранее определенные строковые константы, которые


можно использовать для тестирования. Попробуем применить константу printable:
она содержит 100 печатных символов ASCII, включая буквы в обоих регистрах,
цифры, пробелы и знаки пунктуации:
ʴʴʴ‹’‘”–•–”‹‰
ʴʴʴ’”‹–ƒ„އʰ•–”‹‰Ŝ’”‹–ƒ„އ
ʴʴʴއſ’”‹–ƒ„އƀ
ɨɥɥ
ʴʴʴ’”‹–ƒ„އƃɥśɬɥƄ
ɐɥɨɩɪɫɬɭɮɯɰƒ„ †‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œ ɐ
ʴʴʴ’”‹–ƒ„އƃɬɥśƄ
ɐŠɑɤɛʩĺɎɐſƀƋʫřŞŜŵśŚʳʰʴţɒƃɎɎƄɋɏļƇŶƈɌɎ–ɎɎ”Ɏšɥ„Ɏšɥ ɐ

Какие символы строки printable являются цифрами?


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐɎ†ɐř’”‹–ƒ„އƀ
ƃɐɥɐřɐɨɐřɐɩɐřɐɪɐřɐɫɐřɐɬɐřɐɭɐřɐɮɐřɐɯɐřɐɰɐƄ

Какие символы являются цифрами, буквами и нижним подчеркиванием?


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐɎ™ɐř’”‹–ƒ„އƀ
ƃɐɥɐřɐɨɐřɐɩɐřɐɪɐřɐɫɐřɐɬɐřɐɭɐřɐɮɐřɐɯɐřɐɰɐřɐƒɐřɐ„ɐř
ɐ ɐřɐ†ɐřɐ‡ɐřɐˆɐřɐ‰ɐřɐŠɐřɐ‹ɐřɐŒɐřɐɐřɐŽɐřɐɐřɐɐř
ɐ‘ɐřɐ’ɐřɐ“ɐřɐ”ɐřɐ•ɐřɐ–ɐřɐ—ɐřɐ˜ɐřɐ™ɐřɐšɐřɐ›ɐřɐœɐř
ɐɐřɐɐřɐɐřɐɐřɐɐřɐ ɐřɐ ɐřɐ ɐřɐ ɐřɐ ɐřɐɐřɐɐř
ɐɐřɐɐřɐɐřɐɐřɐɐřɐɐřɐɐřɐɐřɐɐřɐɐřɐɐřɐɐř
ɐɐřɐɐřɐɏɐƄ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Какие символы являются пробелами?


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐɎ•ɐř’”‹–ƒ„އƀ
ƃɐɐřɐɎ–ɐřɐɎɐřɐɎ”ɐřɐɎšɥ„ɐřɐɎšɥ ɐƄ

Перед вами пробелы в следующем порядке: простой пробел, табуляция, возврат


каретки, вертикальная табуляция и перевод страницы.
Регулярные выражения не ограничиваются символами ASCII. Шаблон Ɏ† совпа-
дает со всем, что в кодировке Unicode считается цифрой, а не только с символами
ASCII от 0 до 9. Добавим две не ASCII-буквы в нижнем регистре из ‹Ž‡ ‘”ƒ–Ŝ‹ˆ‘
(KWWSZZZILOHIRUPDWLQIRLQIRXQLFRGHFDWHJRU\/OOLVWKWP).
В этой проверке мы добавим туда следующие символы:
‰три буквы ASCII;
‰три знака препинания, которые не должны совпасть с шаблоном Ɏ™;
‰символ Unicode LATIN SMALL LETTER E WITH CIRCUMFLEX (Ɏ—ɥɥ‡ƒ);
‰символ Unicode LATIN SMALL LETTER E WITH BREVE (Ɏ—ɥɨɨɬ):
ʴʴʴšʰɐƒ„ ɐʫɐŞŵƋɐʫɐɎ—ɥɥ‡ƒɐʫɐɎ—ɥɨɨɬɐ

Как и ожидалось, шаблон нашел только буквы:


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐɎ™ɐřšƀ
ƃɐƒɐřɐ„ɐřɐ ɐřɐ³ɐřɐ·ɐɐƄ

ȀȈȉȓȖȕȣȐșȗȖȓȤȏȖȊȈȕȐȍșȗȍȞȐȜȐȒȈȚȖȘȖȊ
Теперь сделаем «пунктуационную пиццу», используя основные спецификаторы
шаблонов для регулярных выражений, показанные в табл. 12.3.
В этой таблице expr и другие слова, выделенные курсивом, означают любое кор-
ректное регулярное выражение.
ǺȈȉȓȐȞȈǹȗȍȞȐȜȐȒȈȚȖȘȣȠȈȉȓȖȕȖȊ

ȀȈȉȓȖȕ ǹȖȊȗȈȌȍȕȐȧ
abc Буквосочетание abc
(expr) expr
expr1 | expr2 expr1 или expr2
. Любой символ, кроме \n
^ Начало строки источника
$ Конец строки источника
prev ? Ноль или одно включение prev
prev * Ноль или больше включений prev, максимальное количество
prev *? Ноль или больше включений prev, минимальное количество
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

ȀȈȉȓȖȕ ǹȖȊȗȈȌȍȕȐȧ
prev + Одно или больше включений prev, максимальное количество
prev +? Одно или больше включений prev, минимальное количество
prev { m } m последовательных включений prev
prev { m, n } От m до n последовательных включений prev, максимальное количество
prev { m, n }? От m до n последовательных включений prev, минимальное количество
[abc] a, или b, или c (аналогично a|b|c)
[^ abc] Не (a, или b, или c)
prev (?= next) prev, если за ним следует next
prev (? ! next) prev, если за ним не следует next
(?<= prev) next next, если перед ним находится prev
(?<! prev) next next, если перед ним не находится prev

У вас могло зарябить в глазах при попытке прочесть эти примеры. Для начала
определим строку-источник:
ʴʴʴ•‘—” ‡ʰɐɐɐ ™‹•Š ƒ›ř ™‹•Š ‹‰Š–
ŜŜŜ ƒ˜‡ƒ†‹•Š‘ˆˆ‹•Š–‘‹‰Š–Ŝɐɐɐ

Теперь применим разные шаблоны и с помощью регулярных выражений попро-


буем найти их в строке-источнике.

ǪșȓȍȌțȦȡȐȝȗȘȐȔȍȘȈȝȊȒȈȟȍșȚȊȍȠȈȉȓȖȕȖȊȧȐșȗȖȓȤȏțȦȗȘȖșȚȣȍșȚȘȖȒȐȊȒȈȊȣȟ
ȒȈȝǬȈȓȍȍȊȥȚȖȔȗȖȌȘȈȏȌȍȓȍȧȗȖȒȈȎțȒȈȒȕȍȖȉȘȈȉȖȚȈȕȕȈȧșȚȘȖȒȈȠȈȉȓȖȕ ȖȕȈ
ȕȈȟȐȕȈȍȚșȧșșȐȔȊȖȓȈUȗȍȘȍȌȗȍȘȊȖȑȒȈȊȣȟȒȖȑ ȗȖȏȊȖȓȧȍȚȐȏȉȍȎȈȚȤȕȍȒȖȚȖȘȣȝ
ȒȖȕȜȓȐȒȚȖȊȔȍȎȌțȖȉȣȟȕȣȔȐHVFDSHȗȖșȓȍȌȖȊȈȚȍȓȤȕȖșȚȧȔȐȊ3\WKRQȐȘȍȋțȓȧȘ
ȕȣȔȐ ȊȣȘȈȎȍȕȐȧȔȐ ǰȏ șȖȖȉȘȈȎȍȕȐȑ ȉȍȏȖȗȈșȕȖșȚȐ ȗȍȘȊȣȔ ȈȘȋțȔȍȕȚȖȔ ȊȖ Ȋșȍȝ
șȓȍȌțȦȡȐȝȗȘȐȔȍȘȈȝȌȖȓȎȕȈȉȣȚȤȕȍȖȉȘȈȉȖȚȈȕȕȈȧșȚȘȖȒȈ

Для начала найдем в любом месте строку ɐ™‹•Šɐ:


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐ™‹•Šɐř•‘—” ‡ƀ
ƃɐ™‹•Šɐřɐ™‹•ŠɐƄ

Далее найдем строки ɐ™‹•Šɐ или ɐˆ‹•Šɐ:


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐ™‹•ŠŶˆ‹•Šɐř•‘—” ‡ƀ
ƃɐ™‹•Šɐřɐ™‹•Šɐřɐˆ‹•ŠɐƄ

Найдем строку ɐ™‹•Šɐ в начале текста:


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐɋ™‹•Šɐř•‘—” ‡ƀ
ƃƄ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Найдем строку ɐ ™‹•Šɐ в начале текста:


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐɋ ™‹•Šɐř•‘—” ‡ƀ
ƃɐ ™‹•ŠɐƄ

Найдем строку ɐˆ‹•Šɐ в конце текста:


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐˆ‹•Šɛɐř•‘—” ‡ƀ
ƃƄ

Наконец, найдем строку ɐˆ‹•Š –‘‹‰Š–Ŝɛɐ в конце текста:


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐˆ‹•Š–‘‹‰Š–Ŝɛɐř•‘—” ‡ƀ
ƃɐˆ‹•Š–‘‹‰Š–ŜɐƄ

Символы ɋ и $ называются якорями: с помощью якоря ɋ выполняется поиск


в начале строки, а с помощью якоря $ — в конце. Сочетание Ŝɛ совпадает с любым
символом в конце строки, включая точку, поэтому выражение сработало. Для обе-
спечения большей точности нужно создать escape-последовательность, чтобы найти
именно точку:
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐˆ‹•Š–‘‹‰Š–ɎŜɛɐř•‘—” ‡ƀ
ƃɐˆ‹•Š–‘‹‰Š–ŜɐƄ

Начнем с поиска символов w или f, за которыми следует буквосочетание ish:


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐƃ™ˆƄ‹•Šɐř•‘—” ‡ƀ
ƃɐ™‹•Šɐřɐ™‹•Šɐřɐˆ‹•ŠɐƄ

Найдем одно или несколько сочетаний символов w, s и h:


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐƃ™•ŠƄʫɐř•‘—” ‡ƀ
ƃɐ™ɐřɐ•Šɐřɐ™ɐřɐ•ŠɐřɐŠɐřɐ•Šɐřɐ•ŠɐřɐŠɐƄ

Найдем сочетание ght, за которым следует любой символ, кроме буквенного или
цифрового символа или знака подчеркивания:
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐ‰Š–Ɏɐř•‘—” ‡ƀ
ƃɐ‰Š–Ɏɐřɐ‰Š–ŜɐƄ

Найдем символ , за которым следует сочетание wish:


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐ ſţʰ™‹•Šƀɐř•‘—” ‡ƀ
ƃɐ ɐřɐ ɐƄ

И наконец, сочетание wish, перед которым находится :


ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐſţʳʰ ƀ™‹•Šɐř•‘—” ‡ƀ
ƃɐ™‹•Šɐřɐ™‹•ŠɐƄ

Существует несколько ситуаций, в которых правила шаблонов регулярных вы-


ражений конфликтуют с правилами для строк Python. Следующий шаблон должен
совпасть с любым словом, которое начинается с fish:
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſɐɎ„ˆ‹•Šɐř•‘—” ‡ƀ
ƃƄ
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

Почему этого не произошло? Как мы говорили в главе 5, Python использует


специальные escape-последовательности для строк. Например, Ɏ„ для строки
означает возврат на шаг, но в мини-языке регулярных выражений эта последо-
вательность означает начало слова. Избегайте случайного применения escape-
последовательностей, используя неформатированные строки Python, когда опре-
деляете строку регулярного выражения. Всегда размещайте символ r перед строкой
шаблона регулярного выражения, и escape-последовательности Python будут от-
ключены, как показано здесь:
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ”ɐɎ„ˆ‹•Šɐř•‘—” ‡ƀ
ƃɐˆ‹•ŠɐƄ

ȀȈȉȓȖȕȣțȒȈȏȣȊȈȍȔșȗȖșȖȉȊȣȊȖȌȈșȖȊȗȈȌȍȕȐȧ
При использовании функций ƒ– Šſƀ или •‡ƒ” Šſƀ все совпадения можно получить
из объекта результата , вызвав функцию Ŝ‰”‘—’ſƀ. Если вы заключите шаблон
в круглые скобки, совпадения будут сохранены в отдельную группу, а кортеж, со-
стоящий из них, окажется доступен благодаря вызову Ŝ‰”‘—’•ſƀ. Так, как показано
здесь:
ʴʴʴʰ”‡Ŝ•‡ƒ” Šſ”ɐſŜ†‹•ŠɎ„ƀŜƋſɎ„ˆ‹•Šƀɐř•‘—” ‡ƀ
ʴʴʴŜ‰”‘—’ſƀ
ɐƒ†‹•Š‘ˆˆ‹•Šɐ
ʴʴʴŜ‰”‘—’•ſƀ
ſɐƒ†‹•Šɐřɐˆ‹•Šɐƀ

Если вы используете этот шаблон ſţʳ ȜȠȳ ʴ ȖȯȤ ƀ, он совпадет с выражением ȖȯȤ
и сохранит совпадение в группе ȜȠȳ:
ʴʴʴʰ”‡Ŝ•‡ƒ” Šſ”ɐſţʳ  ʴŜ†‹•ŠɎ„ƀŜƋſţʳ  ʴɎ„ˆ‹•Šƀɐř•‘—” ‡ƀ
ʴʴʴŜ‰”‘—’ſƀ
ɐƒ†‹•Š‘ˆˆ‹•Šɐ
ʴʴʴŜ‰”‘—’•ſƀ
ſɐƒ†‹•Šɐřɐˆ‹•Šɐƀ
ʴʴʴŜ‰”‘—’ſɐ  ɐƀ
ɐƒ†‹•Šɐ
ʴʴʴŜ‰”‘—’ſɐ  ɐƀ
ɐˆ‹•Šɐ

ǩȐȕȈȘȕȣȍȌȈȕȕȣȍ
Работать с текстовыми данными может быть трудно, но работать с бинарными мо-
жет быть… интересно. Вам нужно знать о таких концепциях, как порядок следования
байтов (как процессор вашего компьютера разбивает данные на байты) и знаковые
биты для целых чисел. Вам может понадобиться закопаться в бинарные форматы
файлов или сетевых пакетов, чтобы извлечь или даже изменить данные. В этом раз-
деле я покажу вам основы работы с бинарными данными в Python.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

E\WHVȐE\WHDUUD\
В Python 3 появились последовательности восьмибитных целых чисел с возможны-
ми значениями от 0 до 255. Они могут быть двух типов:
‰bytes неизменяем, как кортеж байтов;
‰bytearray изменяем, как список байтов.
Начнем мы с создания списка с именем blist. В этом примере создадим переменную
типа bytes с именем –Š‡ɏ„›–‡• и переменную типа bytearray с именем –Š‡ɏ„›–‡ɏƒ””ƒ›:
ʴʴ„Ž‹•–ʰƃɨřɩřɪřɩɬɬƄ
ʴʴʴ–Їɏ„›–‡•ʰ„›–‡•ſ„Ž‹•–ƀ
ʴʴʴ–Їɏ„›–‡•
„ɐɎšɥɨɎšɥɩɎšɥɪɎšˆˆɐ
ʴʴʴ–Їɏ„›–‡ɏƒ””ƒ›ʰ„›–‡ƒ””ƒ›ſ„Ž‹•–ƀ
ʴʴʴ–Їɏ„›–‡ɏƒ””ƒ›
„›–‡ƒ””ƒ›ſ„ɐɎšɥɨɎšɥɩɎšɥɪɎšˆˆɐƀ

ǷȘȍȌșȚȈȊȓȍȕȐȍȏȕȈȟȍȕȐȧȚȐȗȈE\WHVȕȈȟȐȕȈȍȚșȧșșȐȔȊȖȓȈEȐȒȈȊȣȟȒȐȏȈȒȖ
ȚȖȘȣȔȐșȓȍȌțȦȚȠȍșȚȕȈȌȞȈȚȍȘȐȟȕȣȍȗȖșȓȍȌȖȊȈȚȍȓȤȕȖșȚȐȐȏșȐȔȊȖȓȖȊ?[ȐȓȐ
$6&,,ȐȏȈȒȈȕȟȐȊȈȍȚșȧȒȖȕșȚȘțȒȞȐȧșȖȖȚȊȍȚșȚȊțȦȡȐȔșȐȔȊȖȓȖȔȒȈȊȣȟȒȐ3\WKRQ
ȗȘȍȖȉȘȈȏțȍȚ ȠȍșȚȕȈȌȞȈȚȍȘȐȟȕȣȍ ȗȖșȓȍȌȖȊȈȚȍȓȤȕȖșȚȐ ȐȓȐ șȐȔȊȖȓȣ $6&,, Ȋ ȕȍ
ȉȖȓȤȠȐȍȞȍȓȣȍȟȐșȓȈȕȖȗȖȒȈȏȣȊȈȍȚȉȈȑȚȖȊȣȍȏȕȈȟȍȕȐȧȒȖȘȘȍȒȚȕȖȏȈȗȐșȈȕȕȣȍ
șȚȖȟȒȐȏȘȍȕȐȧȒȖȌȐȘȖȊȒȐ$6&,,
ʴʴʴ„ɐɎšɭɨɐ
„ɐƒɐ

ʴʴʴ„ɐɎšɥɨƒ„ Ɏšˆˆɐ
„ɐɎšɥɨƒ„ Ɏšˆˆɐ

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


bytes:
ʴʴʴ„Ž‹•–ʰƃɨřɩřɪřɩɬɬƄ
ʴʴʴ–Їɏ„›–‡•ʰ„›–‡•ſ„Ž‹•–ƀ
ʴʴʴ–Їɏ„›–‡•ƃɨƄʰɨɩɮ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
›’‡””‘”śɐ„›–‡•ɐ‘„Œ‡ –†‘‡•‘–•—’’‘”–‹–‡ƒ••‹‰‡–

Но переменная типа bytearray легко изменяется:


ʴʴʴ„Ž‹•–ʰƃɨřɩřɪřɩɬɬƄ
ʴʴʴ–Їɏ„›–‡ɏƒ””ƒ›ʰ„›–‡ƒ””ƒ›ſ„Ž‹•–ƀ
ʴʴʴ–Їɏ„›–‡ɏƒ””ƒ›
„›–‡ƒ””ƒ›ſ„ɐɎšɥɨɎšɥɩɎšɥɪɎšˆˆɐƀ
ʴʴʴ–Їɏ„›–‡ɏƒ””ƒ›ƃɨƄʰɨɩɮ
ʴʴʴ–Їɏ„›–‡ɏƒ””ƒ›
„›–‡ƒ””ƒ›ſ„ɐɎšɥɨɎšɮˆɎšɥɪɎšˆˆɐƀ
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

Каждая из этих переменных может содержать результат, состоящий из 256 эле-


ментов, имеющих значения от 0 до 255:
ʴʴʴ–Їɏ„›–‡•ʰ„›–‡•ſ”ƒ‰‡ſɥřɩɬɭƀƀ
ʴʴʴ–Їɏ„›–‡ɏƒ””ƒ›ʰ„›–‡ƒ””ƒ›ſ”ƒ‰‡ſɥřɩɬɭƀƀ

При выводе на экран содержимого переменных типа bytes или типа bytearray
Python использует формат Ɏššš для непечатаемых байтов и их эквиваленты ASCII для
печатаемых (и заменяет некоторые распространенные escape-последовательности,
например Ɏ на Ɏšɥƒ). Так выглядит на экране представление значения переменной
–Їɏ„›–‡• (переформатированное вручную для того, чтобы показать по 16 байт на
строку):
ʴʴʴ–Їɏ„›–‡•
„ɐɎšɥɥɎšɥɨɎšɥɩɎšɥɪɎšɥɫɎšɥɬɎšɥɭɎšɥɮɎšɥɯɎ–ɎɎšɥ„Ɏšɥ Ɏ”Ɏšɥ‡Ɏšɥˆ
ɎšɨɥɎšɨɨɎšɨɩɎšɨɪɎšɨɫɎšɨɬɎšɨɭɎšɨɮɎšɨɯɎšɨɰɎšɨƒɎšɨ„Ɏšɨ Ɏšɨ†Ɏšɨ‡Ɏšɨˆ
ŠɑɤɛʩĺɎɐſƀƋʫřŞŜŵ
ɥɨɩɪɫɬɭɮɯɰśŚʳʰʴţ
ɒ 
ƃɎɎƄɋɏ
ļƒ„ †‡ˆ‰Š‹ŒŽ‘
’“”•–—˜™š›œƇŶƈɌɎšɮˆ
ɎšɯɥɎšɯɨɎšɯɩɎšɯɪɎšɯɫɎšɯɬɎšɯɭɎšɯɮɎšɯɯɎšɯɰɎšɯƒɎšɯ„Ɏšɯ Ɏšɯ†Ɏšɯ‡Ɏšɯˆ
ɎšɰɥɎšɰɨɎšɰɩɎšɰɪɎšɰɫɎšɰɬɎšɰɭɎšɰɮɎšɰɯɎšɰɰɎšɰƒɎšɰ„Ɏšɰ Ɏšɰ†Ɏšɰ‡Ɏšɰˆ
ɎšƒɥɎšƒɨɎšƒɩɎšƒɪɎšƒɫɎšƒɬɎšƒɭɎšƒɮɎšƒɯɎšƒɰɎšƒƒɎšƒ„Ɏšƒ Ɏšƒ†Ɏšƒ‡Ɏšƒˆ
Ɏš„ɥɎš„ɨɎš„ɩɎš„ɪɎš„ɫɎš„ɬɎš„ɭɎš„ɮɎš„ɯɎš„ɰɎš„ƒɎš„„Ɏš„ Ɏš„†Ɏš„‡Ɏš„ˆ
Ɏš ɥɎš ɨɎš ɩɎš ɪɎš ɫɎš ɬɎš ɭɎš ɮɎš ɯɎš ɰɎš ƒɎš „Ɏš Ɏš †Ɏš ‡Ɏš ˆ
Ɏš†ɥɎš†ɨɎš†ɩɎš†ɪɎš†ɫɎš†ɬɎš†ɭɎš†ɮɎš†ɯɎš†ɰɎš†ƒɎš†„Ɏš† Ɏš††Ɏš†‡Ɏš†ˆ
Ɏš‡ɥɎš‡ɨɎš‡ɩɎš‡ɪɎš‡ɫɎš‡ɬɎš‡ɭɎš‡ɮɎš‡ɯɎš‡ɰɎš‡ƒɎš‡„Ɏš‡ Ɏš‡†Ɏš‡‡Ɏš‡ˆ
ɎšˆɥɎšˆɨɎšˆɩɎšˆɪɎšˆɫɎšˆɬɎšˆɭɎšˆɮɎšˆɯɎšˆɰɎšˆƒɎšˆ„Ɏšˆ Ɏšˆ†Ɏšˆ‡Ɏšˆˆɐ

Это может показаться запутанным, поскольку перед нами байты (небольшие


целые числа), а не символы.

ǷȘȍȖȉȘȈȏțȍȔȉȐȕȈȘȕȣȍȌȈȕȕȣȍ
șȗȖȔȖȡȤȦȔȖȌțȓȧVWUXFW
Как вы уже могли убедиться, Python имеет множество инструментов для манипули-
рования текстом. Инструментов для работы с бинарными данными гораздо меньше.
Стандартная библиотека содержит модуль •–”— –, который обрабатывает данные,
аналогичные структурам в С или С++. С помощью этого модуля можно преобра-
зовать бинарные данные в структуры данных Python и наоборот.
Посмотрим, как он работает с данными из файла с расширением PNG (рас-
пространенным форматом изображений, использующимся наряду с GIF и JPEG).
Напишем небольшую программу, которая извлекает ширину и высоту изображения
из фрагмента данных PNG.
Мы будем использовать логотип издательства O’Reilly — изображение малень-
кого долгопята с глазками-бусинами (рис. 12.1).
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Файл этого изображения с расширением PNG доступен


в «Википедии» (KWWSVXSORDGZLNLPHGLDRUJZLNLSHGLDHQ2 5HLOO\B
ORJRSQJ). Мы не будем рассматривать чтение файлов вплоть до
главы 14, поэтому я загрузил этот файл, написал небольшую
программу для вывода его значений в байтах и просто распе-
чатал значения первых 30 байт как значения переменной типа
bytes с именем †ƒ–ƒ для примера, размещенного ниже. (Специ-
фикация формата PNG предполагает, что ширина и высота ǸȐșǬȖȓȋȖȗȧȚ
ȖȚȐȏȌȈȚȍȓȤșȚȊȈ
хранятся в первых 24 байтах, поэтому больше данных нам пока
2¶5HLOO\
и не нужно.)
ʴʴʴ‹’‘”–•–”— –
ʴʴʴ˜ƒŽ‹†ɏ’‰ɏЇƒ†‡”ʰ„ɐɎšɯɰ Ɏ”ɎɎšɨƒɎɐ
ʴʴʴ†ƒ–ƒʰ„ɐɎšɯɰ Ɏ”ɎɎšɨƒɎɎšɥɥɎšɥɥɎšɥɥɎ” ɐʫɎ
ŜŜŜ„ɐɎšɥɥɎšɥɥɎšɥɥɎšɰƒɎšɥɥɎšɥɥɎšɥɥɎšɯ†ɎšɥɯɎšɥɩɎšɥɥɎšɥɥɎšɥɥɎš ɥɐ
ʴʴʴ‹ˆ†ƒ–ƒƃśɯƄʰʰ˜ƒŽ‹†ɏ’‰ɏЇƒ†‡”ś
ŜŜŜ™‹†–ŠřЇ‹‰Š–ʰ•–”— –Ŝ—’ƒ ſɐʴɐř†ƒ–ƒƃɨɭśɩɫƄƀ
ŜŜŜ’”‹–ſɐƒŽ‹† ř™‹†–Šɐř™‹†–ŠřɐЇ‹‰Š–ɐřЇ‹‰Š–ƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɐ‘–ƒ˜ƒŽ‹† ɐƀ
ŜŜŜ
ƒŽ‹† ř™‹†–ŠɨɬɫЇ‹‰Š–ɨɫɨ

Этот код делает следующее:


‰переменная †ƒ–ƒ содержит первые 30 байт файла PNG. Для того чтобы раз-
местить ее на странице, я объединил две байтовые строки с помощью операто-
ров ʫ и Ɏ;
‰переменная ˜ƒŽ‹†ɏ’‰ɏЇƒ†‡” содержит восьмибайтную последовательность,
которая обозначает начало корректного PNG-файла;
‰значение переменной ™‹†–Š извлекается из байтов 16–19, а переменной height —
из байтов 20–23.
ʴ — это строка формата, которая указывает функции —’ƒ ſƀ, как интерпре-
тировать входные последовательности байтов и преобразовывать их в типы данных
Python. Рассмотрим ее детальнее:
‰символ ʴ означает, что целые числа хранятся в формате big-endian (прямой по-
рядок байтов);
‰каждый символ  определяет четырехбайтное целое число типа unsigned long.
Вы можете проверить значение каждого четырехбайтного набора напрямую:
ʴʴʴ†ƒ–ƒƃɨɭśɩɥƄ
„ɐɎšɥɥɎšɥɥɎšɥɥɎšɰƒɐ
ʴʴʴ†ƒ–ƒƃɩɥśɩɫƄɥšɰƒ
„ɐɎšɥɥɎšɥɥɎšɥɥɎšɯ†ɐ

У целых чисел с прямым порядком байтов (big-endian) главный байт рас-


полагается слева. Поскольку значения ширины и длины меньше 255, они умеща-
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

ются в последний байт каждой последовательности. Вы можете убедиться в том,


что эти шестнадцатеричные значения соответствуют ожидаемым десятичным
значениям:
ʴʴʴɥšɰƒ
ɨɬɫ
ʴʴʴɥšɯ†
ɨɫɨ

Если вы хотите произвести противоположное действие, то есть преобразовать


данные Python в байты, используйте функцию ’ƒ ſƀ модуля •–”— –:
ʴʴʴ‹’‘”–•–”— –
ʴʴʴ•–”— –Ŝ’ƒ ſɐʴɐřɨɬɫƀ
„ɐɎšɥɥɎšɥɥɎšɥɥɎšɰƒɐ
ʴʴʴ•–”— –Ŝ’ƒ ſɐʴɐřɨɫɨƀ
„ɐɎšɥɥɎšɥɥɎšɥɥɎšɯ†ɐ

В табл. 12.4 и 12.5 показаны спецификаторы формата для функций ’ƒ ſƀ


и —’ƒ ſƀ.
Спецификаторы порядка байтов (endian) располагаются первыми в строке
формата.
ǺȈȉȓȐȞȈǹȗȍȞȐȜȐȒȈȚȖȘȣȗȖȘȧȌȒȈȉȈȑȚȖȊ

ǹȗȍȞȐȜȐȒȈȚȖȘ ǷȖȘȧȌȖȒȉȈȑȚȖȊ
< Обратный порядок (Little endian)
> Прямой порядок (Big endian)

ǺȈȉȓȐȞȈǹȗȍȞȐȜȐȒȈȚȖȘȣȜȖȘȔȈȚȈ

ǹȗȍȞȐȜȐȒȈȚȖȘ ǶȗȐșȈȕȐȍ DzȖȓȐȟȍșȚȊȖȉȈȑȚȖȊ


x Пропустить байт 1
b Знаковый байт 1
B Беззнаковый байт 1
h Знаковое короткое целое число 2
H Беззнаковое короткое целое число 2
i Знаковое целое число 4
I Беззнаковое целое число 4
l Знаковое длинное целое число 4
L Беззнаковое длинное целое число 4
Q Беззнаковое очень длинное целое число 8
f Число с плавающей точкой 4

Продолжение ®
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǺȈȉȓȐȞȈ ȗȘȖȌȖȓȎȍȕȐȍ

ǹȗȍȞȐȜȐȒȈȚȖȘ ǶȗȐșȈȕȐȍ DzȖȓȐȟȍșȚȊȖȉȈȑȚȖȊ


d Число с плавающей точкой двойной точности 8
p Счетчик и символы 1 + количество 1 + количество
s Символы количество

Спецификаторы типа следуют за символом, указывающим порядок байтов.


Любому спецификатору может предшествовать число, указывающее ȞȢȟȜȫșȥȦȖȢ;
запись ɬ аналогична записи .
Вы можете использовать префикс ȞȢȟȜȫșȥȦȖȔ вместо конструкции ʴ:
ʴʴʴ•–”— –Ŝ—’ƒ ſɐʴɩɐř†ƒ–ƒƃɨɭśɩɫƄƀ
ſɨɬɫřɨɫɨƀ

Мы использовали разделение †ƒ–ƒƃɨɭśɩɫƄ, чтобы получить интересующие нас


байты напрямую. А могли бы использовать спецификатор š, чтобы пропустить не-
нужные нам части:
ʴʴʴ•–”— –Ŝ—’ƒ ſɐʴɨɭšɩɭšɐř†ƒ–ƒƀ
ſɨɬɫřɨɫɨƀ

Эта строка означает:


‰использовать формат с прямым порядком байтов (>);
‰пропустить 16 байт (16x);
‰прочитать 8 байт — два беззнаковых длинных целых числа (2L);
‰пропустить последние 6 байт (6x).

ǬȘțȋȐȍȐȕșȚȘțȔȍȕȚȣȌȓȧȘȈȉȖȚȣ
șȉȐȕȈȘȕȣȔȐȌȈȕȕȣȔȐ
Некоторые сторонние пакеты с открытым исходным кодом часто предлагают следу-
ющие более декларативные способы определения и извлечения бинарных данных:
‰bitstring (KWWSELWO\S\ELWVWULQJ);
‰construct (KWWSELWO\S\FRQVWUXFW);
‰hachoir (KWWSVS\SLRUJSURMHFWKDFKRLU);
‰binio (KWWSVSLNDQHWS\ELQLR);
‰Kaitai Struct (KWWSNDLWDLLR).
В приложении Б содержатся инструкции о том, как загрузить и установить такие
внешние пакеты. В следующем примере используем пакет ‘•–”— –. Вот все, что
вам необходимо сделать:
ɛpip install construct
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

Здесь показано, как можно извлечь измерения PNG из нашей строки байтов †ƒ–ƒ
с помощью пакета ‘•–”— –:
ʴʴʴˆ”‘ ‘•–”— –‹’‘”––”— –řƒ‰‹ ř –ɪɩř‘•–ř–”‹‰
ʴʴʴɤȔȘȔȣȦȜȤȢȖȔȡȢȜțȞȢȘȔȣȢȔȘȤșȥȧŠ––’•śŵŵ‰‹–Š—„Ŝ ‘ŵ ‘•–”— –
ʴʴʴˆ–ʰ–”— –ſɐ’‰ɐř
ŜŜŜƒ‰‹ ſ„ɐɎšɯɰ Ɏ”ɎɎšɨƒɎɐƀř
ŜŜŜ –ɪɩſɐއ‰–Šɐƀř
ŜŜŜ‘•–ſ–”‹‰ſɐ–›’‡ɐřɫƀř„ɐ ɐƀř
ŜŜŜ –ɪɩſɐ™‹†–Šɐƀř
ŜŜŜ –ɪɩſɐЇ‹‰Š–ɐƀ
ŜŜŜƀ
ʴʴʴ†ƒ–ƒʰ„ɐɎšɯɰ Ɏ”ɎɎšɨƒɎɎšɥɥɎšɥɥɎšɥɥɎ” ɐʫɎ
ŜŜŜ„ɐɎšɥɥɎšɥɥɎšɥɥɎšɰƒɎšɥɥɎšɥɥɎšɥɥɎšɯ†ɎšɥɯɎšɥɩɎšɥɥɎšɥɥɎšɥɥɎš ɥɐ
ʴʴʴ”‡•—Ž–ʰˆ–Ŝ’ƒ”•‡ſ†ƒ–ƒƀ
ʴʴʴ’”‹–ſ”‡•—Ž–ƀ
‘–ƒ‹‡”ś
އ‰–Šʰɨɪ
–›’‡ʰ„ɐ ɐ
™‹†–Šʰɨɬɫ
Ї‹‰Š–ʰɨɫɨ
ʴʴʴ’”‹–ſ”‡•—Ž–Ŝ™‹†–Šř”‡•—Ž–ŜЇ‹‰Š–ƀ
ɨɬɫřɨɫɨ

ǷȘȍȖȉȘȈȏțȍȔȉȈȑȚȣșȚȘȖȒȐșȗȖȔȖȡȤȦȔȖȌțȓȧELQDVFLL
Стандартный модуль „‹ƒ• ‹‹ содержит функции, которые позволяют вам кон-
вертировать данные в бинарный вид и в различные представления строк: шест-
надцатеричное (с основанием 16), с основанием 64, uuencoded и др. Например,
в следующем фрагменте мы выведем на экран восьмибайтный заголовок PNG как
последовательность шестнадцатеричных значений вместо комбинации символов
ASCII и escape-последовательностей вида Ɏš šš, которые Python использует для
отображения байтовых переменных:
ʴʴʴ‹’‘”–„‹ƒ• ‹‹
ʴʴʴ˜ƒŽ‹†ɏ’‰ɏЇƒ†‡”ʰ„ɐɎšɯɰ Ɏ”ɎɎšɨƒɎɐ
ʴʴʴ’”‹–ſ„‹ƒ• ‹‹ŜŠ‡šŽ‹ˆ›ſ˜ƒŽ‹†ɏ’‰ɏЇƒ†‡”ƀƀ
„ɐɯɰɬɥɫ‡ɫɮɥ†ɥƒɨƒɥƒɐ

В обратном направлении это тоже работает:


ʴʴʴ’”‹–ſ„‹ƒ• ‹‹Ŝ—Š‡šŽ‹ˆ›ſ„ɐɯɰɬɥɫ‡ɫɮɥ†ɥƒɨƒɥƒɐƀƀ
„ɐɎšɯɰ Ɏ”ɎɎšɨƒɎɐ

ǩȐȚȖȊȣȍȖȗȍȘȈȚȖȘȣ
Python предоставляет целочисленные операторы на уровне битов, аналогичные тем,
что имеются в языке С. В табл. 12.6 собраны все операторы вместе с примерами для
целочисленных переменных a (в десятичной системе счисления ɬ, в двоичной —
ɥ„ɥɨɥɨ) и b (в десятичной системе счисления ɨ, в двоичной — ɥ„ɥɥɥɨ).
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǺȈȉȓȐȞȈǾȍȓȖȟȐșȓȍȕȕȣȍȖȗȍȘȈȞȐȐȌȓȧțȘȖȊȕȧȉȐȚȖȊ

ǶȗȍȘȈȚȖȘ ǶȗȐșȈȕȐȍ ǷȘȐȔȍȘ ǬȍșȧȚȐȟȕȣȑ ǬȊȖȐȟȕȣȑȘȍȏțȓȤȚȈȚ


ȘȍȏțȓȤȚȈȚ
& Логическое И a&b 1 0b0001
| Логическое ИЛИ a|b 5 0b0101
^ Исключающее ИЛИ a ^ b 4 0b0100
~ Инверсия битов ~a –6 Двоичное представление
зависит от размера типа int
<< Сдвиг влево a << 1 10 0b1010
>> Сдвиг вправо a >> 1 2 0b0010

Эти операторы похожи на операторы для работы с множествами, показанные


в главе 8. Оператор ĺ возвращает биты, одинаковые в обоих аргументах, а опера-
тор Ŷ возвращает биты, которые установлены в обоих аргументах. Оператор ɋ воз-
вращает биты, установленные в одном или в другом аргументе, но не в них обоих.
Оператор Ɍ инвертирует порядок байтов в одном аргументе и также изменяет
знак, поскольку старший бит целого числа указывает на его знак (1 означает
«минус») в арифметике дополнительных кодов, которая используется во всех
современных компьютерах. Операторы ʳʳ и ʴʴ просто смещают биты влево или
вправо. Сдвиг влево на один бит аналогичен умножению на 2, а сдвиг вправо —
делению на 2.

ǨȕȈȓȖȋȐȧșȦȊȍȓȐȘȕȣȔȐȐȏȌȍȓȐȧȔȐ
Строки Unicode похожи на браслет с брелоками, а байты — на нитки с бусинами.

ǿȐȚȈȑȚȍȌȈȓȍȍ
Далее следует еще одна практическая глава — в ней показывается, как работать
с датой и временем.

ǻȗȘȈȎȕȍȕȐȧ
12.1. Создайте строку Unicode с именем ›•–‡”› и присвойте ей значение ɐɎɥɥɥɨˆɫƒɰɐ.
Выведите на экран значение строки ›•–‡”›. Выведите на экран значение пере-
менной ›•–‡”› и ее имя Unicode.
12.2. Закодируйте строку ›•–‡”›, на этот раз с использованием кодировки UTF-8,
в переменную типа bytes с именем ’‘’ɏ„›–‡•. Выведите на экран значение
переменной ’‘’ɏ„›–‡•.
ǫȓȈȊȈǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ  

12.3. Используя кодировку UTF-8, декодируйте переменную ’‘’ɏ„›–‡• в строку


’‘’ɏ•–”‹‰. Выведите на экран значение переменной ’‘’ɏ•–”‹‰. Равно ли оно
значению переменной ›•–‡”›?
12.4. При работе с текстом могут пригодиться регулярные выражения. В следую-
щем примере (пример 12.1) мы воспользуемся ими несколькими способами.
Перед вами стихотворение Ode on the Mammoth Cheese, написанное Джеймсом
Макинтайром в 1866 году во славу головки сыра весом 7000 фунтов, которая
была изготовлена в Онтарио и отправлена в международное путешествие. Если
не хотите самостоятельно перепечатывать это стихотворение, используйте
свой любимый поисковик и скопируйте текст в программу. Или скопируйте
стихотворение из проекта «Гутенберг» (KWWSELWO\PFLQW\UHSRHWU\). Назовите
следующую строку ƒ‘–Š:
ǷȘȐȔȍȘPDPPRWKW[W
‡Šƒ˜‡•‡‡–Ї‡ř“—‡‡‘ˆ Ї‡•‡ř
›‹‰“—‹‡–Ž›ƒ–›‘—”‡ƒ•‡ř
‡–Ž›ˆƒ‡†„›‡˜‡‹‰„”‡‡œ‡ř
Š›ˆƒ‹”ˆ‘”‘ˆŽ‹‡•†ƒ”‡•‡‹œ‡Ŝ

ŽŽ‰ƒ‹Ž›†”‡••‡†•‘‘›‘—ɐŽŽ‰‘
‘–Ї‰”‡ƒ–”‘˜‹ ‹ƒŽ•Š‘™ř
‘„‡ƒ†‹”‡†„›ƒ›ƒ„‡ƒ—
–Ї ‹–›‘ˆ‘”‘–‘Ŝ

‘™•—‡”‘—•ƒ•ƒ•™ƒ”‘ˆ„‡‡•ř
”ƒ•–Їއƒ˜‡•—’‘–Ї–”‡‡•ř
–†‹†”‡“—‹”‡–‘ƒ‡–Ї‡’އƒ•‡ř
†•–ƒ†—”‹˜ƒŽŽ‡†ř“—‡‡‘ˆ Ї‡•‡Ŝ

ƒ››‘—‘–”‡ ‡‹˜‡ƒ• ƒ”ƒ•


‡Šƒ˜‡Їƒ”†–Šƒ–”Ŝ ƒ””‹•
–‡†•–‘•‡†›‘—‘ˆˆƒ•ˆƒ”ƒ•
Ї‰”‡ƒ–™‘”ކɐ••Š‘™ƒ–ƒ”‹•Ŝ

ˆ–Ї›‘—–Š„‡™ƒ”‡‘ˆ–Ї•‡ř
‘”•‘‡‘ˆ–Ї‹‰Š–”—†‡Ž›•“—‡‡œ‡
†„‹–‡›‘—” Ї‡ř–Ї•‘‰•‘”‰Ž‡‡•
‡ ‘—ކ‘–•‹‰ř‘ŠŠ“—‡‡‘ˆ Ї‡•‡Ŝ

‡ɐ”––Š‘—•—•’‡†‡†ˆ”‘„ƒŽŽ‘‘ř
‘—ɐ† ƒ•–ƒ•Šƒ†‡‡˜‡ƒ–‘‘ř
‘Ž•™‘—ކ–Š‹‹–™ƒ•–Ї‘‘
„‘—––‘ˆƒŽŽƒ† ”—•Š–Ї•‘‘Ŝ

12.5. Импортируйте модуль re, чтобы использовать функции регулярных выраже-


ний в Python. Примените функцию ”‡Ŝˆ‹†ƒŽŽſƀ для вывода на экран всех
слов, начинающихся с буквы ȥ.
12.6. Найдите все четырехбуквенные слова, которые начинаются с буквы .
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

12.7. Найдите все слова, которые заканчиваются на букву r.


12.8. Найдите все слова, которые содержат три гласные подряд.
12.9. Используйте метод —Š‡šŽ‹ˆ› для того, чтобы преобразовать шестнадцате-
ричную строку, созданную путем объединения двух строк для размещения на
странице, в переменную типа bytes с именем gif:
ɐɫɮɫɰɫɭɪɯɪɰɭɨɥɨɥɥɥɨɥɥɯɥɥɥɥɥɥɥɥɥɥɥˆˆˆˆˆˆɩɨˆɰɐʫ
ɐɥɫɥɨɥɥɥɥɥɥɥɥɩ ɥɥɥɥɥɥɥɥɥɨɥɥɥɨɥɥɥɥɥɩɥɨɫɫɥɥɪ„ɐ

12.10. Байты, содержащиеся в переменной gif, определяют однопиксельный про-


зрачный GIF-файл. Этот формат является одним из самых распространенных.
Корректный файл формата GIF начинается со строки ɯɰƒ. Корректен ли
этот файл?
12.11. Ширина GIF-файла в пикселах является шестнадцатибитным целым числом
с обратным порядком байтов, которое начинается со смещения 6 байт. Высота
имеет такой же размер и начинается со смещения 8 байт. Извлеките и выведите
на экран эти значения для переменной gif. Равны ли они ɨ?
ƋƓƈƊƈ
DzȈȓȍȕȌȈȘȐȐȟȈșȣ

«Раз!» — ударили часы на колокольной башне,


Те, что шестьдесят минут назад
Пробили полночь.

Фредерик Б. Нидхэм. The Round of the Clock

Хоть я и снялась для календаря, я никогда


не приходила вовремя.

Мэрилин Монро

Программисты прилагают удивительное количество усилий, работая с датами и вре-


менем. Поговорим о проблемах, с которыми постоянно приходится сталкиваться,
а затем рассмотрим лучшие приемы для их решения.
Даты можно представить по-разному — способов не просто много, а слишком
много. Даже англоговорящие люди, использующие римский календарь, имеют мно-
жество вариантов для написания простой даты:
‰July 21 1987;
‰21 Jul 1987;
‰21/7/1987;
‰7/21/1987.
Наряду с другими проблемами, представление даты может быть двусмысленным.
В приведенных примерах довольно легко понять, что 7 означает месяц, а 21 — день
месяца, хотя бы потому, что у месяца не может быть номера 21. Но что насчет даты
1/6/2012? Мы говорим о 6 января или о 1 июня?
Название месяца в римском календаре изменяется в зависимости от языка. Даже
год и месяц могут иметь разные определения в разных культурах.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Время также способно доставить неприятности, особенно из-за часовых поя-


сов и переходов на летнее время. Если вы взглянете на карту часовых поясов, то
окажется, что эти пояса больше соответствуют политическим и историческим
границам, а не сменяются каждые 15° (360°/24) долготы. Кроме того, разные
страны переходят на летнее время и обратно в разные дни года. Страны Южного
полушария переводят свои часы вперед, когда страны Северного полушария пере-
водят их назад, и наоборот (если вы немного подумаете, то поймете, почему так
происходит).
Стандартная библиотека Python имеет множество модулей для работы с датой
и временем: †ƒ–‡–‹‡, –‹‡, ƒŽ‡†ƒ”, †ƒ–‡—–‹Ž и др. Их функции немного пересека-
ются друг с другом, что иногда приводит к путанице.

ǪȐșȖȒȖșȕȣȑȋȖȌ
Високосные годы — еще одна проблема. Наверняка вы знаете, что каждый четвер-
тый год — високосный (в такие годы проходят летние Олимпийские игры и выборы
президента в США). Но знаете ли вы, что каждый сотый год не является високос-
ным, а каждый 400-й — является? Рассмотрим пример кода, в котором проверяется,
високосный год или нет:
ʴʴʴ‹’‘”– ƒŽ‡†ƒ”
ʴʴʴ ƒŽ‡†ƒ”Ŝ‹•އƒ’ſɨɰɥɥƀ
ƒŽ•‡
ʴʴʴ ƒŽ‡†ƒ”Ŝ‹•އƒ’ſɨɰɰɭƀ
”—‡
ʴʴʴ ƒŽ‡†ƒ”Ŝ‹•އƒ’ſɨɰɰɰƀ
ƒŽ•‡
ʴʴʴ ƒŽ‡†ƒ”Ŝ‹•އƒ’ſɩɥɥɥƀ
”—‡
ʴʴʴ ƒŽ‡†ƒ”Ŝ‹•އƒ’ſɩɥɥɩƀ
ƒŽ•‡
ʴʴʴ ƒŽ‡†ƒ”Ŝ‹•އƒ’ſɩɥɥɫƀ
”—‡

Справка для любопытных:


‰год состоит из 365,242 196 дня (после одного оборота вокруг Солнца Земля на
четверть оборота вокруг своей оси отстает от места, где начинала движение);
‰каждые четыре года добавляется один день. Теперь в среднем каждый год состоит
из 365,242 196 – 0,25 = 364,992 196 дня;
‰каждые 100 лет один день вычитается. Теперь средний год состоит из 364,992 196 +
+ 0,01 = 365,002 196 дня;
‰каждые 400 лет добавляется один день. Теперь средний год состоит из 365,002 196 –
– 0,0025 = 364,999 696 дня.
Получилось достаточно точно! О високосных секундах мы говорить не будем
(KWWSVDOH[ZOFKDQQHWIDOVHKRRGVSURJUDPPHUVEHOLHYHDERXWXQL[WLPH).
ǫȓȈȊȈDzȈȓȍȕȌȈȘȐȐȟȈșȣ  

ǴȖȌțȓȤGDWHWLPH
Модуль стандартной библиотеки †ƒ–‡–‹‡ позволяет работать с датами и време-
нем (что вполне ожидаемо). В нем определены четыре основных класса объектов,
и в каждом содержится множество методов:
‰†ƒ–‡ — для годов, месяцев и дней;
‰–‹‡ — для часов, минут, секунд и долей секунды;
‰†ƒ–‡–‹‡ — для даты и времени одновременно;
‰–‹‡†‡Ž–ƒ — для интервалов даты и/или времени.
Вы можете создать объект †ƒ–‡, указав год, месяц и день. Эти значения будут
доступны как атрибуты:
ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡
ʴʴʴŠƒŽŽ‘™‡‡ʰ†ƒ–‡ſɩɥɨɰřɨɥřɪɨƀ
ʴʴʴŠƒŽŽ‘™‡‡
†ƒ–‡–‹‡Ŝ†ƒ–‡ſɩɥɨɰřɨɥřɪɨƀ
ʴʴʴŠƒŽŽ‘™‡‡Ŝ†ƒ›
ɪɨ
ʴʴʴŠƒŽŽ‘™‡‡Ŝ‘–Š
ɨɥ
ʴʴʴŠƒŽŽ‘™‡‡Ŝ›‡ƒ”
ɩɥɨɰ

Вы можете вывести на экран содержимое объекта †ƒ–‡ с помощью его метода


‹•‘ˆ‘”ƒ–ſƀ:
ʴʴʴŠƒŽŽ‘™‡‡Ŝ‹•‘ˆ‘”ƒ–ſƀ
ɐɩɥɨɰŞɨɥŞɪɨɐ

iso в данном контексте ссылается на ISO 8601 — международный стандарт для


представления даты и времени. Согласно этому стандарту мы начинаем записывать
дату с самого общего элемента (год), а заканчиваем самым точным (день). Вслед-
ствие чего есть возможность корректно отсортировать даты: сначала по году, затем
по месяцу и по дню. Я обычно выбираю этот формат для представления данных
в программах и для имен файлов, которые сохраняют данные по дате. В следующем
разделе будут показаны более сложные методы •–”’–‹‡ſƀ и •–”ˆ–‹‡ſƀ для анализа
и форматирования дат.
В этом примере используется метод –‘†ƒ›ſƀ для генерации сегодняшней даты:
ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡
ʴʴʴ‘™ʰ†ƒ–‡Ŝ–‘†ƒ›ſƀ
ʴʴʴ‘™
†ƒ–‡–‹‡Ŝ†ƒ–‡ſɩɥɨɰřɫřɬƀ

В следующем примере объект –‹‡†‡Ž–ƒ используется для того, чтобы добавить


к объекту †ƒ–‡ некоторый временной интервал:
ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”––‹‡†‡Ž–ƒ
ʴʴʴ‘‡ɏ†ƒ›ʰ–‹‡†‡Ž–ƒſ†ƒ›•ʰɨƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ʴʴʴ–‘‘””‘™ʰ‘™ʫ‘‡ɏ†ƒ›
ʴʴʴ–‘‘””‘™
†ƒ–‡–‹‡Ŝ†ƒ–‡ſɩɥɨɰřɫřɭƀ
ʴʴʴ‘™ʫɨɮƋ‘‡ɏ†ƒ›
†ƒ–‡–‹‡Ŝ†ƒ–‡ſɩɥɨɰřɫřɩɩƀ
ʴʴʴ›‡•–‡”†ƒ›ʰ‘™Ź‘‡ɏ†ƒ›
ʴʴʴ›‡•–‡”†ƒ›
†ƒ–‡–‹‡Ŝ†ƒ–‡ſɩɥɨɰřɫřɫƀ
Объект †ƒ–‡ может иметь значение в диапазоне, начинающемся с †ƒ–‡Ŝ‹
ſ›‡ƒ”ʰɨř ‘–Šʰɨř †ƒ›ʰɨƀ и заканчивающемся †ƒ–‡Ŝƒš ſ›‡ƒ”ʰɰɰɰɰř ‘–Šʰɨɩř
†ƒ›ʰɪɨƀ. Таким образом, этот метод неприменим для исторических или астрономи-
ческих расчетов.
Объект –‹‡ модуля †ƒ–‡–‹‡ применяется для представления времени дня:
ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”––‹‡
ʴʴʴ‘‘ʰ–‹‡ſɨɩřɥřɥƀ
ʴʴʴ‘‘
†ƒ–‡–‹‡Ŝ–‹‡ſɨɩřɥƀ
ʴʴʴ‘‘ŜŠ‘—”
ɨɩ
ʴʴʴ‘‘Ŝ‹—–‡
ɥ
ʴʴʴ‘‘Ŝ•‡ ‘†
ɥ
ʴʴʴ‘‘Ŝ‹ ”‘•‡ ‘†
ɥ
Порядок аргументов таков: от самой крупной единицы времени (часа) до самой
мелкой (микросекунды). Если вы передадите не все аргументы, объект –‹‡ предполо-
жит, что остальные имеют значение ɥ. Кстати, то, что вы можете сохранять и получать
микросекунды, не означает, что вы можете извлекать время из вашего компьютера
с точностью до микросекунды. Высокая точность измерений зависит от многих фак-
торов, присущих аппаратному обеспечению и операционной системе.
Объект †ƒ–‡–‹‡ содержит дату и время дня. Вы можете создать такой объект на-
прямую, как показано в примере: 2 января, 2014, 3:04 утра, плюс 5 секунд и 6 микро-
секунд:
ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
ʴʴʴ•‘‡ɏ†ƒ›ʰ†ƒ–‡–‹‡ſɩɥɨɰřɨřɩřɪřɫřɬřɭƀ
ʴʴʴ•‘‡ɏ†ƒ›
†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ſɩɥɨɰřɨřɩřɪřɫřɬřɭƀ
Объект †ƒ–‡–‹‡ также имеет метод ‹•‘ˆ‘”ƒ–ſƀ:
ʴʴʴ•‘‡ɏ†ƒ›Ŝ‹•‘ˆ‘”ƒ–ſƀ
ɐɩɥɨɰŞɥɨŞɥɩɥɪśɥɫśɥɬŜɥɥɥɥɥɭɐ
Буква , которая находится в середине, разделяет дату и время.
Объект †ƒ–‡–‹‡ имеет метод ‘™ſƀ, с помощью которого можно получить теку-
щие дату и время:
ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
ʴʴʴ‘™ʰ†ƒ–‡–‹‡Ŝ‘™ſƀ
ʴʴʴ‘™
ǫȓȈȊȈDzȈȓȍȕȌȈȘȐȐȟȈșȣ  

†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ſɩɥɨɰřɫřɬřɨɰřɬɪřɮřɬɯɥɬɭɩƀ
ʴʴʴ‘™Ŝ›‡ƒ”
ɩɥɨɰ
ʴʴʴ‘™Ŝ‘–Š
ɫ
ʴʴʴ‘™Ŝ†ƒ›
ɬ
ʴʴʴ‘™ŜŠ‘—”
ɨɰ
ʴʴʴ‘™Ŝ‹—–‡
ɬɪ
ʴʴʴ‘™Ŝ•‡ ‘†
7
ʴʴʴ‘™Ŝ‹ ”‘•‡ ‘†
ɬɯɥɬɭɩ
Объединить объекты †ƒ–‡ и –‹‡ в объект †ƒ–‡–‹‡ можно с помощью метода
‘„‹‡ſƀ:
ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡ř–‹‡ř†ƒ–‡
ʴʴʴ‘‘ʰ–‹‡ſɨɩƀ
ʴʴʴ–Š‹•ɏ†ƒ›ʰ†ƒ–‡Ŝ–‘†ƒ›ſƀ
ʴʴʴ‘‘ɏ–‘†ƒ›ʰ†ƒ–‡–‹‡Ŝ ‘„‹‡ſ–Š‹•ɏ†ƒ›ř‘‘ƀ
ʴʴʴ‘‘ɏ–‘†ƒ›
†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ſɩɥɨɰřɫřɬřɨɩřɥƀ
Получить объекты †ƒ–‡ и –‹‡ из объекта †ƒ–‡–‹‡ можно с помощью методов
†ƒ–‡ſƀ и –‹‡ſƀ:
ʴʴʴ‘‘ɏ–‘†ƒ›Ŝ†ƒ–‡ſƀ
†ƒ–‡–‹‡Ŝ†ƒ–‡ſɩɥɨɰřɫřɬƀ
ʴʴʴ‘‘ɏ–‘†ƒ›Ŝ–‹‡ſƀ
†ƒ–‡–‹‡Ŝ–‹‡ſɨɩřɥƀ

ǴȖȌțȓȤWLPH
В Python есть модуль †ƒ–‡–‹‡ с объектом –‹‡, но есть и отдельный модуль –‹‡.
Более того, в модуле –‹‡ имеется функция с каким бы вы думали именем? Правиль-
но, –‹‡ſƀ.
Одним из способов представления абсолютного времени является подсчет ко-
личества секунд, прошедших с определенной начальной точки. В Unix считают
количество секунд, прошедших с полуночи 1 января 1970 года1: это значение часто
называют epoch. Как правило, данный способ самый простой для обмена датой
и временем между системами.
Функция –‹‡ſƀ модуля –‹‡ возвращает текущее время как значение ‡’‘ Š:
ʴʴʴ‹’‘”––‹‡
ʴʴʴ‘™ʰ–‹‡Ŝ–‹‡ſƀ
ʴʴʴ‘™
ɨɬɬɫɬɨɩɨɪɩŜɮɮɯɩɪɪ

1
Примерно в это время появилась система Unix, если не обращать внимания на досадные
високосные секунды.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Если выполнить подсчеты, вы увидите, что прошло более миллиарда секунд по-
сле наступления нового, 1970 года. И куда ушло время?
Вы можете преобразовать значение ‡’‘ Š в строку с помощью функции –‹‡ſƀ:
ʴʴʴ–‹‡Ŝ –‹‡ſ‘™ƀ
ɐ ”‹’”ɬɨɰśɬɬśɪɩɩɥɨɰɐ

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


для даты и времени.
Значения ‡’‘ Š полезны для обмена датой и временем с разными системами, на-
пример с JavaScript. Однако иногда бывает нужно получить значения именно дней,
часов и т. д., которые объект –‹‡ предоставляет как объекты •–”— –ɏ–‹‡. Функ-
ция Ž‘ ƒŽ–‹‡ſƀ предоставляет время в вашем текущем часовом поясе, а функция
‰–‹‡ſƀ — в UTC:
ʴʴʴ–‹‡ŜŽ‘ ƒŽ–‹‡ſ‘™ƀ
–‹‡Ŝ•–”— –ɏ–‹‡ſ–ɏ›‡ƒ”ʰɩɥɨɰř–ɏ‘ʰɫř–ɏ†ƒ›ʰɬř–ɏŠ‘—”ʰɨɰř
–ɏ‹ʰɬɬř–ɏ•‡ ʰɪɩř–ɏ™†ƒ›ʰɫř–ɏ›†ƒ›ʰɰɬř–ɏ‹•†•–ʰɨƀ
ʴʴʴ–‹‡Ŝ‰–‹‡ſ‘™ƀ
–‹‡Ŝ•–”— –ɏ–‹‡ſ–ɏ›‡ƒ”ʰɩɥɨɰř–ɏ‘ʰɫř–ɏ†ƒ›ʰɭř–ɏŠ‘—”ʰɥř
–ɏ‹ʰɬɬř–ɏ•‡ ʰɪɩř–ɏ™†ƒ›ʰɬř–ɏ›†ƒ›ʰɰɭř–ɏ‹•†•–ʰɥƀ

В моем (Центральном) часовом поясе 19:55 — это то же самое, что 00:55 следу-
ющего дня в поясе UTC (раньше его называли Гринвичским временем или временем
Зулу). Если вы опустите аргумент в функциях Ž‘ ƒŽ–‹‡ſƀ или ‰–‹‡ſƀ, они пред-
положат, что сконвертировать нужно текущее время.
Некоторые значения –ɏŜŜŜ из структуры •–”— –ɏ–‹‡ выглядят неоднозначно,
поэтому обратитесь к табл. 13.1 для получения более подробной информации.
ǺȈȉȓȐȞȈǯȕȈȟȍȕȐȧșȚȘțȒȚțȘȣVWUXFWBWLPH

ǰȕȌȍȒș ǰȔȧ ǯȕȈȟȍȕȐȍ ǬȐȈȗȈȏȖȕ

0 tm_year Год от 0000 до 9999


1 tm_mon Месяц от 1 до 12
2 tm_mday День месяца от 1 до 31
3 tm_hour Часы от 0 до 23
4 tm_min Минуты от 0 до 59
5 tm_sec Секунды от 0 до 61
6 tm_wday День недели от 0 (понедельник) до 6 (воскресенье)
7 tm_yday День года от 1 до 366
8 tm_isdst Летнее время? 0 = нет, 1 = да, –1 = неизвестно

Если вы не хотите вводить все эти имена, начинающиеся с конструкции –ɏ,


структура •–”— –ɏ–‹‡ также может играть роль именованного кортежа (см. раз-
ǫȓȈȊȈDzȈȓȍȕȌȈȘȐȐȟȈșȣ  

дел «Именованные кортежи» на с. 219). Поэтому можно использовать индексы из


предыдущей таблицы:
ʴʴʴ‹’‘”––‹‡
ʴʴʴ‘™ʰ–‹‡ŜŽ‘ ƒŽ–‹‡ſƀ
ʴʴʴ‘™
–‹‡Ŝ•–”— –ɏ–‹‡ſ–ɏ›‡ƒ”ʰɩɥɨɰř–ɏ‘ʰɭř–ɏ†ƒ›ʰɩɪř–ɏŠ‘—”ʰɨɩř
–ɏ‹ʰɨɩř–ɏ•‡ ʰɩɫř–ɏ™†ƒ›ʰɭř–ɏ›†ƒ›ʰɨɮɫř–ɏ‹•†•–ʰɨƀ
ʴʴʴ‘™ƃɥƄ
ɩɥɨɰ
’”‹–ſŽ‹•–ſ‘™ƃšƄˆ‘”š‹”ƒ‰‡ſɰƀƀƀ
ƃɩɥɨɰřɭřɩɪřɨɩřɨɩřɩɫřɭřɨɮɫřɨƄ

Функция –‹‡ſƀ идет в другом направлении и преобразует объект •–”— –ɏ–‹‡


в секунды ‡’‘ Š:
ʴʴʴ–ʰ–‹‡ŜŽ‘ ƒŽ–‹‡ſ‘™ƀ
ʴʴʴ–‹‡Ŝ–‹‡ſ–ƀ
ɨɬɬɫɬɨɩɨɪɩŜɥ

Результат не совсем похож на предыдущее значение ‡’‘ Š, полученное с по-


мощью функции ‘™ſƀ, поскольку объект •–”— –ɏ–‹‡ сохраняет время только до
секунд.

ǵȍȉȖȓȤȠȖȑ șȖȊȍȚ ȊȍȏȌȍ ȋȌȍ ȊȖȏȔȖȎȕȖ ȐșȗȖȓȤȏțȑȚȍ ȟȈșȖȊȖȑ ȗȖȧș 87& 87& ²
ȥȚȖȈȉșȖȓȦȚȕȖȍȊȘȍȔȧȕȍȏȈȊȐșȧȡȍȍȖȚȟȈșȖȊȣȝȗȖȧșȖȊǭșȓȐțȊȈșȍșȚȤșȍȘȊȍȘ
țșȚȈȕȖȊȐȚȍȍȋȖȊȘȍȔȧȊ87&ȕȍȗȘȐȊȧȏȣȊȈȧșȤȒȔȍșȚȕȖȔțȊȘȍȔȍȕȐ
ǭȡȍ ȖȌȐȕ șȖȊȍȚ ȕȐȒȖȋȌȈ ȕȍ ȐșȗȖȓȤȏțȑȚȍ ȓȍȚȕȍȍ ȊȘȍȔȧ ȍșȓȐ ȔȖȎȕȖ ȉȍȏ ȥȚȖȋȖ
ȖȉȖȑȚȐșȤǭșȓȐȊȣțȟȐȚȣȊȈȍȚȍȗȖȌȖȉȕȣȍȗȍȘȍȝȖȌȣȊȒȈȒȖȑȚȖȔȖȔȍȕȚȟȈșțȊȈș
ȗȘȖȗȈȌȍȚ ȊȍșȕȖȑ ȈȊȌȘțȋȖȑ²ȕȈșȚțȗȐȚȌȊȈȎȌȣ ȖșȍȕȤȦ ǷȖȘȈȏȕȣȔȗȘȐȟȐȕȈȔ
ȔȕȖȋȐȍȖȘȋȈȕȐȏȈȞȐȐȗȖȓȤȏțȦȚșȧȓȍȚȕȐȔȊȘȍȔȍȕȍȔȊșȊȖȐȝȒȖȔȗȤȦȚȍȘȕȣȝșȐșȚȍȔȈȝ
ȈȗȖȚȖȔțȌȐȊȓȧȦȚșȧțȌȊȖȍȕȐȦȐȗȖȚȍȘȍȌȈȕȕȣȝȐȏȏȈȥȚȖȋȖȚȈȐȕșȚȊȍȕȕȖȋȖȟȈșȈ

ǿȐȚȈȍȔȐȏȈȗȐșȣȊȈȍȔȌȈȚțȐȊȘȍȔȧ
Функция •‘ˆ‘”ƒ–ſƀ — это не единственный способ записывать дату и время.
Вы уже видели функцию –‹‡ſƀ в модуле –‹‡, которую можете использовать для
преобразования времени ‡’‘ Š в строку:
ʴʴʴ‹’‘”––‹‡
ʴʴʴ‘™ʰ–‹‡Ŝ–‹‡ſƀ
ʴʴʴ–‹‡Ŝ –‹‡ſ‘™ƀ
ɐ ”‹’”ɬɨɰśɬɯśɩɪɩɥɨɰɐ

Вы также можете преобразовывать дату и время с помощью функции •–”ˆ–‹‡ſƀ.


Она предоставляется как метод в объектах †ƒ–‡–‹‡, †ƒ–‡ и –‹‡ и как функция
в модуле –‹‡. Функция •–”ˆ–‹‡ſƀ использует для вывода информации на экран
спецификаторы формата, которые вы можете увидеть в табл. 13.2.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǺȈȉȓȐȞȈǹȗȍȞȐȜȐȒȈȚȖȘȣȊȣȊȖȌȈȌȓȧVWUIWLPH

ǹȗȍȞȐȜȐȒȈȚȖȘ ǭȌȐȕȐȞȈȌȈȚȣȊȘȍȔȍȕȐ ǬȐȈȗȈȏȖȕ


%Y Год 1900–…
%m Месяц 01–12
%B Название месяца Январь…
%b Сокращение для месяца Янв…
%d День месяца 01–31
%А Название дня Воскресенье…
А Сокращение для дня Вск…
%Н Часы (24 часа) 00–23
%I Часы (12 часов) 01–12
%p AM или PM AM, PM
%M Минуты 00–59
%S Секунды 00–59

Слева к числам добавляется ноль.


Рассмотрим пример работы функции •–”ˆ–‹‡ſƀ , предоставленной модулем
–‹‡. Она преобразует объект •–”— –ɏ–‹‡ в строку. Сначала мы определим строку
формата ˆ–, и потом снова будем ее использовать:
ʴʴʴ‹’‘”––‹‡
ʴʴʴˆ–ʰɑ –ɐ•ʩřʩʩ†řʩřŽ‘ ƒŽ–‹‡ʩ śʩśʩʩ’ɑ
ʴʴʴ–ʰ–‹‡ŜŽ‘ ƒŽ–‹‡ſƀ
ʴʴʴ–
–‹‡Ŝ•–”— –ɏ–‹‡ſ–ɏ›‡ƒ”ʰɩɥɨɰř–ɏ‘ʰɪř–ɏ†ƒ›ʰɨɪř–ɏŠ‘—”ʰɨɬř
–ɏ‹ʰɩɪř–ɏ•‡ ʰɫɭř–ɏ™†ƒ›ʰɩř–ɏ›†ƒ›ʰɮɩř–ɏ‹•†•–ʰɨƀ
ʴʴʴ–‹‡Ŝ•–”ˆ–‹‡ſˆ–ř–ƀ
ɑ –ɐ•‡†‡•†ƒ›řƒ” ŠɨɪřɩɥɨɰřŽ‘ ƒŽ–‹‡ɥɪśɩɪśɫɭɑ

Если мы попробуем сделать это с объектом †ƒ–‡, функция отработает только для
даты. Время будет установлено в полночь:
ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡
ʴʴʴ•‘‡ɏ†ƒ›ʰ†ƒ–‡ſɩɥɨɰřɮřɫƀ
ʴʴʴˆ–ʰɑ –ɐ•ʩʩ†řʩřŽ‘ ƒŽ–‹‡ʩ śʩśʩʩ’ɑ
ʴʴʴ•‘‡ɏ†ƒ›Ŝ•–”ˆ–‹‡ſˆ–ƀ
ɑ –ɐ• ”‹†ƒ›ř —Ž›ɥɫřɩɥɨɰřŽ‘ ƒŽ–‹‡ɨɩśɥɥśɥɥɑ

Для объекта –‹‡ будут преобразованы только части, касающиеся времени:


ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”––‹‡
ʴʴʴ•‘‡ɏ–‹‡ʰ–‹‡ſɨɥřɪɬƀ
ʴʴʴ•‘‡ɏ–‹‡Ŝ•–”ˆ–‹‡ſˆ–ƀ
ɑ –ɐ•‘†ƒ›ř ƒ—ƒ”›ɥɨřɨɰɥɥřŽ‘ ƒŽ–‹‡ɨɥśɪɬśɥɥɑ

Очевидно, вам не нужно использовать те части объекта –‹‡, которые касаются


дней, поскольку они бессмысленны.
ǫȓȈȊȈDzȈȓȍȕȌȈȘȐȐȟȈșȣ  

Чтобы пойти другим путем и преобразовать строку в дату или время, используйте
функцию •–”’–‹‡ſƀ с такой же строкой формата. Эта строка работает не так, как
регулярные выражения, — части строки, не касающиеся формата (без символа ʩ),
должны совпадать точно. Укажем формат ȗȢȘŞȠșȥȳȪŞȘșȡȰ, например ɩɥɨɰŞɥɨŞɩɰ.
Что произойдет, если строка даты, которую вы хотите проанализировать, имеет
пробелы вместо дефисов?
ʴʴʴ‹’‘”––‹‡
ʴʴʴˆ–ʰɑʩŞʩŞʩ†ɑ
ʴʴʴ–‹‡Ŝ•–”’–‹‡ſɑɩɥɨɰɥɨɩɰɑřˆ–ƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑř
Ž‹‡ɨř‹ʳ‘†—އʴ
 ‹Ž‡ɑŵ‹„”ƒ”›ŵ ”ƒ‡™‘”•ŵ›–Š‘Ŝˆ”ƒ‡™‘”ŵ‡”•‹‘•ŵɪŜɪŵŽ‹„ŵ
’›–Š‘ɪŜɪŵɏ•–”’–‹‡Ŝ’›ɑř
Ž‹‡ɫɰɫř‹ɏ•–”’–‹‡ɏ–‹‡
––ʰɏ•–”’–‹‡ſ†ƒ–ƒɏ•–”‹‰řˆ‘”ƒ–ƀƃɥƄ
 ‹Ž‡ɑŵ‹„”ƒ”›ŵ ”ƒ‡™‘”•ŵ›–Š‘Ŝˆ”ƒ‡™‘”ŵ‡”•‹‘•ŵɪŜɪŵŽ‹„ŵ
’›–Š‘ɪŜɪŵɏ•–”’–‹‡Ŝ’›ɑř
Ž‹‡ɪɪɮř‹ɏ•–”’–‹‡ſ†ƒ–ƒɏ•–”‹‰řˆ‘”ƒ–ƀƀ
ƒŽ—‡””‘”ś–‹‡†ƒ–ƒɐɩɥɨɰɥɨɩɰɐ†‘‡•‘–ƒ– Šˆ‘”ƒ–ɐʩŞʩŞʩ†ɐ
Будет ли довольна функция •–”’–‹‡ſƀ, если мы передадим ей несколько дефисов?
ʴʴʴ–‹‡Ŝ•–”’–‹‡ſɑɩɥɨɰŞɥɨŞɩɰɑřˆ–ƀ
–‹‡Ŝ•–”— –ɏ–‹‡ſ–ɏ›‡ƒ”ʰɩɥɨɰř–ɏ‘ʰɨř–ɏ†ƒ›ʰɩɰř–ɏŠ‘—”ʰɥř–ɏ‹ʰɥř
–ɏ•‡ ʰɥř–ɏ™†ƒ›ʰɭř–ɏ›†ƒ›ʰɩɰř–ɏ‹•†•–ʰŞɨƀ
Да.
Даже если строка совпадает с заданным форматом, но одно из значений находит-
ся вне диапазона, будет сгенерировано исключение:
ʴʴʴ–‹‡Ŝ•–”’–‹‡ſɑɩɥɨɰŞɨɪŞɩɰɑřˆ–ƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
 ‹Ž‡ɑŵ‹„”ƒ”›ŵ ”ƒ‡™‘”•ŵ›–Š‘Ŝˆ”ƒ‡™‘”ŵ‡”•‹‘•ŵɪŜɪŵŽ‹„ŵ
’›–Š‘ɪŜɪŵɏ•–”’–‹‡Ŝ’›ɑř
Ž‹‡ɫɰɫř‹ɏ•–”’–‹‡ɏ–‹‡
––ʰɏ•–”’–‹‡ſ†ƒ–ƒɏ•–”‹‰řˆ‘”ƒ–ƀƃɥƄ
 ‹Ž‡ɑŵ‹„”ƒ”›ŵ ”ƒ‡™‘”•ŵ›–Š‘Ŝˆ”ƒ‡™‘”ŵ‡”•‹‘•ŵɪŜɪŵŽ‹„ŵ
’›–Š‘ɪŜɪŵɏ•–”’–‹‡Ŝ’›ɑř
Ž‹‡ɪɪɮř‹ɏ•–”’–‹‡ſ†ƒ–ƒɏ•–”‹‰řˆ‘”ƒ–ƀƀ
ƒŽ—‡””‘”ś–‹‡†ƒ–ƒɐɩɥɨɰŞɨɪŞɩɰɐ†‘‡•‘–ƒ– Šˆ‘”ƒ–ɐʩŞʩŞʩ†ɐ
Имена соответствуют вашей локали — региональному набору настроек операци-
онной системы. Чтобы вывести на экран другие названия месяцев и дней, измените
свою локаль с помощью функции •‡–Ž‘ ƒŽ‡ſƀ: ее первый аргумент — Ž‘ ƒŽ‡Ŝɏ 
для даты и времени, а второй аргумент — это строка, содержащая сокращенное обо-
значение языка и страны. Давайте пригласим на вечеринку в честь Дня Всех Святых
наших иностранных друзей. Выведем на экран дату (месяц, число и день недели)
на английском, французском, немецком, испанском и исландском. (А что? Думаете,
исландцы не любят вечеринки? У них даже есть настоящие эльфы.)
ʴʴʴ‹’‘”–Ž‘ ƒŽ‡
ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ʴʴʴŠƒŽŽ‘™‡‡ʰ†ƒ–‡ſɩɥɨɫřɨɥřɪɨƀ
ʴʴʴˆ‘”Žƒ‰ɏ ‘—–”›‹ƃɐ‡ɏ—•ɐřɐˆ”ɏˆ”ɐřɐ†‡ɏ†‡ɐřɐ‡•ɏ‡•ɐřɐ‹•ɏ‹•ɐřƄś
ŜŜŜŽ‘ ƒŽ‡Ŝ•‡–Ž‘ ƒŽ‡ſŽ‘ ƒŽ‡Ŝɏ řŽƒ‰ɏ ‘—–”›ƀ
ŜŜŜŠƒŽŽ‘™‡‡Ŝ•–”ˆ–‹‡ſɐʩřʩʩ†ɐƀ
ŜŜŜ
ɐ‡ɏ—•ɐ
ɐŠ—”•†ƒ›ř –‘„‡”ɪɨɐ
ɐˆ”ɏˆ”ɐ
ɐ ‡—†‹ř‘ –‘„”‡ɪɨɐ
ɐ†‡ɏ†‡ɐ
ɐ‘‡”•–ƒ‰ř–‘„‡”ɪɨɐ
ɐ‡•ɏ‡•ɐ
ɐŒ—‡˜‡•ř‘ –—„”‡ɪɨɐ
ɐ‹•ɏ‹•ɐ
ɐˆ‹–—†ƒ‰—”ř‘–Ü„‡”ɪɨɐ
ʴʴʴ

Откуда можно взять эти волшебные значения аргумента Žƒ‰ɏ ‘—–”›? Следу-
ющий способ не самый надежный, но вы можете попробовать получить их все сразу
(все несколько сотен):
ʴʴʴ‹’‘”–Ž‘ ƒŽ‡
ʴʴʴƒ‡•ʰŽ‘ ƒŽ‡ŜŽ‘ ƒŽ‡ɏƒŽ‹ƒ•Ŝ‡›•ſƀ

Из переменной ƒ‡• получим только имена локалей, которые, похоже, будут


работать с методом •‡–Ž‘ ƒŽ‡ſƀ: например, те, которые мы использовали в пре-
дыдущем примере, — двухсимвольный код языка (KWWSELWO\LVR), за которым
следуют подчеркивание и двухсимвольный код страны (KWWSVUXZLNLSHGLDRUJZLNL
,62BBDOSKD):
ʴʴʴ‰‘‘†ɏƒ‡•ʰƃƒ‡ˆ‘”ƒ‡‹ƒ‡•‹ˆɎ
އſƒ‡ƀʰʰɬƒ†ƒ‡ƃɩƄʰʰɐɏɐƄ

Как будут выглядеть первые пять из них?


ʴʴʴ‰‘‘†ɏƒ‡•ƃśɬƄ
ƃɐ•”ɏ •ɐřɐ†‡ɏƒ–ɐřɐŽɏŽɐřɐ‡•ɏ‹ɐřɐ•’ɏ›—ɐƄ

Если вы хотите получить все локали для Германии, используйте следующий код:
ʴʴʴ†‡ʰƃƒ‡ˆ‘”ƒ‡‹‰‘‘†ɏƒ‡•‹ˆƒ‡Ŝ•–ƒ”–•™‹–Šſɐ†‡ɐƀƄ
ʴʴʴ†‡
ƃɐ†‡ɏƒ–ɐřɐ†‡ɏ†‡ɐřɐ†‡ɏ Šɐřɐ†‡ɏŽ—ɐřɐ†‡ɏ„‡ɐƄ

ǭșȓȐȊȣȏȈȗțșȚȐȚȍȜțȕȒȞȐȦVHWBORFDOH ȐȗȖȓțȟȐȚȍȖȠȐȉȒțORFDOH(UURUXQVXSSRUWHG
ORFDOHȥȚȖȉțȌȍȚȖȏȕȈȟȈȚȤȟȚȖțșȚȈȕȖȊȒȈȌȈȕȕȖȑȓȖȒȈȓȐȕȍȗȖȌȌȍȘȎȐȊȈȍȚșȧȊȈȠȍȑ
ȖȗȍȘȈȞȐȖȕȕȖȑ șȐșȚȍȔȖȑ ǪȈȔ ȗȖȚȘȍȉțȍȚșȧ ȊȣȧșȕȐȚȤ ȟȚȖ ȕțȎȕȖ ȖȗȍȘȈȞȐȖȕȕȖȑ
șȐșȚȍȔȍ Ȍȓȧ ȌȖȉȈȊȓȍȕȐȧ ȓȖȒȈȓȐ ǶȠȐȉȒȈ ȔȖȎȍȚ ȗȘȖȐȏȖȑȚȐ ȌȈȎȍ Ȋ ȚȖȔ șȓțȟȈȍ
ȍșȓȐ 3\WKRQ ș ȗȖȔȖȡȤȦ ȜțȕȒȞȐȐ ORFDOHORFDOHBDOLDVNH\V  șȖȖȉȡȐȚ ȊȈȔ ȟȚȖ ȥȚȈ
ȓȖȒȈȓȤȝȖȘȖȠȈȧȇȗȖȓțȟȐȓȖȠȐȉȒțȗȘȐȚȍșȚȐȘȖȊȈȕȐȐȕȈPDF26șȐșȗȖȓȤȏȖȊȈȕȐȍȔ
ȓȖȒȈȓȐF\BJE ȊȈȓȓȐȑșȒȐȑǪȍȓȐȒȖȉȘȐȚȈȕȐȧ ȌȈȎȍȕȍșȔȖȚȘȧȕȈȚȖȟȚȖȓȖȒȈȓȤLVBLV
ȐșȓȈȕȌșȒȐȑǰșȓȈȕȌȐȧ ȗȍȘȍȌȥȚȐȔȉȣȓȈȗȘȐȕȧȚȈ
ǫȓȈȊȈDzȈȓȍȕȌȈȘȐȐȟȈșȣ  

ǪșȍȗȘȍȖȉȘȈȏȖȊȈȕȐȧ
На рис. 13.1, взятом из вики Python (KWWSVRUHLOO\&BN), обобщены все стандартные
преобразования времени, которые можно выполнить в Python.

ǸȐșǷȘȍȖȉȘȈȏȖȊȈȕȐȧȌȈȚȣȐȊȘȍȔȍȕȐ

ǨȓȤȚȍȘȕȈȚȐȊȕȣȍȔȖȌțȓȐ
Если вы считаете, что модули стандартной библиотеки только создают путаницу
или в них не хватает какого-то конкретного преобразования, можете использовать
альтернативные модули от сторонних разработчиков. Рассмотрим некоторые из них:
‰arrow (KWWSVDUURZUHDGWKHGRFVLR). Этот модуль содержит множество функций для
работы с датой и временем и имеет простой API;
‰†ƒ–‡—–‹Ž (KWWSODEL[RUJS\WKRQGDWHXWLO). Модуль может проанализировать любой
формат даты и хорошо работает с относительными датами и временем;
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰‹•‘ɯɭɥɨ (KWWSVS\SLS\WKRQRUJS\SLLVR). Этот модуль заполняет пробелы, свя-


занные с работой модулей стандартной библиотеки, когда речь идет о формате
ISO 8601;
‰ˆŽ‡‹‰ (KWWSVJLWKXEFRPDPELWLRQLQFIOHPLQJ). Модуль содержит множество функ-
ций для работы с часовыми поясами;
‰ƒ›ƒ (KWWSVJLWKXEFRPNHQQHWKUHLW]PD\D). Интуитивный интерфейс для дат, времени
и интервалов;
‰†ƒ–‡‹ˆ‡” (KWWSVJLWKXEFRPMHIIUH\VWDUUGDWHLQIHU). Определяет правильные строки
формата на основе строк, содержащих дату и время.

ǿȐȚȈȑȚȍȌȈȓȍȍ
Файлы и каталоги тоже хотят внимания.

ǻȗȘȈȎȕȍȕȐȧ
13.1. Запишите текущие дату и время как строку в текстовый файл –‘†ƒ›Ŝ–š–.
13.2. Прочтите текстовый файл –‘†ƒ›Ŝ–š– и разместите данные в строке –‘†ƒ›ɏ
string.
13.3. Проанализируйте дату из строки –‘†ƒ›ɏ•–”‹‰.
13.4. Создайте объект †ƒ–‡ с датой вашего рождения.
13.5. В какой день недели вы родились?
13.6. Когда вам будет (или уже было) 10 000 дней от роду?
ƋƓƈƊƈ
ǼȈȑȓȣȐȒȈȚȈȓȖȋȐ

У меня есть файлы, у меня есть компьютерные


файлы, есть, как вы понимаете, и файлы на бумаге.
Но большая часть [истории] хранится у меня в голове.
Помоги мне, Господь, если что-то случится с моей
головой.

Джордж Р. Р. Мартин

Когда вы только начинаете программировать, некоторые слова вы слышите раз за


разом, но не уверены, имеют ли они какое-то техническое значение или просто со-
трясают воздух. Термины «файл» и «каталог» входят в список таких слов, и они на
самом деле имеют техническое значение. Файл — это последовательность байтов,
хранящаяся в определенной файловой системе, к которой можно получить доступ
по имени файла. Каталог — это коллекция файлов и, возможно, других каталогов.
Слово «папка» является синонимом каталога: оно вошло в обиход, когда компью-
теры получили графический пользовательский интерфейс, а чтобы вещи казались
более знакомыми, использовались некоторые офисные концепции.
Многие файловые системы иерархичны и зачастую похожи на деревья. В реаль-
ных офисах, как правило, не бывает деревьев, и аналогия с папками работает только
в том случае, если вы визуализируете все подкаталоги.

ǪȊȖȌȐȕȜȖȘȔȈȞȐȐȊȜȈȑȓȣȐȍȍȊȣȊȖȌȐȏȕȐȝ
Самый простой вид хранения — это старый добрый файл, иногда называемый пло-
ским файлом. Он представляет собой последовательность байтов, которая хранится
под именем файла. Вы считываете данные из файла в память и записываете данные
из памяти в файл. Python позволяет делать это довольно легко. Как и во многих
других языках, операции с файлами, присутствующие в этом языке программирова-
ния, в большинстве своем были смоделированы на основе знакомых и популярных
аналогов, имеющихся в Unix.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǹȖȏȌȈȍȔȐȓȐȖȚȒȘȣȊȈȍȔȜȈȑȓȣ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐRSHQ
Вам нужно вызвать функцию open, прежде чем сделать следующее:
‰прочитать существующий файл;
‰записать в новый файл;
‰добавить данные в существующий файл;
‰перезаписать существующий файл.
ȨȔȝȟɕȢȕʰ‘’‡ſȜȠȳɕȨȔȝȟȔřȤșȚȜȠƀ
Кратко поясню фрагменты этого вызова:
‰ȨȔȝȟɕȢȕ — это объект файла, возвращаемый функцией ‘’‡ſƀ;
‰ȜȠȳɕȨȔȝȟȔ — это строка, представляющая собой имя файла;
‰ȤșȚȜȠ — это строка, указывающая на тип файла и действия, которые вы хотите
произвести над файлом.
Первая буква строки mode указывает на операцию:
‰r означает чтение;
‰w означает запись. Если файла не существует, он будет создан. Если файл суще-
ствует, он будет перезаписан;
‰š означает запись, но только если файла еще не существует;
‰a означает добавление данных в конец файла, если он существует.
Вторая буква строки ‘†‡ указывает на тип файла:
‰t (или ничего) означает, что файл текстовый;
‰b означает, что файл бинарный.
После открытия файла вы вызываете функции для чтения или записи данных.
Они будут показаны в следующих примерах.
Наконец, вам нужно закрыть файл, чтобы гарантировать, что все операции за-
писи завершены, а память освобождена. Далее вы узнаете, как оператор with может
это автоматизировать.
В данной программе открывается файл с именем ‘‘’•Ŝ–š–, а затем закрывается
без выполнения каких-либо действий. В результате будет создан пустой файл:
ʴʴʴˆ‘—–ʰ‘’‡ſɐ‘‘’•Ŝ–š–ɐřɐ™–ɐƀ
ʴʴʴˆ‘—–Ŝ Ž‘•‡ſƀ

ǯȈȗȐșȣȊȈȍȔȊȚȍȒșȚȖȊȣȑȜȈȑȓșȗȖȔȖȡȤȦȜțȕȒȞȐȐSULQW
Создадим заново файл ‘‘’•Ŝ–š–, но теперь запишем в него строку, а затем закроем:
ʴʴʴˆ‘—–ʰ‘’‡ſɐ‘‘’•Ŝ–š–ɐřɐ™–ɐƀ
ʴʴʴ’”‹–ſɐ‘’•ř  ”‡ƒ–‡†ƒˆ‹Ž‡Ŝɐřˆ‹Ž‡ʰˆ‘—–ƀ
ʴʴʴˆ‘—–Ŝ Ž‘•‡ſƀ
ǫȓȈȊȈǼȈȑȓȣȐȒȈȚȈȓȖȋȐ  

Мы создали пустой файл ‘‘’•Ŝ–š– в предыдущем подразделе, поэтому программа


перезаписала его. В вызове функции print мы использовали аргумент file. Без него
функция print будет записывать данные в стандартный поток вывода, которым
является ваша консоль (если только вы не указали программе оболочки перенапра-
вить вывод данных в файл с помощью оператора ʴ или не направили его в другую
программу с помощью оператора Ŷ).

ǯȈȗȐșȣȊȈȍȔȊȚȍȒșȚȖȊȣȑȜȈȑȓ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐZULWH
Мы использовали функцию print для того, чтобы записать строку в файл. Но можно
использовать и функцию write.
В качестве примера многострочного источника данных возьмем лимерик о специ-
альной теории относительности1:
ʴʴʴ’‘‡ʰɐɐɐЇ”‡™ƒ•ƒ›‘—‰Žƒ†›ƒ‡†”‹‰Š–ř
ŜŜŜŠ‘•‡•’‡‡†™ƒ•ˆƒ”ˆƒ•–‡”–ŠƒŽ‹‰Š–Ś
ŜŜŜЇ•–ƒ”–‡†‘‡†ƒ›
ŜŜŜ ƒ”‡Žƒ–‹˜‡™ƒ›ř
ŜŜŜ†”‡–—”‡†‘–Ї’”‡˜‹‘—•‹‰Š–Ŝɐɐɐ
ʴʴʴއſ’‘‡ƀ
ɨɬɥ

Следующий код записывает это стихотворение в файл ɐ”‡Žƒ–‹˜‹–›ɐ с помощью


всего одного вызова:
ʴʴʴˆ‘—–ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐ™–ɐƀ
ʴʴʴˆ‘—–Ŝ™”‹–‡ſ’‘‡ƀ
ɨɬɥ
ʴʴʴˆ‘—–Ŝ Ž‘•‡ſƀ

Функция ™”‹–‡ſƀ возвращает число записанных байтов. Она не добавляет ника-


ких пробелов или символов новой строки, в отличие от функции ’”‹–ſƀ. Как и рань-
ше, вы можете записать в текстовый файл несколько строк:
ʴʴʴˆ‘—–ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐ™–ɐƀ
ʴʴʴ’”‹–ſ’‘‡řˆ‹Ž‡ʰˆ‘—–ƀ
ʴʴʴˆ‘—–Ŝ Ž‘•‡ſƀ

Отсюда возникает вопрос: какую функцию использовать — ™”‹–‡ſƀ или ’”‹–ſƀ?


Как вы уже видели, по умолчанию функция ’”‹–ſƀ добавляет пробел после каждого
аргумента и символ новой строки в конце. В предыдущем примере она добавила
символ новой строки в файл relativity. Для того чтобы функция ’”‹–ſƀ работала
как функция ™”‹–‡ſƀ, передайте ей два следующих аргумента:
‰sep (разделитель, по умолчанию это пробел ɐ ɐ);
‰‡† (символ конца файла, по умолчанию это символ новой строки ɐɎɐ).

1
В первой рукописи этой книги я использовал термин «общая теория относительности»
и был любезно исправлен редактором-физиком.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Вместо значений по умолчанию мы используем пустые строки:


ʴʴʴˆ‘—–ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐ™–ɐƀ
ʴʴʴ’”‹–ſ’‘‡řˆ‹Ž‡ʰˆ‘—–ř•‡’ʰɐɐř‡†ʰɐɐƀ
ʴʴʴˆ‘—–Ŝ Ž‘•‡ſƀ

Если исходная строка большая, вы можете записывать в файл ее фрагменты (ис-


пользуя разделения (слайсы)) до тех пор, пока не запишете всю:
ʴʴʴˆ‘—–ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐ™–ɐƀ
ʴʴʴ•‹œ‡ʰއſ’‘‡ƀ
ʴʴʴ‘ˆˆ•‡–ʰɥ
ʴʴʴ Š—ʰɨɥɥ
ʴʴʴ™Š‹Ž‡”—‡ś
ŜŜŜ‹ˆ‘ˆˆ•‡–ʴ•‹œ‡ś
ŜŜŜ„”‡ƒ
ŜŜŜˆ‘—–Ŝ™”‹–‡ſ’‘‡ƃ‘ˆˆ•‡–ś‘ˆˆ•‡–ʫ Š—Ƅƀ
ŜŜŜ‘ˆˆ•‡–ʫʰ Š—
ŜŜŜ
ɨɥɥ
ɬɥ
ʴʴʴˆ‘—–Ŝ Ž‘•‡ſƀ

Этот код записал 100 символов первым заходом и оставшиеся 50 — вторым.


Слайсы позволяют вам забраться за границы последовательности без генерации
исключения.
Если файл relativity нам очень дорог, проверим, спасет ли режим ȩ его от пере-
записывания:
ʴʴʴˆ‘—–ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐš–ɐƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
‹Ž‡š‹•–•””‘”śƃ””‘ɨɮƄ ‹Ž‡‡š‹•–•śɐ”‡Žƒ–‹˜‹–›ɐ

Вы можете использовать этот код вместе с обработчиком исключений:


ʴʴʴ–”›ś
ŜŜŜˆ‘—–ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐš–ɐƀƄ
ŜŜŜˆ‘—–Ŝ™”‹–‡ſɐ•–‘’•–‘’•–‘’ɐƀ
ŜŜŜ‡š ‡’– ‹Ž‡š‹•–•””‘”ś
ŜŜŜ’”‹–ſɐ”‡Žƒ–‹˜‹–›ƒŽ”‡ƒ†›‡š‹•–•ŠŜŠƒ–™ƒ•ƒ Ž‘•‡‘‡Ŝɐƀ
ŜŜŜ
”‡Žƒ–‹˜‹–›ƒŽ”‡ƒ†›‡š‹•–•ŠŜŠƒ–™ƒ•ƒ Ž‘•‡‘‡Ŝ

ǹȟȐȚȣȊȈȍȔȌȈȕȕȣȍȐȏȚȍȒșȚȖȊȖȋȖȜȈȑȓȈ
ȐșȗȖȓȤȏțȧȜțȕȒȞȐȐUHDG UHDGOLQH ȐUHDGOLQHV
Вы можете вызвать функцию ”‡ƒ†ſƀ без аргументов, чтобы достать весь файл сразу,
как показано в следующем примере. Будьте осторожны, делая это с крупными фай-
лами: файл размером 1 Гбайт потребит 1 Гбайт памяти:
ʴʴʴˆ‹ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐ”–ɐƀ
ʴʴʴ’‘‡ʰˆ‹Ŝ”‡ƒ†ſƀ
ǫȓȈȊȈǼȈȑȓȣȐȒȈȚȈȓȖȋȐ  

ʴʴʴˆ‹Ŝ Ž‘•‡ſƀ
ʴʴʴއſ’‘‡ƀ
ɨɬɥ

Вы можете указать максимальное количество символов, которое функция ”‡ƒ†ſƀ


вернет за один вызов. Мы будем считывать по 100 символов за раз и присоединять
каждый фрагмент к строке ’‘‡, чтобы восстановить оригинал:
ʴʴʴ’‘‡ʰɐɐ
ʴʴʴˆ‹ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐ”–ɐƀ
ʴʴʴ Š—ʰɨɥɥ
ʴʴʴ™Š‹Ž‡”—‡ś
ŜŜŜˆ”ƒ‰‡–ʰˆ‹Ŝ”‡ƒ†ſ Š—ƀ
ŜŜŜ‹ˆ‘–ˆ”ƒ‰‡–ś
ŜŜŜ„”‡ƒ
ŜŜŜ’‘‡ʫʰˆ”ƒ‰‡–
ŜŜŜ
ʴʴʴˆ‹Ŝ Ž‘•‡ſƀ
ʴʴʴއſ’‘‡ƀ
ɨɬɥ

После того как вы считаете весь файл, дальнейшие вызовы функции ”‡ƒ†ſƀ будут
возвращать пустую строку ɐ ɐ, которая рассматривается как ƒŽ•‡ при проверке if
not ˆ”ƒ‰‡–. Это позволит выйти из цикла while ”—‡.
Вы также можете считывать файл построчно с помощью функции ”‡ƒ†Ž‹‡ſƀ.
В следующем примере мы будем присоединять по одной строке к ’‘‡, чтобы вос-
становить оригинал:
ʴʴʴ’‘‡ʰɐɐ
ʴʴʴˆ‹ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐ”–ɐƀ
ʴʴʴ™Š‹Ž‡”—‡ś
ŜŜŜŽ‹‡ʰˆ‹Ŝ”‡ƒ†Ž‹‡ſƀ
ŜŜŜ‹ˆ‘–Ž‹‡ś
ŜŜŜ„”‡ƒ
ŜŜŜ’‘‡ʫʰŽ‹‡
ŜŜŜ
ʴʴʴˆ‹Ŝ Ž‘•‡ſƀ
ʴʴʴއſ’‘‡ƀ
ɨɬɥ

Для текстового файла даже пустая строка имеет длину, равную ɨ (символ новой
строки), такая строка будет считаться ”—‡. Когда весь файл будет считан, функция
”‡ƒ†Ž‹‡ſƀ (как и функция ”‡ƒ†ſƀ) возвратит пустую строку, которая будет счи-
таться ƒŽ•‡.
Самый простой способ считать текстовый файл — использовать итератор.
Он будет возвращать по одной строке за раз. Этот пример похож на предыдущий,
но кода в нем меньше:
ʴʴʴ’‘‡ʰɐɐ
ʴʴʴˆ‹ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐ”–ɐƀ
ʴʴʴˆ‘”Ž‹‡‹ˆ‹ś
ŜŜŜ’‘‡ʫʰŽ‹‡
ŜŜŜ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ʴʴʴˆ‹Ŝ Ž‘•‡ſƀ
ʴʴʴއſ’‘‡ƀ
ɨɬɥ

Во всех предыдущих примерах в результате получалась одна строка ’‘‡. Функ-


ция ”‡ƒ†Ž‹‡ſƀ считывает по одной строке за раз и возвращает список этих строк:
ʴʴʴˆ‹ʰ‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐ”–ɐƀ
ʴʴʴŽ‹‡•ʰˆ‹Ŝ”‡ƒ†Ž‹‡•ſƀ
ʴʴʴˆ‹Ŝ Ž‘•‡ſƀ
ʴʴʴ’”‹–ſއſŽ‹‡•ƀřɐŽ‹‡•”‡ƒ†ɐƀ
ɬŽ‹‡•”‡ƒ†
ʴʴʴˆ‘”Ž‹‡‹Ž‹‡•ś
ŜŜŜ’”‹–ſŽ‹‡ř‡†ʰɐɐƀ
ŜŜŜ
Ї”‡™ƒ•ƒ›‘—‰Žƒ†›ƒ‡†”‹‰Š–ř
Š‘•‡•’‡‡†™ƒ•ˆƒ”ˆƒ•–‡”–ŠƒŽ‹‰Š–Ś
Ї•–ƒ”–‡†‘‡†ƒ›
ƒ”‡Žƒ–‹˜‡™ƒ›ř
†”‡–—”‡†‘–Ї’”‡˜‹‘—•‹‰Š–Ŝʴʴʴ

Мы указали функции ’”‹–ſƀ не добавлять автоматически символы новой


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

ǯȈȗȐșȣȊȈȍȔȌȈȕȕȣȍȊȉȐȕȈȘȕȣȑȜȈȑȓ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐZULWH
Если вы включите символ ɐ„ɐ в строку режима, файл откроется в бинарном режиме.
В этом случае вы будете читать и записывать байты, а не строки.
У нас под рукой нет бинарного стихотворения, поэтому мы просто сгенерируем
256 байтовых значений от 0 до 255:
ʴʴʴ„†ƒ–ƒʰ„›–‡•ſ”ƒ‰‡ſɥřɩɬɭƀƀ
ʴʴʴއſ„†ƒ–ƒƀ
ɩɬɭ

Откроем файл для записи в бинарном режиме и запишем все данные сразу:
ʴʴʴˆ‘—–ʰ‘’‡ſɐ„ˆ‹Ž‡ɐřɐ™„ɐƀ
ʴʴʴˆ‘—–Ŝ™”‹–‡ſ„†ƒ–ƒƀ
ɩɬɭ
ʴʴʴˆ‘—–Ŝ Ž‘•‡ſƀ

И вновь функция ™”‹–‡ſƀ возвращает количество записанных байтов.


Как и при работе с текстом, вы можете записывать бинарные данные фрагмен-
тами:
ʴʴʴˆ‘—–ʰ‘’‡ſɐ„ˆ‹Ž‡ɐřɐ™„ɐƀ
ʴʴʴ•‹œ‡ʰއſ„†ƒ–ƒƀ
ǫȓȈȊȈǼȈȑȓȣȐȒȈȚȈȓȖȋȐ  

ʴʴʴ‘ˆˆ•‡–ʰɥ
ʴʴʴ Š—ʰɨɥɥ
ʴʴʴ™Š‹Ž‡”—‡ś
ŜŜŜ‹ˆ‘ˆˆ•‡–ʴ•‹œ‡ś
ŜŜŜ„”‡ƒ
ŜŜŜˆ‘—–Ŝ™”‹–‡ſ„†ƒ–ƒƃ‘ˆˆ•‡–ś‘ˆˆ•‡–ʫ Š—Ƅƀ
ŜŜŜ‘ˆˆ•‡–ʫʰ Š—
ŜŜŜ
ɨɥɥ
ɨɥɥ
ɬɭ
ʴʴʴˆ‘—–Ŝ Ž‘•‡ſƀ

ǿȐȚȈȍȔȉȐȕȈȘȕȣȍȜȈȑȓȣșȗȖȔȖȡȤȦȜțȕȒȞȐȐUHDG
Это достаточно просто. Все, что вам нужно, — открыть файл в режиме ɐ”„ɐ:
ʴʴʴˆ‹ʰ‘’‡ſɐ„ˆ‹Ž‡ɐřɐ”„ɐƀ
ʴʴʴ„†ƒ–ƒʰˆ‹Ŝ”‡ƒ†ſƀ
ʴʴʴއſ„†ƒ–ƒƀ
ɩɬɭ
ʴʴʴˆ‹Ŝ Ž‘•‡ſƀ

ǯȈȒȘȣȊȈȍȔȜȈȑȓȣȈȊȚȖȔȈȚȐȟȍșȒȐ
șȗȖȔȖȡȤȦȒȓȦȟȍȊȖȋȖșȓȖȊȈZLWK
Если вы забудете закрыть файл, его закроет Python после того, как будет удалена
последняя ссылка на этот файл. Таким образом, если вы откроете файл и не за-
кроете его явно, он будет закрыт автоматически по завершении функции. Но вы
можете открыть файл внутри длинной функции или даже основного раздела про-
граммы. Файл должен быть закрыт, чтобы все оставшиеся операции записи были
завершены.
У Python имеются менеджеры контекста для очистки таких объектов, как от-
крытые файлы. Вы можете использовать конструкцию with ȖȯȤȔȚșȡȜș as ȣșȤșȠșȡȡȔȳ:
ʴʴʴ™‹–Š‘’‡ſɐ”‡Žƒ–‹˜‹–›ɐřɐ™–ɐƀƒ•ˆ‘—–ś
ŜŜŜˆ‘—–Ŝ™”‹–‡ſ’‘‡ƀ
ŜŜŜ

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

ǴȍȕȧȍȔȗȖȏȐȞȐȦșȗȖȔȖȡȤȦȜțȕȒȞȐȐVHHN
В процессе чтения и записи Python отслеживает ваше местоположение в файле.
Функция –‡ŽŽſƀ возвращает ваше текущее смещение от начала файла в байтах.
Функция •‡‡ſƀ позволяет перейти к другому смещению в файле. Это значит, что
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

вам не обязательно прочитывать каждый байт файла, чтобы добраться до послед-


него, — вы можете использовать функцию •‡‡ſƀ: сместиться именно к нужному
байту и считать его.
Для примера воспользуемся 256-байтным бинарным файлом ɐ„ˆ‹Ž‡ɐ, который
мы создали ранее:
ʴʴʴˆ‹ʰ‘’‡ſɐ„ˆ‹Ž‡ɐřɐ”„ɐƀ
ʴʴʴˆ‹Ŝ–‡ŽŽſƀ
ɥ

Используем функцию •‡‡ſƀ, чтобы перейти к предпоследнему байту файла:


ʴʴʴˆ‹Ŝ•‡‡ſɩɬɬƀ
ɩɬɬ

Считаем все данные от текущей позиции до конца файла:


ʴʴʴ„†ƒ–ƒʰˆ‹Ŝ”‡ƒ†ſƀ
ʴʴʴއſ„†ƒ–ƒƀ
ɨ
ʴʴʴ„†ƒ–ƒƃɥƄ
ɩɬɬ

Функция •‡‡ſƀ также возвращает текущее смещение.


Вы также можете вызвать функцию •‡‡ſƀ , передав ей второй аргумент:
•‡‡ſ‘ˆˆ•‡–ř ‘”‹‰‹ƀ:

‰если значение origin равно ɥ (по умолчанию), вы сместитесь на offset байтов


от начала файла;
‰если значение origin равно ɨ, вы сместитесь на offset байтов с текущей по-
зиции;
‰если значение origin равно ɩ, вы сместитесь на offset байтов от конца файла.
Эти значения также определены в стандартном модуле os:
ʴʴʴ‹’‘”–‘•
ʴʴʴ‘•Ŝɏ
ɥ
ʴʴʴ‘•Ŝɏ
ɨ
ʴʴʴ‘•Ŝɏ
ɩ

Благодаря этому последний байт можно считать разными способами:


ʴʴʴˆ‹ʰ‘’‡ſɐ„ˆ‹Ž‡ɐřɐ”„ɐƀ

Один байт перед концом файла:


ʴʴʴˆ‹Ŝ•‡‡ſŞɨřɩƀ
ɩɬɬ
ʴʴʴˆ‹Ŝ–‡ŽŽſƀ
ɩɬɬ
ǫȓȈȊȈǼȈȑȓȣȐȒȈȚȈȓȖȋȐ  

Считать данные до конца файла:


ʴʴʴ„†ƒ–ƒʰˆ‹Ŝ”‡ƒ†ſƀ
ʴʴʴއſ„†ƒ–ƒƀ
ɨ
ʴʴʴ„†ƒ–ƒƃɥƄ
ɩɬɬ

ǪȈȔȕȍȕțȎȕȖȊȣȏȣȊȈȚȤȜțȕȒȞȐȦWHOO ȟȚȖȉȣȘȈȉȖȚȈȓȈȜțȕȒȞȐȧVHHN ȇȚȖȓȤȒȖ


ȝȖȚȍȓȗȖȒȈȏȈȚȤȟȚȖȖȉȍȥȚȐȜțȕȒȞȐȐȊȖȏȊȘȈȡȈȦȚȖȌȐȕȈȒȖȊȖȍșȔȍȡȍȕȐȍ

Рассмотрим случай, когда мы вызываем функцию •‡‡ſƀ , чтобы сместиться


с текущей позиции:
ʴʴʴˆ‹ʰ‘’‡ſɐ„ˆ‹Ž‡ɐřɐ”„ɐƀ

Следующий пример переносит позицию за 2 байта до конца файла:


ʴʴʴˆ‹Ŝ•‡‡ſɩɬɫřɥƀ
ɩɬɫ
ʴʴʴˆ‹Ŝ–‡ŽŽſƀ
ɩɬɫ

Теперь перейдем вперед на 1 байт:


ʴʴʴˆ‹Ŝ•‡‡ſɨřɨƀ
ɩɬɬ
ʴʴʴˆ‹Ŝ–‡ŽŽſƀ
ɩɬɬ

Наконец, считаем все данные до конца файла:


ʴʴʴ„†ƒ–ƒʰˆ‹Ŝ”‡ƒ†ſƀ
ʴʴʴއſ„†ƒ–ƒƀ
ɨ
ʴʴʴ„†ƒ–ƒƃɥƄ
ɩɬɬ

Эти функции наиболее полезны при работе с бинарными файлами. Вы можете


использовать их и для работы с текстовыми файлами, но если файл состоит не толь-
ко из символов формата ASCII (каждый из которых занимает по 1 байту в памяти),
вам будет трудно определить смещение. Ведь в таком случае оно будет зависеть от
кодировки текста, а самая популярная кодировка (UTF-8) использует разное коли-
чество байтов для разных символов.

ǶȚȖȉȘȈȎȍȕȐȍȊȗȈȔȧȚȐ
Альтернативой чтению и записи файла является его отображение в памяти
(memory-map) с помощью стандартного модуля ƒ’. Такой подход позволяет пред-
ставить содержимое файла как bytearray в памяти. Для получения более подробной
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

информации обратитесь к документации (KWWSVGRFVS\WKRQRUJOLEUDU\PPDSKWPO)


и примерам (KWWSVS\PRWZFRPPPDSLQGH[KWPO).

ǶȗȍȘȈȞȐȐșȜȈȑȓȈȔȐ
В Python, как и во многих других языках программирования, операции для работы
с файлами основаны на аналогичных операциях ОС Unix. Некоторые функции,
такие как Š‘™ſƀ и Š‘†ſƀ, называются одинаково, но теперь появились и новые
названия. Сначала я покажу, как Python решает задачи с помощью функций из мо-
дуля ‘•Ŝ’ƒ–Š, а затем — с помощью более нового модуля pathlib.

ǷȘȖȊȍȘȧȍȔșțȡȍșȚȊȖȊȈȕȐȍȜȈȑȓȈ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐH[LVWV
Если хотите убедиться в том, что файл или каталог действительно существуют,
а не являются плодом вашего воображения, воспользуйтесь функцией ‡š‹•–•ſƀ.
Передайте функции относительное или абсолютное имя файла, как показано
здесь:
ʴʴʴ‹’‘”–‘•
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‡š‹•–•ſɐ‘‘’•Ŝ–š–ɐƀ
”—‡
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‡š‹•–•ſɐŜŵ‘‘’•Ŝ–š–ɐƀ
”—‡
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‡š‹•–•ſɐ™ƒˆˆŽ‡•ɐƀ
ƒŽ•‡
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‡š‹•–•ſɐŜɐƀ
”—‡
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‡š‹•–•ſɐŜŜɐƀ
”—‡

ǷȘȖȊȍȘȧȍȔȚȐȗșȗȖȔȖȡȤȦȜțȕȒȞȐȐLVILOH
Функции, показанные в этом подразделе, проверяют, ссылается ли имя на файл,
каталог или символьную ссылку (см. примеры, которые располагаются после опи-
сания ссылок).
Первой мы рассмотрим функцию ‹•ˆ‹Ž‡ſƀ. Она задает простой вопрос: перед
нами находится старый добрый законопослушный файл?
ʴʴʴƒ‡ʰɐ‘‘’•Ŝ–š–ɐ
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‹•ˆ‹Ž‡ſƒ‡ƀ
”—‡

Вот так можно определить папку:


ʴʴʴ‘•Ŝ’ƒ–ŠŜ‹•†‹”ſƒ‡ƀ
ƒŽ•‡
ǫȓȈȊȈǼȈȑȓȣȐȒȈȚȈȓȖȋȐ  

Одна точка (Ŝ) является сокращением для текущей папки, а две точки (ŜŜ) — для
родительской. Эти папки существуют всегда, поэтому следующее выражение вернет
результат ”—‡:
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‹•†‹”ſɐŜɐƀ
”—‡

Модуль os содержит множество функций, работающих с pathname (именем


пути) — полным именем файла, начинающимся с символа ŵ и включающим в себя
имена всех вложенных файлов. Одна из таких функций, ‹•ƒ„•ſƀ, определяет, явля-
ется ли аргумент абсолютным путем. Аргумент не обязательно должен быть именем
реально существующего файла:
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‹•ƒ„•ſƒ‡ƀ
ƒŽ•‡
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‹•ƒ„•ſɐŵ„‹‰ŵˆƒ‡ŵƒ‡ɐƀ
”—‡
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‹•ƒ„•ſɐ„‹‰ŵˆƒ‡ŵƒ‡ŵ™‹–Š‘—–ŵƒŵއƒ†‹‰ŵ•Žƒ•Šɐƀ
ƒŽ•‡

DzȖȗȐȘțȍȔȜȈȑȓȣȐșȗȖȓȤȏțȧȜțȕȒȞȐȦFRS\
Функция ‘’›ſƀ находится в другом модуле, shutil. В этом примере файл ‘‘’•Ŝ–š–
копируется в файл ‘Š‘Ŝ–š–:
ʴʴʴ‹’‘”–•Š—–‹Ž
ʴʴʴ•Š—–‹ŽŜ ‘’›ſɐ‘‘’•Ŝ–š–ɐřɐ‘А‘Ŝ–š–ɐƀ

Функция •Š—–‹ŽŜ‘˜‡ſƀ копирует файл, а затем удаляет оригинал.

ǰȏȔȍȕȧȍȔȐȔȍȕȈȜȈȑȓȖȊșȗȖȔȖȡȤȦȜțȕȒȞȐȐUHQDPH
Эта функция соответствует своему названию. В этом примере файл ‘Š‘Ŝ–š– пере-
именовывается в ‘Š™‡ŽŽŜ–š–:
ʴʴʴ‹’‘”–‘•
ʴʴʴ‘•Ŝ”‡ƒ‡ſɐ‘А‘Ŝ–š–ɐřɐ‘Š™‡ŽŽŜ–š–ɐƀ

ǹȖȏȌȈȍȔșșȣȓȒȐșȗȖȔȖȡȤȦȜțȕȒȞȐȐOLQN 
ȐȓȐV\POLQN
В операционных системах семейства Unix файл находится в одном определенном
месте, но может иметь несколько имен, называемых ссылками. В низкоуровневых
жестких ссылках найти все имена заданного файла не так уж легко. Символьная ссыл-
ка — это альтернативный метод, который сохраняет новое имя в своем собственном
файле, позволяя вам получить одновременно оба имени — оригинальное и новое.
Вызов Ž‹ſƀ создает жесткую ссылку, а •›Ž‹ſƀ — символьную ссылку. Функция
‹•Ž‹ſƀ проверяет, является ли файл символьной ссылкой.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Вот так можно создать жесткую ссылку на существующий файл ‘‘’•Ŝ–š– из


нового файла ›‹‡•Ŝ–š–:
ʴʴʴ‘•ŜŽ‹ſɐ‘‘’•Ŝ–š–ɐřɐ›‹‡•Ŝ–š–ɐƀ
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‹•ˆ‹Ž‡ſɐ›‹‡•Ŝ–š–ɐƀ
”—‡

Для того чтобы создать символьную ссылку на существующий файл ‘‘’•Ŝ–š– из


нового файла Œ‡‡’‡”•Ŝ–š–, используйте следующий код:
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‹•Ž‹ſɐ›‹‡•Ŝ–š–ɐƀ
ƒŽ•‡
ʴʴʴ‘•Ŝ•›Ž‹ſɐ‘‘’•Ŝ–š–ɐřɐŒ‡‡’‡”•Ŝ–š–ɐƀ
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‹•Ž‹ſɐŒ‡‡’‡”•Ŝ–š–ɐƀ
”—‡

ǰȏȔȍȕȧȍȔȘȈȏȘȍȠȍȕȐȧșȗȖȔȖȡȤȦȜțȕȒȞȐȐFKPRG
В системах Unix функция Š‘†ſƀ вносит изменения в права на доступ к файлу.
Существуют права на чтение, запись и выполнение файла для пользователя (обыч-
но того, кто создавал файл), а также для какой-то группы, в которой состоит поль-
зователь, и для всех остальных. Команда принимает сильно сжатое восьмеричное
значение (в системе счисления с основанием 8), в котором указаны пользователь,
группа и другие, кто имеет доступ. Например, для указания того, что файл ‘‘’•Ŝ–š–
для чтения доступен только своему владельцу, нужно ввести следующий код:
ʴʴʴ‘•Ŝ Š‘†ſɐ‘‘’•Ŝ–š–ɐřɥ‘ɫɥɥƀ

Если вы не хотите работать с загадочными восьмеричными значениями и пред-


почитаете иметь дело с более понятными символами, можете импортировать не-
которые константы из модуля stat и использовать такое выражение:
ʴʴʴ‹’‘”–•–ƒ–
ʴʴʴ‘•Ŝ Š‘†ſɐ‘‘’•Ŝ–š–ɐř•–ƒ–Ŝɏ ƀ

ǰȏȔȍȕȍȕȐȍȊȓȈȌȍȓȤȞȈȜȈȑȓȈșȗȖȔȖȡȤȦȜțȕȒȞȐȐFKRZQ
Эта функция также характерна для систем Unix/Linux/Mac. Вы можете изменить
владельца и/или группу, указав числовой идентификатор пользователя ID (—‹†)
и идентификатор группы (‰‹†):
ʴʴʴ—‹†ʰɬ
ʴʴʴ‰‹†ʰɩɩ
ʴʴʴ‘•Ŝ Š‘™ſɐ‘‘’•ɐř—‹†ř‰‹†ƀ

ǻȌȈȓȧȍȔȜȈȑȓșȗȖȔȖȡȤȦȜțȕȒȞȐȐUHPRYH
В этом фрагменте мы используем функцию ”‡‘˜‡ſƀ и попрощаемся с файлом ‘‘’•Ŝ–š–:
ʴʴʴ‘•Ŝ”‡‘˜‡ſɐ‘‘’•Ŝ–š–ɐƀ
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‡š‹•–•ſɐ‘‘’•Ŝ–š–ɐƀ
ƒŽ•‡
ǫȓȈȊȈǼȈȑȓȣȐȒȈȚȈȓȖȋȐ  

DzȈȚȈȓȖȋȐ
В большинстве операционных систем файлы существуют в рамках иерархии ȞȔȦȔŞ
ȟȢȗȢȖ (иначе их еще называют ȣȔȣȞȔȠȜ). Контейнером для всех этих файлов и ката-
логов служит файловая система (иногда ее называют томом). Стандартный модуль
os работает с такой иерархией и предоставляет функции, с помощью которых ею
можно манипулировать.

ǹȖȏȌȈȍȔȒȈȚȈȓȖȋșȗȖȔȖȡȤȦȜțȕȒȞȐȐPNGLU
В этом примере показывается, как создать каталог ’‘‡•, в котором мы сохраним
предыдущее стихотворение:
ʴʴʴ‘•Ŝ†‹”ſɐ’‘‡•ɐƀ
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‡š‹•–•ſɐ’‘‡•ɐƀ
”—‡

ǻȌȈȓȧȍȔȒȈȚȈȓȖȋȐșȗȖȓȤȏțȧȜțȕȒȞȐȦUPGLU
Немного подумав1, вы решили, что этот каталог вам не нужен. Удалить его можно
так:
ʴʴʴ‘•Ŝ”†‹”ſɐ’‘‡•ɐƀ
ʴʴʴ‘•Ŝ’ƒ–ŠŜ‡š‹•–•ſɐ’‘‡•ɐƀ
ƒŽ•‡

ǪȣȊȖȌȐȔȕȈȥȒȘȈȕșȖȌȍȘȎȐȔȖȍȒȈȚȈȓȖȋȈ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐOLVWGLU
О’кей, дубль два: снова создадим файл ’‘‡• и что-нибудь в него запишем:
ʴʴʴ‘•Ŝ†‹”ſɐ’‘‡•ɐƀ

Теперь получим список всех файлов, содержащихся в этом каталоге (их пока нет):
ʴʴʴ‘•ŜŽ‹•–†‹”ſɐ’‘‡•ɐƀ
ƃƄ

Далее создадим подкаталог:


ʴʴʴ‘•Ŝ†‹”ſɐ’‘‡•ŵ ‹–›”‡ɐƀ
ʴʴʴ‘•ŜŽ‹•–†‹”ſɐ’‘‡•ɐƀ
ƃɐ ‹–›”‡ɐƄ

Создайте в подкаталоге файл (не вводите все эти строки, если только не хотите
почувствовать себя поэтом, а просто убедитесь, что начинаете и заканчиваете соот-
ветствующими кавычками, одинарными или тройными):
ʴʴʴˆ‘—–ʰ‘’‡ſɐ’‘‡•ŵ ‹–›”‡ŵ–Їɏ‰‘‘†ɏƒɐřɐ™–ɐƀ
ʴʴʴˆ‘—–Ŝ™”‹–‡ſɐɐɐЇ‡”ˆ—Žƒ†Šƒ’’›™ƒ•Š‹•‘‘†ř

1
И почему же мы не подумали раньше?
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ŜŜŜ ‡–‘–Ї’‘‘”™ƒ•‹†ƒ†‰‘‘†ř
ŜŜŜ†Ї‘ˆ–ɐ–‹‡•†‹†ˆ‹†–Їˆ‘‘†ř
ŜŜŜŽ•‘•—’’Ž‹‡•‘ˆ ‘ƒŽƒ†™‘‘†ř
ŜŜŜ ‡‡˜‡”•’ƒ‡ƒ™‘”†™ƒ•”—†‡ř
ŜŜŜ† Ї‡”ɐ†–Š‘•‡†‹†‘ɐ‡”•‘””‘™•„”‘‘†ř
ŜŜŜ ‡’ƒ••‡†ƒ™ƒ›‘–—†‡”•–‘‘†ř
ŜŜŜ‡ ƒ—•‡‘’‘‡–‹Š‹•Žƒ›•
ŜŜŜ ƒ†’‡‡†ƒ•‘‡–‹Š‹•’”ƒ‹•‡ř
ŜŜŜɐ‹••ƒ†ř„—–•— Š‹•™‘”ކɐ•™ƒ›•Ŝ
ŜŜŜɐɐɐƀ
ɪɫɫ
ʴʴʴˆ‘—–Ŝ Ž‘•‡ſƀ

Наконец, проверьте, что получилось. Хорошо, если бы файл там был:


ʴʴʴ‘•ŜŽ‹•–†‹”ſɐ’‘‡•ŵ ‹–›”‡ɐƀ
ƃɐ–Їɏ‰‘‘†ɏƒɐƄ

ǰȏȔȍȕȧȍȔȚȍȒțȡȐȑȒȈȚȈȓȖȋ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐFKGLU
С помощью этой функции вы можете переходить из одной папки в другие. Покинем
текущую папку и проведем немного времени в каталоге ’‘‡•:
ʴʴʴ‹’‘”–‘•
ʴʴʴ‘•Ŝ І‹”ſɐ’‘‡•ɐƀ
ʴʴʴ‘•ŜŽ‹•–†‹”ſɐŜɐƀ
ƃɐ ‹–›”‡ɐƄ

ǷȍȘȍȟȐșȓȧȍȔșȖȊȗȈȌȈȦȡȐȍȜȈȑȓȣ
ȐșȗȖȓȤȏțȧȜțȕȒȞȐȦJORE
Функция ‰Ž‘„ſƀ ищет совпадающие имена файлов или каталогов, используя правила
оболочки Unix, а не более полный синтаксис регулярных выражений. Эти правила
выглядят так:
‰* — совпадает со всем (в регулярных выражениях аналогом выступает ŜƋ);
‰ţ — совпадает с одним символом;
‰ƃƒ„ Ƅ — совпадает с символами a, b или ;
‰ƃЃ„ Ƅ — совпадает со всеми символами, кроме a, b или .
Получим все файлы и каталоги, имена которых начинаются с буквы :
ʴʴʴ‹’‘”–‰Ž‘„
ʴʴʴ‰Ž‘„Ŝ‰Ž‘„ſɐƋɐƀ
ƃɐ ‹–›”‡ɐƄ

А как насчет файлов и каталогов с именами, состоящими из двух символов?


ʴʴʴ‰Ž‘„Ŝ‰Ž‘„ſɐţţɐƀ
ƃƄ
ǫȓȈȊȈǼȈȑȓȣȐȒȈȚȈȓȖȋȐ  

Я думаю о слове из восьми букв, которое начинается на  и заканчивается на e:


ʴʴʴ‰Ž‘„Ŝ‰Ž‘„ſɐţţţţţţ‡ɐƀ
ƃɐ ‹–›”‡ɐƄ

Как насчет чего-то, что начинается с букв , l или  и заканчивается на букву e?


ʴʴʴ‰Ž‘„Ŝ‰Ž‘„ſɐƃŽƄƋ‡ɐƀ
ƃɐ ‹–›”‡ɐƄ

3DWKQDPH
Практически во всех компьютерах используется иерархическая файловая система,
в которой каталоги (папки) содержат файлы и другие каталоги произвольного
уровня вложенности. Если вы хотите обратиться к определенному файлу или ката-
логу, вам необходимо указать его путь (pathname): последовательность каталогов,
необходимых для того, чтобы добраться до искомого объекта. Последовательность
может быть абсолютной и начинаться сверху (от корня), а может быть относитель-
ной и начинаться с вашего текущего каталога.
Вы часто слышите, как люди путают прямой слеш (это символ ɐŵɐ, а не музыкант
из группы Guns N’ Roses) и обратный слеш ɐɎɐ1. В ОС семейств Unix и Macs (а также
в URL) как разделитель пути применяется слеш, а в ОС Windows — обратный слеш2.
Python позволяет использовать слеш в качестве разделителя пути, когда вы указы-
ваете имена. В Windows вы можете задействовать обратный слеш, но при этом обрат-
ный слеш также является распространенным символом в escape-последовательностях
в Python, поэтому вы должны его удваивать или использовать необработанные
строки Python:
ʴʴʴ™‹ɏˆ‹Ž‡ʰɐ‡‡ɎɎ—”ɎɎ•‘”–Ŝ–š–ɐ
ʴʴʴ™‹ɏˆ‹Ž‡ɩʰ”ɐ‡‡Ɏ—”Ɏ•‘”–Ŝ–š–ɐ
ʴʴʴ™‹ɏˆ‹Ž‡
ɐ‡‡ɎɎ—”ɎɎ•‘”–Ŝ–š–ɐ
ʴʴʴ™‹ɏˆ‹Ž‡ɩ
ɐ‡‡ɎɎ—”ɎɎ•‘”–Ŝ–š–ɐ

При создании pathname вы можете сделать следующее:


‰использовать подходящий символ разделителя пути (ɐŵɐ или ɐɎɐ);
‰построить путь (см. подраздел «Построение пути с помощью [Link]()» далее
в этой главе);
‰использовать модуль pathlib (см. подраздел «Модуль pathlib» также в этой
главе).

1
Один из способов запомнить названия слешей: обычный наклонен вперед, а обратный —
назад.
2
QDOS — это операционная система, которую приобрел Билл Гейтс за $50 000, чтобы соз-
дать MS-DOS, когда IBM начала интересоваться первым ПК. Она была похожа на CP/M,
где слеши использовались в аргументах командной строки. Когда в MS-DOS появились
каталоги, для них пришлось использовать обратные слеши.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǷȖȓțȟȈȍȔȗțȚȤșȗȖȔȖȡȤȦȜțȕȒȞȐȐDEVSDWK
Эта функция расширяет относительное имя до абсолютного. Если ваш текущий
каталог — ŵ—•”ŵ‰ƒ„‡”Ž—œ‹‡ и файл ‘‘’•Ŝ–š– находится там же, можете воспользо-
ваться следующим кодом:
ʴʴʴ‘•Ŝ’ƒ–ŠŜƒ„•’ƒ–Šſɐ‘‘’•Ŝ–š–ɐƀ
ɐŵ—•”ŵ‰ƒ„‡”Ž—œ‹‡ŵ‘‘’•Ŝ–š–ɐ

ǷȖȓțȟȈȍȔșȐȔȊȖȓȤȕțȦșșȣȓȒț
șȗȖȔȖȡȤȦȜțȕȒȞȐȐUHDOSDWK
В одном из предыдущих разделов мы создавали символьную ссылку на файл
‘‘’•Ŝ–š– из нового файла Œ‡‡’‡”•Ŝ–š–. При похожих обстоятельствах вы можете
получить имя файла ‘‘’•Ŝ–š– из файла Œ‡‡’‡”•Ŝ–š– с помощью функции ”‡ƒŽ’ƒ–Šſƀ,
как показано здесь:
ʴʴʴ‘•Ŝ’ƒ–ŠŜ”‡ƒŽ’ƒ–ŠſɐŒ‡‡’‡”•Ŝ–š–ɐƀ
ɐŵ—•”ŵ‰ƒ„‡”Ž—œ‹‡ŵ‘‘’•Ŝ–š–ɐ

ǷȖșȚȘȖȍȕȐȍȗțȚȐșȗȖȔȖȡȤȦȜțȕȒȞȐȐRVSDWKMRLQ
Когда вы создаете составное имя пути, вы можете вызвать функцию ‘•Ŝ’ƒ–ŠŜŒ‘‹ſƀ
и объединить части попарно, используя правильный для вашей ОС символ-раз-
делитель:
ʴʴʴ‹’‘”–‘•
ʴʴʴ™‹ɏˆ‹Ž‡ʰ‘•Ŝ’ƒ–ŠŜŒ‘‹ſɑ‡‡ɑřɑ—”ɑƀ
ʴʴʴ™‹ɏˆ‹Ž‡ʰ‘•Ŝ’ƒ–ŠŜŒ‘‹ſ™‹ɏˆ‹Ž‡řɑ•‘”–Ŝ–š–ɑƀ

Если я запущу эту функцию на ПК с ОС Mac или Linux, я получу следующее:


ʴʴʴ™‹ɏˆ‹Ž‡
ɐ‡‡ŵ—”ŵ•‘”–Ŝ–š–ɐ

Запуск в ОС Windows даст такой результат:


ʴʴʴ™‹ɏˆ‹Ž‡
ɐ‡‡ɎɎ—”ɎɎ•‘”–Ŝ–š–ɐ

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

ǴȖȌțȓȤSDWKOLE
В Python модуль pathlib добавился в версии 3.4. Он представляет собой альтерна-
тиву модулям ‘•Ŝ’ƒ–Š, которые мы только что рассмотрели. Зачем же нужен еще
один модуль?
ǫȓȈȊȈǼȈȑȓȣȐȒȈȚȈȓȖȋȐ  

Вместо того чтобы считать пути строками, этот модуль создает объект типа ƒ–Š,
чтобы работать с ними на более высоком уровне. Создайте объект типа ƒ–Š с помо-
щью вызова ƒ–Šſƀ, а затем склейте все элементы вашего пути с помощью простых
слешей (а не символов ɐŵ'):
ʴʴʴˆ”‘’ƒ–ŠŽ‹„‹’‘”–ƒ–Š
ʴʴʴˆ‹Ž‡ɏ’ƒ–Šʰƒ–Šſɐ‡‡ɐƀŵɐ—”ɐŵɐ•‘”–Ŝ–š–ɐ
ʴʴʴˆ‹Ž‡ɏ’ƒ–Š
‘•‹šƒ–Šſɐ‡‡ŵ—”ŵ•‘”–Ŝ–š–ɐƀ
ʴʴʴ’”‹–ſˆ‹Ž‡ɏ’ƒ–Šƀ
‡‡ŵ—”ŵ•‘”–Ŝ–š–

Этот прием со слешами использует «магические методы» Python. Объект класса


ƒ–Š может немного рассказать о себе:
ʴʴʴˆ‹Ž‡ɏ’ƒ–ŠŜƒ‡
ɐ•‘”–Ŝ–š–ɐ
ʴʴʴˆ‹Ž‡ɏ’ƒ–ŠŜ•—ˆˆ‹š
ɐŜ–š–ɐ
ʴʴʴˆ‹Ž‡ɏ’ƒ–ŠŜ•–‡
ɐ•‘”–ɐ

Вы можете передать переменную ˆ‹Ž‡ɏ’ƒ–Š в функцию ‘’‡ſƀ, как и любое имя


файла или строку пути.
Вы также можете увидеть, что случится, если запустить эту программу в другой
операционной системе или если вам нужно сгенерировать внешние пути на своем
компьютере:
ʴʴʴˆ”‘’ƒ–ŠŽ‹„‹’‘”–—”‡‹†‘™•ƒ–Š
ʴʴʴ—”‡‹†‘™•ƒ–Šſˆ‹Ž‡ɏ’ƒ–Šƀ
—”‡‹†‘™•ƒ–Šſɐ‡‡ŵ—”ŵ•‘”–Ŝ–š–ɐƀ
ʴʴʴ’”‹–ſ—”‡‹†‘™•ƒ–Šſˆ‹Ž‡ɏ’ƒ–Šƀƀ
‡‡Ɏ—”Ɏ•‘”–Ŝ–š–

Для получения более подробной информации обратитесь к документации (KWWSV


GRFVS\WKRQRUJOLEUDU\SDWKOLEKWPO).

%\WHV,2Ȑ6WULQJ,2
Вы уже знаете, как изменять данные в памяти и как получать данные из файлов,
а также записывать их внутрь. Но что делать в ситуации, когда у вас есть данные
в памяти, но вам нужно вызвать функцию, которая ожидает в качестве параметра
файл (или наоборот)? Вам понадобится изменить данные и передать эти байты или
символы, не создавая временных файлов.
Вы можете применить ‹‘Ŝ›–‡•  для бинарных данных (байтов) и ‹‘Ŝ–”‹‰ 
для текстовых данных (строк). И в том и в другом случае из данных будет создан
файлоподобный объект, который подойдет для всех функций работы с файлами,
рассмотренных в этой главе.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Одним из вариантов использования этих типов является преобразование фор-


мата данных. Поработаем, например, с библиотекой PIL (более подробно о ней вы
сможете прочитать в подразделе «PIL и Pillow» на с. 475), которая считывает и за-
писывает данные из изображения.
В качестве первого аргумента методов ‘’‡ſƀ и •ƒ˜‡ſƀ класса ƒ‰‡ ожидается
имя файла или файлоподобный объект. Код в примере 14.1 использует тип ›–‡• 
для того, чтобы считать и записать данные, лежащие в памяти. Он считывает один
или несколько файлов изображений из командной строки, преобразовывает дан-
ные из них в три разных формата и выводит длины и первые 10 байт полученного
результата.

ǷȘȐȔȍȘFRQYHUWBLPDJHS\
ˆ”‘‹‘‹’‘”–›–‡• 
ˆ”‘ ‹’‘”– ƒ‰‡
‹’‘”–•›•

†‡ˆ†ƒ–ƒɏ–‘ɏ‹‰ſ†ƒ–ƒƀś
ɑɑɑ‡–—”  ƒ‰‡‘„Œ‡ –ř™‹–Іƒ–ƒˆ”‘‹Ş‡‘”›ʳ†ƒ–ƒʴɑɑɑ
ˆ’ʰ›–‡• ſ†ƒ–ƒƀ
”‡–—” ƒ‰‡Ŝ‘’‡ſˆ’ƀɤȖȯȣȢȟȡȳșȦȫȦșȡȜșȜțȣȔȠȳȦȜ

†‡ˆ‹‰ɏ–‘ɏ†ƒ–ƒſ‹‰řˆ–ʰ‘‡ƀś
ɑɑɑ‡–—”‹ƒ‰‡†ƒ–ƒˆ”‘  ƒ‰‡ʳ‹‰ʴř‹ʳˆ–ʴˆ‘”ƒ–ɑɑɑ
ˆ’ʰ›–‡• ſƀ
‹ˆ‘–ˆ–ś
ˆ–ʰ‹‰Ŝˆ‘”ƒ–ɤȥȢȩȤȔȡȳșȦȢȤȜȗȜȡȔȟȰȡȯȝȨȢȤȠȔȦ
‹‰Ŝ•ƒ˜‡ſˆ’řˆ–ƀɤțȔȣȜȥȯȖȔșȦȖȣȔȠȳȦȰ
”‡–—”ˆ’Ŝ‰‡–˜ƒŽ—‡ſƀ

†‡ˆ ‘˜‡”–ɏ‹ƒ‰‡ſ†ƒ–ƒřˆ–ʰ‘‡ƀś
ɑɑɑ‘˜‡”–‹ƒ‰‡ʳ†ƒ–ƒʴ–‘ ʳˆ–ʴ‹ƒ‰‡†ƒ–ƒɑɑɑ
‹‰ʰ†ƒ–ƒɏ–‘ɏ‹‰ſ†ƒ–ƒƀ
”‡–—”‹‰ɏ–‘ɏ†ƒ–ƒſ‹‰řˆ–ƀ

†‡ˆ‰‡–ɏˆ‹Ž‡ɏ†ƒ–ƒſƒ‡ƀś
ɑɑɑ‡–—”  ƒ‰‡‘„Œ‡ –ˆ‘”‹ƒ‰‡ˆ‹Ž‡ʳƒ‡ʴɑɑɑ
‹‰ʰ ƒ‰‡Ŝ‘’‡ſƒ‡ƀ
’”‹–ſɑ‹‰ɑř‹‰ř‹‰Ŝˆ‘”ƒ–ƀ
”‡–—”‹‰ɏ–‘ɏ†ƒ–ƒſ‹‰ƀ

‹ˆɏɏƒ‡ɏɏʰʰɑɏɏƒ‹ɏɏɑś
ˆ‘”ƒ‡‹•›•Ŝƒ”‰˜ƃɨśƄś
†ƒ–ƒʰ‰‡–ɏˆ‹Ž‡ɏ†ƒ–ƒſƒ‡ƀ
’”‹–ſɑ‹ɑřއſ†ƒ–ƒƀř†ƒ–ƒƃśɨɥƄƀ
ˆ‘”ˆ–‹ſɑ‰‹ˆɑřɑ’‰ɑřɑŒ’‡‰ɑƀś
‘—–ɏ†ƒ–ƒʰ ‘˜‡”–ɏ‹ƒ‰‡ſ†ƒ–ƒřˆ–ƀ
’”‹–ſɑ‘—–ɑřއſ‘—–ɏ†ƒ–ƒƀř‘—–ɏ†ƒ–ƒƃśɨɥƄƀ
ǫȓȈȊȈǼȈȑȓȣȐȒȈȚȈȓȖȋȐ  

ǷȖșȒȖȓȤȒț ȖȉȢȍȒȚ %\WHV,2 ȊȍȌȍȚ șȍȉȧ ȒȈȒ ȜȈȑȓ Ȋȣ ȔȖȎȍȚȍ ȊȣȏȣȊȈȚȤ Ȍȓȧ ȕȍȋȖ
ȜțȕȒȞȐȐVHHN UHDG ȐZULWH ȚȈȒȎȍȒȈȒȐȌȓȧȖȉȣȟȕȖȋȖȜȈȑȓȈǭșȓȐȊȣȊȣȏȖ
ȊȍȚȍȜțȕȒȞȐȦVHHN ȈȏȈȚȍȔȜțȕȒȞȐȦUHDG ȚȖȗȖȓțȟȐȚȍȚȖȓȤȒȖȉȈȑȚȣȒȖȚȖȘȣȍ
ȕȈȝȖȌȧȚșȧȔȍȎȌțȚȍȒțȡȍȑȗȖȏȐȞȐȍȑȜȈȑȓȈȐȍȋȖȒȖȕȞȖȔǼțȕȒȞȐȧJHWYDOXH ȊȍȘȕȍȚ
ȊșȍȉȈȑȚȣȖȉȢȍȒȚȈ%\WHV,2

Перед вами полученные значения для изображения, которое вы увидите в гла-


ве 20:
ɛpython convert_image.py ch20_critter.png
‹‰ʳ Ŝ‰ ƒ‰‡Ž—‰‹Ŝ‰ ƒ‰‡ ‹Ž‡‹ƒ‰‡‘†‡ʰ •‹œ‡ʰɨɬɫšɨɫɨ
ƒ–ɥšɨɥɪɫɥ ɩɯʴ
‹ɩɫɰɫɨ„ɐɎɎšɯɰ ɎɎ”ɎɎɎɎšɨƒɎɎɎɎšɥɥɎɎšɥɥɐ
‘—–ɨɫɮɬɨ„ɐ ɯɮƒɎɎšɰƒɎɎšɥɥɎɎšɯ†ɎɎšɥɥɐ
‘—–ɩɫɰɫɨ„ɐɎɎšɯɰ ɎɎ”ɎɎɎɎšɨƒɎɎɎɎšɥɥɎɎšɥɥɐ
‘—–ɬɰɨɫ„ɐɎɎšˆˆɎš†ɯɎɎšˆˆɎɎš‡ɥɎɎšɥɥɎɎšɨɥ ɐ

ǿȐȚȈȑȚȍȌȈȓȍȍ
Следующая глава будет чуточку сложнее. В ней мы рассмотрим конкурентность
(способы выполнения нескольких операций одновременно) и процессы (запущен-
ные программы).

ǻȗȘȈȎȕȍȕȐȧ
14.1. Выведите на экран список всех файлов из текущего каталога.
14.2. Выведите на экран список всех файлов из родительского каталога.
14.3. Присвойте строку Š‹• is a test of the ‡‡”‰‡ › –‡š– •›•–‡ переменной –‡•–ɨ
и запишите эту переменную в файл с именем –‡•–Ŝ–š–.
14.4. Откройте файл –‡•–Ŝ–š– и считайте его содержимое в строку –‡•–ɩ. Будут ли
одинаковыми строки –‡•–ɨ и –‡•–ɩ?
ƋƓƈƊƈ
ǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣ
ȐȒȖȕȒțȘȍȕȚȕȖșȚȤ

Что может компьютер, но не может большинство


людей, — лежать на складе, запечатанным в коробке.
Джек Хэнди

Эта глава, а также две последующие — более сложные, чем остальные. Сейчас мы
рассмотрим данные во времени (последовательный и конкурентный доступ на од-
ном компьютере), в главе 16 поговорим о данных в коробке (хранение и извлечение
данных с помощью особых файлов и баз данных), а в главе 17 — о данных в про-
странстве (сети).

ǷȘȖȋȘȈȔȔȣȐȗȘȖȞȍșșȣ
Когда вы запускаете отдельную программу, ваша операционная система создает один
процесс, который использует системные ресурсы (центральный процессор, память,
место на диске) и структуры данных в ядре операционной системы (файлы и сетевые
соединения, статистику использования и т. д.). Процесс изолирован от других про-
цессов — он не может видеть, что делают другие процессы, или мешать им.
Операционная система отслеживает все запущенные процессы, выделяя каждому
из них немного времени и затем переключаясь на другие, для того чтобы справедли-
во распределять работу и реагировать на действия пользователя. Вы можете увидеть
состояние своих процессов с помощью графического интерфейса, такого как Mac’s
Activity Monitor в OS X, диспетчера задач в Windows или команды top в Linux.
Вы также можете получить доступ к данным процесса ваших собственных
программ. Модуль стандартной библиотеки os предоставляет общий способ до-
ступа к определенной системной информации. Например, следующие функции
получают идентификатор процесса и текущую рабочую папку запущенного ин-
терпретатора Python:
ʴʴʴ‹’‘”–‘•
ʴʴʴ‘•Ŝ‰‡–’‹†ſƀ
ɮɭɥɬɨ
ʴʴʴ‘•Ŝ‰‡– ™†ſƀ
ɐŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ɐ
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

А это — мои идентификаторы пользователя и группы:


ʴʴʴ‘•Ŝ‰‡–—‹†ſƀ
ɬɥɨ
ʴʴʴ‘•Ŝ‰‡–‰‹†ſƀ
ɩɥ

ǹȖȏȌȈȍȔȗȘȖȞȍșșșȗȖȔȖȡȤȦȔȖȌțȓȧVXESURFHVV
Все программы, с которыми вы сталкивались до этого момента, представляли
собой отдельные процессы. Запускать и останавливать другие существующие
в Python программы можно, используя модуль •—„’”‘ ‡•• из стандартной библио-
теки. Если вы хотите просто запустить другую программу в оболочке и получить
результат ее работы (как стандартный отчет, так и отчет об ошибках), используйте
функцию ‰‡–‘—–’—–ſƀ. В этом примере мы получим результат работы программы
†ƒ–‡ системы Unix:
ʴʴʴ‹’‘”–•—„’”‘ ‡••
ʴʴʴ”‡–ʰ•—„’”‘ ‡••Ŝ‰‡–‘—–’—–ſɐ†ƒ–‡ɐƀ
ʴʴʴ”‡–
ɐ—ƒ”ɪɥɩɩśɬɫśɪɮɩɥɨɫɐ

Вы не получите результат, пока процесс не завершится. Если вы хотите запу-


стить еще какую-нибудь программу или процесс, которые займут много времени,
обратитесь к разделу «Конкурентность» на с. 308. Поскольку аргументом функции
‰‡–‘—–’—–ſƀ является строка, представляющая собой команду оболочки, вы можете
включить в эту строку аргументы, каналы, перенаправление ввода/вывода и т. д.:
ʴʴʴ”‡–ʰ•—„’”‘ ‡••Ŝ‰‡–‘—–’—–ſɐ†ƒ–‡Ş—ɐƀ
ʴʴʴ”‡–
ɐ‘ƒ”ɪɨɥɪśɬɬśɥɨɩɥɨɫɐ

Передача строки-отчета команде ™ насчитывает одну строку, шесть «слов»


и 29 символов:
ʴʴʴ”‡–ʰ•—„’”‘ ‡••Ŝ‰‡–‘—–’—–ſɐ†ƒ–‡Ş—Ŷ™ ɐƀ
ʴʴʴ”‡–
ɐɨɭɩɰɐ

Метод Š‡ ɏ‘—–’—–ſƀ принимает список команд и аргументов. По умолчанию


он возвращает не строку, а объект типа bytes и не использует оболочку:
ʴʴʴ”‡–ʰ•—„’”‘ ‡••Ŝ Ї ɏ‘—–’—–ſƃɐ†ƒ–‡ɐřɐŞ—ɐƄƀ
ʴʴʴ”‡–
„ɐ‘ƒ”ɪɨɥɫśɥɨśɬɥɩɥɨɫɎɐ

Чтобы показать статус завершения другой программы, используйте функцию


‰‡–•–ƒ–—•‘—–’—–ſƀ, которая возвращает кортеж с кодом статуса и результатом ра-
боты:
ʴʴʴ”‡–ʰ•—„’”‘ ‡••Ŝ‰‡–•–ƒ–—•‘—–’—–ſɐ†ƒ–‡ɐƀ
ʴʴʴ”‡–
ſɥřɐƒ– ƒɨɯɩɨśɪɭśɩɪɩɥɨɫɐƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

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


функцию ƒŽŽſƀ:
ʴʴʴ”‡–ʰ•—„’”‘ ‡••Ŝ ƒŽŽſɐ†ƒ–‡ɐƀ
ƒ– ƒɨɯɩɨśɪɪśɨɨɩɥɨɫ
ʴʴʴ”‡–
ɥ

(В системах семейства Unix ɥ обычно является статусом, сигнализирующим об


успехе.)
Эти дата и время были выведены на экран, но не получены нашей программой.
Поэтому мы сохраняем код возврата как ret.
Запускать программы с аргументами можно двумя способами. Первый заклю-
чается в том, чтобы разместить аргументы в одной строке. Для примера возьмем
команду †ƒ–‡ Ş—, которая выводит на экран дату и время в UTC (о UTC мы погово-
рим немного позже):
ʴʴʴ”‡–ʰ•—„’”‘ ‡••Ŝ ƒŽŽſɐ†ƒ–‡Ş—ɐř•Š‡ŽŽʰ”—‡ƀ
—‡ ƒɩɨɥɫśɫɥśɥɫɩɥɨɫ

Вам нужно использовать •Š‡ŽŽʰ”—‡, чтобы распознать команду †ƒ–‡ Ş—, разбив
ее на отдельные строки и, возможно, развернув любые символы подстановки, такие
как * (в нашем примере мы их не использовали).
Второй метод создает список аргументов, поэтому нет необходимости вызывать
оболочку:
ʴʴʴ”‡–ʰ•—„’”‘ ‡••Ŝ ƒŽŽſƃɐ†ƒ–‡ɐřɐŞ—ɐƄƀ
—‡ ƒɩɨɥɫśɫɨśɬɰɩɥɨɫ

ǹȖȏȌȈȍȔȗȘȖȞȍșș
șȗȖȔȖȡȤȦȔȖȌțȓȧPXOWLSURFHVVLQJ
Запустить функцию Python как отдельный процесс или даже создать несколько
независимых процессов можно с помощью модуля —Ž–‹’”‘ ‡••‹‰. Рассмотрим
короткий и простой пример 15.1. Сохраните его под именем ’Ŝ’›, а затем запустите,
введя команду python ’Ŝ’›:

ǷȘȐȔȍȘPSS\
‹’‘”–—Ž–‹’”‘ ‡••‹‰
‹’‘”–‘•

†‡ˆ™Š‘ƒ‹ſ™Šƒ–ƀś
’”‹–ſɑ”‘ ‡••ʩ••ƒ›•śʩ•ɑʩſ‘•Ŝ‰‡–’‹†ſƀř™Šƒ–ƀƀ

‹ˆɏɏƒ‡ɏɏʰʰɑɏɏƒ‹ɏɏɑś
™Š‘ƒ‹ſɑ ɐ–Їƒ‹’”‘‰”ƒɑƀ
ˆ‘”‹”ƒ‰‡ſɫƀś
’ʰ—Ž–‹’”‘ ‡••‹‰Ŝ”‘ ‡••ſ–ƒ”‰‡–ʰ†‘ɏ–Š‹•ř
ƒ”‰•ʰſɑ ɐˆ— –‹‘ʩ•ɑʩřƀƀ
’Ŝ•–ƒ”–ſƀ
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

Когда я запускаю этот пример, то вижу на экране следующее:


”‘ ‡••ɭɩɩɫ•ƒ›•ś ɐ–Їƒ‹’”‘‰”ƒ
”‘ ‡••ɭɩɩɬ•ƒ›•ś ɐˆ— –‹‘ɥ
”‘ ‡••ɭɩɩɭ•ƒ›•ś ɐˆ— –‹‘ɨ
”‘ ‡••ɭɩɩɮ•ƒ›•ś ɐˆ— –‹‘ɩ
”‘ ‡••ɭɩɩɯ•ƒ›•ś ɐˆ— –‹‘ɪ

Функция ”‘ ‡••ſƀ вызвала новый процесс и запустила в нем функцию †‘ɏ–Š‹•ſƀ.
Поскольку мы делали это в цикле с четырьмя итерациями, сгенерировалось четыре
новых процесса, которые выполнили †‘ɏ–Š‹•ſƀ и завершились.
У модуля —Ž–‹’”‘ ‡••‹‰ есть много возможностей. Он прекрасно подходит для
тех случаев, когда в целях экономии времени нужно распределить какие-то задачи
между несколькими процессами: это может быть, например, загрузка веб-страницы,
изменение размера изображений или что-то другое. В модуле содержатся способы
постановки задач в очередь, включения взаимодействия между процессами и ожи-
дания завершения всех процессов.
В разделе «Конкурентность» на с. 308 содержится более подробная информация.

ǻȉȐȊȈȍȔȗȘȖȞȍșșȐșȗȖȓȤȏțȧȜțȕȒȞȐȦWHUPLQDWH
Если вы создали один или несколько процессов, а теперь по какой-то причине
хотите их завершить (возможно, они зависли в цикле или же вам стало скучно,
а может, просто захотелось побыть жестоким правителем), используйте функцию
–‡”‹ƒ–‡ſƀ. В примере 15.2 процесс должен досчитать до миллиона, замирая по-
сле каждого шага на секунду и выводя раздражающее сообщение. Однако у нашей
основной программы заканчивается терпение, и она сбивает его с орбиты:

ǷȘȐȔȍȘPSS\
‹’‘”–—Ž–‹’”‘ ‡••‹‰
‹’‘”––‹‡
‹’‘”–‘•

†‡ˆ™Š‘ƒ‹ſƒ‡ƀś
’”‹–ſɑ ɐʩ•ř‹’”‘ ‡••ʩ•ɑʩſƒ‡ř‘•Ŝ‰‡–’‹†ſƀƀƀ

†‡ˆŽ‘‘’›ſƒ‡ƀś
™Š‘ƒ‹ſƒ‡ƀ
•–ƒ”–ʰɨ
•–‘’ʰɨɥɥɥɥɥɥ
ˆ‘”—‹”ƒ‰‡ſ•–ƒ”–ř•–‘’ƀś
’”‹–ſɑɎ–—„‡”ʩ•‘ˆʩ•Ŝ ‘Šɑʩſ—ř•–‘’ƀƀ
–‹‡Ŝ•އ‡’ſɨƀ

‹ˆɏɏƒ‡ɏɏʰʰɑɏɏƒ‹ɏɏɑś
™Š‘ƒ‹ſɑƒ‹ɑƀ
’ʰ—Ž–‹’”‘ ‡••‹‰Ŝ”‘ ‡••ſ–ƒ”‰‡–ʰŽ‘‘’›řƒ”‰•ʰſɑŽ‘‘’›ɑřƀƀ
’Ŝ•–ƒ”–ſƀ
–‹‡Ŝ•އ‡’ſɬƀ
’Ŝ–‡”‹ƒ–‡ſƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Когда я запускаю эту программу, я вижу следующее:


ɐƒ‹ř‹’”‘ ‡••ɰɮɥɯɥ
ɐŽ‘‘’›ř‹’”‘ ‡••ɰɮɥɯɨ
—„‡”ɨ‘ˆɨɥɥɥɥɥɥŜ ‘Š
—„‡”ɩ‘ˆɨɥɥɥɥɥɥŜ ‘Š
—„‡”ɪ‘ˆɨɥɥɥɥɥɥŜ ‘Š
—„‡”ɫ‘ˆɨɥɥɥɥɥɥŜ ‘Š
—„‡”ɬ‘ˆɨɥɥɥɥɥɥŜ ‘Š

ǷȖȓțȟȈȍȔșȐșȚȍȔȕțȦȐȕȜȖȘȔȈȞȐȦ
șȗȖȔȖȡȤȦȔȖȌțȓȧRV
Стандартный пакет os предоставляет подробную информацию о вашей системе
и позволяет управлять некоторыми функциями, запуская скрипт, написанный на
Python, от лица привилегированного пользователя (например, администратора).
Помимо функций файлов и каталогов, которые мы рассмотрели в главе 14, в нем
есть такие информационные функции (они запускаются на iMac):
ʴʴʴ‹’‘”–‘•
ʴʴʴ‘•Ŝ—ƒ‡ſƀ
’‘•‹šŜ—ƒ‡ɏ”‡•—Ž–ſ•›•ƒ‡ʰɐƒ”™‹ɐř
‘†‡ƒ‡ʰɐ‹ƒ ŜŽ‘ ƒŽɐř
”‡Ž‡ƒ•‡ʰɐɨɯŜɬŜɥɐř
˜‡”•‹‘ʰɐƒ”™‹‡”‡Ž‡”•‹‘ɨɯŜɬŜɥś‘ƒ”ɨɨɩɥśɫɥśɪɩɩɥɨɰŚ
”‘‘–śš—ŞɫɰɥɪŜɩɬɨŜɪɌɪŵɏɯɭɏɭɫɐř
ƒ Š‹‡ʰɐšɯɭɏɭɫɐƀ
ʴʴʴ‘•Ŝ‰‡–Ž‘ƒ†ƒ˜‰ſƀ
ſɨŜɮɰɫɰɩɨɯɮɬřɨŜɰɪɨɨɬɩɪɫɪɮɬřɩŜɩɬɯɮɯɰɥɭɩɬƀ
ʴʴʴ‘•Ŝ ’—ɏ ‘—–ſƀ
ɫ

Имеется также полезная функция •›•–‡ſƀ, которая выполняет командную стро-


ку так, как если бы вы ввели ее в консоли:
ʴʴʴ‹’‘”–‘•
ʴʴʴ‘•Ŝ•›•–‡ſɐ†ƒ–‡ŷ—ɐƀ
—‡’”ɪɥɨɪśɨɥśɥɰɩɥɨɰ
ɥ
В этом пакете много полезного. Обратитесь к документации (KWWSVGRFVS\WKRQRUJ
OLEUDU\RVKWPO), чтобы узнать все самое интересное.

ǷȖȓțȟȈȍȔȐȕȜȖȘȔȈȞȐȦȖȗȘȖȞȍșșȈȝ
șȗȖȔȖȡȤȦȔȖȌțȓȧSVXWLO
Сторонний пакет psutil (KWWSVJLWKXEFRPJLDPSDRORSVXWLO) также предоставляет инфор-
мацию о системе и процессах для ОС Linux, Unix, macOS, и Windows.
Нетрудно догадаться, как он устанавливается:
ɛpip install psutil
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

В нем содержатся следующие разделы:


‰Система. ЦП, память, диск, сеть, сенсоры.
‰Процессы. Идентификатор, родительский идентификатор, ЦП, память, открытые
файлы, потоки.
Мы уже видели (в разделе, посвященном пакету os), что мой компьютер имеет
четыре процессора. Сколько времени (в секундах) они использовали?
ʴʴʴ‹’‘”–’•—–‹Ž
ʴʴʴ’•—–‹ŽŜ ’—ɏ–‹‡•ſ”—‡ƀ
ƃ• ’—–‹‡•ſ—•‡”ʰɭɩɪɥɭŜɫɰř‹ ‡ʰɥŜɥř•›•–‡ʰɨɰɯɮɩŜɮɨř‹†Ž‡ʰɩɬɭɥɰɮŜɭɫƀř
• ’—–‹‡•ſ—•‡”ʰɨɰɰɩɯŜɪř‹ ‡ʰɥŜɥř•›•–‡ʰɭɰɪɫŜɩɰř‹†Ž‡ʰɪɨɨɫɥɮŜɩɯƀř
• ’—–‹‡•ſ—•‡”ʰɬɮɪɨɨŜɫɨř‹ ‡ʰɥŜɥř•›•–‡ʰɨɬɫɮɩŜɰɰř‹†Ž‡ʰɩɭɬɫɯɬŜɬɭƀř
• ’—–‹‡•ſ—•‡”ʰɨɫɪɰɰŜɫɰř‹ ‡ʰɥŜɥř•›•–‡ʰɫɯɫɯŜɯɫř‹†Ž‡ʰɪɨɰɥɨɮŜɯɮƀƄ

Насколько они заняты сейчас?


ʴʴʴ‹’‘”–’•—–‹Ž
ʴʴʴ’•—–‹ŽŜ ’—ɏ’‡” ‡–ſ”—‡ƀ
ɩɭŜɨ
ʴʴʴ’•—–‹ŽŜ ’—ɏ’‡” ‡–ſ’‡” ’—ʰ”—‡ƀ
ƃɪɰŜɮřɨɭŜɩřɬɥŜɬřɭŜɥƄ

Вам, возможно, никогда не понадобятся подобные данные, но всегда полезно


знать, как их можно получить.

ǨȊȚȖȔȈȚȐȏȈȞȐȧȒȖȔȈȕȌ
Вы часто выполняете команды из оболочки (вводя их вручную или запуская скрип-
ты оболочки). Однако в Python имеется несколько качественных сторонних инстру-
ментов для управления запуском. Связанная с этим тема — очереди задач — рассма-
тривается в подразделе «Очереди» на с. 309.

,QYRNH
Первая версия инструмента ˆƒ„”‹ позволяет вам определить локальные и удален-
ные (сетевые) задачи в коде Python. Разработчик разбил этот пакет на ˆƒ„”‹ ɩ (для
удаленных задач) и ‹˜‘‡ (для локальных задач).
Вы можете установить ‹˜‘‡ с помощью следующей команды:
ɛpip install invoke

Одним из вариантов использования пакета ‹˜‘‡ является возможность сделать


функции доступными в качестве аргументов командной строки. Давайте создадим
файл –ƒ••Ŝ’›, который содержит строки, показанные в примере 15.3.

ǷȘȐȔȍȘWDVNVS\
ˆ”‘‹˜‘‡‹’‘”––ƒ•

ɒ–ƒ•
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

†‡ˆ›–‹‡ſ –šƀś
‹’‘”––‹‡
‘™ʰ–‹‡Ŝ–‹‡ſƀ
–‹‡ɏ•–”ʰ–‹‡Ŝƒ• –‹‡ſ–‹‡ŜŽ‘ ƒŽ–‹‡ſ‘™ƀƀ
’”‹–ſɑ‘ ƒŽ–‹‡‹•ɑř–‹‡•–”ƀ

(Аргумент –š — первый аргумент для каждой преобразуемой функции, но ис-


пользуется он только самим пакетом ‹˜‘‡. Неважно, с каким именем, но этот
аргумент там должен быть.)
ɛinvoke mytime
‘ ƒŽ–‹‡‹•Š—ƒ›ɩɨɪśɨɭśɩɪɩɥɨɰ

Используйте аргументы –l или –list, чтобы увидеть, какие задачи доступны:


ɛinvoke –l
˜ƒ‹Žƒ„އ–ƒ••ś

›–‹‡

Задачи могут иметь аргументы, и вы можете вызвать из командной строки не-


сколько задач одновременно (аналогично использованию оператора ĺĺ в командной
строке).
Другие варианты использования:
‰запуск локальных скриптов оболочки с помощью функции run;
‰ответ на возвращаемые другими программами строковые шаблоны.
Этот пакет мы рассмотрели поверхностно. Для получения более подробной ин-
формации обратитесь к документации (KWWSGRFVS\LQYRNHRUJHQVWDEOH).

ǬȘțȋȐȍȊșȗȖȔȖȋȈȚȍȓȤȕȣȍȔȍȚȖȌȣȌȓȧȒȖȔȈȕȌ
Следующие пакеты немного похожи на ‹˜‘‡, но в определенных ситуациях лучшее
решение может предложить один из таких пакетов:
‰click (KWWSVFOLFNSDOOHWVSURMHFWVFRPHQ[);
‰doit (KWWSVS\GRLWRUJ);
‰sh (KWWSDPRIIDWJLWKXELRVK);
‰delegator (KWWSVJLWKXEFRPDPLWWGHOHJDWRUS\);
‰pypeln (KWWSVFJDUFLDHJLWKXELRS\SHOQ).

DzȖȕȒțȘȍȕȚȕȖșȚȤ
Официальный сайт Python рассматривает тему конкурентности в целом и с точки
зрения стандартной библиотеки (KWWSELWO\FRQFXUOLE). На страницах сайта содержит-
ся множество ссылок на различные пакеты и приемы, а я в этой главе остановлюсь
на самых полезных пакетах.
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

Когда речь идет о компьютерах, находиться в ожидании приходится по одной


из двух причин:
‰из-за ограничения ввода-вывода. Это наиболее распространенная причина. Про-
цессоры компьютеров безумно быстры — в сотни раз быстрее, чем компьютерная
память, и в тысячи — чем диски или сети;
‰из-за ограничения процессора. Это случается при выполнении таких объемных
задач, как научные или графические расчеты.
С конкурентностью связаны еще два термина:
‰синхронность — одна вещь следует за другой, как гусята, семенящие за родителями;
‰асинхронность — задачи независимы, как гуси, которые плавают в пруду.
По мере того как от простых систем и задач вы будете переходить к проблемам
реальной жизни, вам все чаще придется иметь дело с конкурентностью. Возьмем,
например, сайт. Обычно вы можете довольно быстро предоставлять веб-клиентам
статическую и динамическую страницы. Если ожидание длится долю секунды,
приложение считается интерактивным, однако если время до отображения или
взаимодействия более продолжительное, люди становятся нетерпеливыми. Тесты,
проведенные компаниями Google и Amazon, показали, что трафик быстро падает,
если страница загружается хотя бы немного медленнее обычного.
Ну а если вы не можете повлиять на то, что долго выполняется? Например, на
загрузку файла на сервер, на изменение размеров изображения или запрос к базе
данных? Вы больше не можете делать это при помощи синхронного кода вашего
веб-сервера, поскольку кто-то уже ждет.
Если вам нужно выполнить несколько задач как можно быстрее на одном ком-
пьютере, вы можете сделать их независимыми, и тогда медленные задачи не будут
блокировать остальные.
Ранее в этой главе было показано, как использовать многопроцессорную обра-
ботку для параллельной работы на одной машине. Если нужно, например, изменить
размер изображения, ваш веб-сервер может создать отдельный процесс для данной
задачи и запустить его асинхронно. Можно масштабировать приложение горизон-
тально, вызвав несколько процессов изменения размера.
Идея заключается в том, чтобы заставить их работать друг с другом. Наличие
любого общего элемента управления или состояния означает, что будут возникать
узкие места. Особый подход нужен для обработки ошибок, поскольку конкурентные
вычисления сложнее обычных. Многое может пойти не так, и ваши шансы на успех
будут ниже.
Какие же методы могут помочь справиться с этими сложностями? Начнем с хо-
рошего способа для управления несколькими задачами — это очереди.

ǶȟȍȘȍȌȐ
Очередь похожа на список: элементы добавляются с одного ее конца и удаляются
с другого. Часто такой принцип называют FIFO (first in, first out — «первым пришел,
первым ушел»).
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Представьте, что вы моете посуду. Если вы хотите совершить полный цикл,


вам нужно вымыть тарелку, высушить ее и отложить в сторону. Сделать это
можно несколькими способами. Можно вымыть, высушить и отложить первую
тарелку и повторить эти действия со второй и последующими тарелками. Или же
можно сгруппировать операции: сначала вымыть всю посуду, затем ее высушить
и отложить в сторону. При этом подразумевается, что в раковине и сушилке до-
статочно места, чтобы разместить там всю посуду на каждом этапе. Оба подхода
являются синхронными — один работник выполняет одно действие в любой
момент времени.
В качестве альтернативы вы могли бы найти одного-двух помощников. Пред-
положим, вы моете тарелку, передаете ее тому, кто тарелки сушит, а сушильщик
передаст тарелку тому, кто отложит ее в сторону. Если все работают в одном темпе,
вы должны закончить работу гораздо быстрее, чем если бы выполняли ее полностью
самостоятельно.
Но что, если вы моете посуду быстрее, чем сушильщик успевает с ней справ-
ляться? Тогда или вымытая посуда будет падать на пол, или вы будете складывать
ее между собой и сушильщиком. Есть вариант, что вы просто начнете что-нибудь
насвистывать до тех пор, пока сушильщик не примет от вас очередную тарелку.
А если последний помощник работает медленнее сушильщика, падать на пол или
накапливаться будет уже сухая посуда либо насвистывать начнет уже сушильщик.
Хоть у вас и есть несколько работников, но общая задача все еще синхронна и может
выполняться только со скоростью самого медленного работника.
«Берись дружно, не будет грузно» — гласит старая пословица. Увеличение коли-
чества работников поможет быстрее построить сарай или вымыть посуду. При этом
будут задействованы очереди.
В целом, очереди переносят сообщения, которые могут содержать любую
информацию. В данном случае нас интересуют очереди для распределенного
управления задачами, также известные как рабочие очереди или очереди за-
даний. Каждая тарелка из раковины выдается доступному мойщику: он ее моет
и передает первому доступному сушильщику. Тот, в свою очередь, отдает тарелку
первому доступному работнику, в чьи обязанности входит убрать ее в сторону.
Этот процесс может быть синхронным (работники сначала ждут, когда им дадут
тарелку, а потом ждут, когда освободится следующий в очереди работник) или
асинхронным (посуда поступает от работников с разной скоростью). Если у вас
есть достаточно работников и они трудятся в одном темпе, задача будет выполнена
гораздо быстрее.

ǷȘȖȞȍșșȣ
Реализовать очередь можно разными способами. Для одного компьютера модуль
стандартной библиотеки —Ž–‹’”‘ ‡••‹‰ (с которым вы ранее уже встречались)
содержит функцию —‡—‡. Смоделируем ситуацию только с одним мойщиком по-
суды и несколькими сушильщиками (кто-то позже отложит посуду в сторону)
и создадим промежуточную очередь †‹•Šɏ“—‡—‡. Назовем эту программу †‹•Ї•Ŝ’›
(пример 15.4).
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

ǷȘȐȔȍȘGLVKHVS\
‹’‘”–—Ž–‹’”‘ ‡••‹‰ƒ•’

†‡ˆ™ƒ•Ї”ſ†‹•Ї•ř‘—–’—–ƀś
ˆ‘”†‹•Š‹†‹•Ї•ś
’”‹–ſɐƒ•Š‹‰ɐř†‹•Šřɐ†‹•Šɐƀ
‘—–’—–Ŝ’—–ſ†‹•Šƀ

†‡ˆ†”›‡”ſ‹’—–ƀś
™Š‹Ž‡”—‡ś
†‹•Šʰ‹’—–Ŝ‰‡–ſƀ
’”‹–ſɐ”›‹‰ɐř†‹•Šřɐ†‹•Šɐƀ
‹’—–Ŝ–ƒ•ɏ†‘‡ſƀ

†‹•Šɏ“—‡—‡ʰ’Ŝ ‘‹ƒ„އ—‡—‡ſƀ
†”›‡”ɏ’”‘ ʰ’Ŝ”‘ ‡••ſ–ƒ”‰‡–ʰ†”›‡”řƒ”‰•ʰſ†‹•Šɏ“—‡—‡řƀƀ
†”›‡”ɏ’”‘ Ŝ†ƒ‡‘ʰ”—‡
†”›‡”ɏ’”‘ Ŝ•–ƒ”–ſƀ

†‹•Ї•ʰƃɐ•ƒŽƒ†ɐřɐ„”‡ƒ†ɐřɐ‡–”‡‡ɐřɐ†‡••‡”–ɐƄ
™ƒ•Ї”ſ†‹•Ї•ř†‹•Šɏ“—‡—‡ƀ
†‹•Šɏ“—‡—‡ŜŒ‘‹ſƀ

Запускаем нашу новую программу:


ɛpython [Link]
ƒ•Š‹‰•ƒŽƒ††‹•Š
ƒ•Š‹‰„”‡ƒ††‹•Š
ƒ•Š‹‰‡–”‡‡†‹•Š
ƒ•Š‹‰†‡••‡”–†‹•Š
”›‹‰•ƒŽƒ††‹•Š
”›‹‰„”‡ƒ††‹•Š
”›‹‰‡–”‡‡†‹•Š
”›‹‰†‡••‡”–†‹•Š

Эта очередь похожа на простой итератор, производящий наборы тарелок. В дей-


ствительности здесь создаются отдельные процессы, которые общаются между
собой. Я использовал ‘‹ƒ„އ—‡—‡ и финальный метод Œ‘‹ſƀ, чтобы сообщить
мойщику о том, что вся посуда высушена. У модуля —Ž–‹’”‘ ‡••‹‰ есть очереди
и других типов: узнать о них вы можете из документации (KWWSVGRFVS\WKRQRUJ
OLEUDU\PXOWLSURFHVVLQJKWPO).

ǷȖȚȖȒȐ
Поток запускается внутри процесса и имеет доступ ко всему, что находится в про-
цессе, — это можно сравнить с раздвоением личности. Модуль —Ž–‹’”‘ ‡••‹‰
имеет «кузена» по имени –Š”‡ƒ†‹‰, который использует потоки вместо процессов
(на самом деле модуль —Ž–‹’”‘ ‡••‹‰ был разработан позже своего собрата,
основанного на процессах). Переделаем наш пример с процессами для применения
потоков (пример 15.5).
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǷȘȐȔȍȘWKUHDGS\
‹’‘”––Š”‡ƒ†‹‰

†‡ˆ†‘ɏ–Š‹•ſ™Šƒ–ƀś
™Š‘ƒ‹ſ™Šƒ–ƀ

†‡ˆ™Š‘ƒ‹ſ™Šƒ–ƀś
’”‹–ſɑŠ”‡ƒ†ʩ••ƒ›•śʩ•ɑʩſ–Š”‡ƒ†‹‰Ŝ —””‡–ɏ–Š”‡ƒ†ſƀř™Šƒ–ƀƀ

‹ˆɏɏƒ‡ɏɏʰʰɑɏɏƒ‹ɏɏɑś
™Š‘ƒ‹ſɑ ɐ–Їƒ‹’”‘‰”ƒɑƀ
ˆ‘”‹”ƒ‰‡ſɫƀś
’ʰ–Š”‡ƒ†‹‰ŜŠ”‡ƒ†ſ–ƒ”‰‡–ʰ†‘ɏ–Š‹•ř
ƒ”‰•ʰſɑ ɐˆ— –‹‘ʩ•ɑʩřƀƀ
’Ŝ•–ƒ”–ſƀ

Вот что я вижу на своем экране:


Š”‡ƒ†ʳɏƒ‹Š”‡ƒ†ſƒ‹Š”‡ƒ†ř•–ƒ”–‡†ɨɫɥɮɪɬɩɥɮɪɫɭɰɭɥƀʴ•ƒ›•ś ɐ–Їƒ‹
’”‘‰”ƒ
Š”‡ƒ†ʳŠ”‡ƒ†ſŠ”‡ƒ†Şɨř•–ƒ”–‡†ɫɪɩɭɭɩɰɪɮɭƀʴ•ƒ›•ś ɐˆ— –‹‘ɥ
Š”‡ƒ†ʳŠ”‡ƒ†ſŠ”‡ƒ†Şɩř•–ƒ”–‡†ɫɪɫɩɨɬɮɪɨɩƀʴ•ƒ›•ś ɐˆ— –‹‘ɨ
Š”‡ƒ†ʳŠ”‡ƒ†ſŠ”‡ƒ†Şɪř•–ƒ”–‡†ɫɪɫɮɫɨɩɫɯɥƀʴ•ƒ›•ś ɐˆ— –‹‘ɩ
Š”‡ƒ†ʳŠ”‡ƒ†ſŠ”‡ƒ†Şɫř•–ƒ”–‡†ɫɪɫɩɨɬɮɪɨɩƀʴ•ƒ›•ś ɐˆ— –‹‘ɪ

Мы можем воспроизвести пример с посудой, основанный на процессах, используя


потоки (пример 15.6).

ǷȘȐȔȍȘWKUHDGBGLVKHVS\
‹’‘”––Š”‡ƒ†‹‰ř“—‡—‡
‹’‘”––‹‡

†‡ˆ™ƒ•Ї”ſ†‹•Ї•ř†‹•Šɏ“—‡—‡ƀś
ˆ‘”†‹•Š‹†‹•Ї•ś
’”‹–ſɑƒ•Š‹‰ɑř†‹•Šƀ
–‹‡Ŝ•އ‡’ſɬƀ
†‹•Šɏ“—‡—‡Ŝ’—–ſ†‹•Šƀ

†‡ˆ†”›‡”ſ†‹•Šɏ“—‡—‡ƀś
™Š‹Ž‡”—‡ś
†‹•Šʰ†‹•Šɏ“—‡—‡Ŝ‰‡–ſƀ
’”‹–ſɑ”›‹‰ɑř†‹•Šƀ
–‹‡Ŝ•އ‡’ſɨɥƀ
†‹•Šɏ“—‡—‡Ŝ–ƒ•ɏ†‘‡ſƀ

†‹•Šɏ“—‡—‡ʰ“—‡—‡Ŝ—‡—‡ſƀ
ˆ‘”‹”ƒ‰‡ſɩƀś
†”›‡”ɏ–Š”‡ƒ†ʰ–Š”‡ƒ†‹‰ŜŠ”‡ƒ†ſ–ƒ”‰‡–ʰ†”›‡”řƒ”‰•ʰſ†‹•Šɏ“—‡—‡řƀƀ
†”›‡”ɏ–Š”‡ƒ†Ŝ•–ƒ”–ſƀ

†‹•Ї•ʰƃɐ•ƒŽƒ†ɐřɐ„”‡ƒ†ɐřɐ‡–”‡‡ɐřɐ†‡•‡”–ɐƄ
™ƒ•Ї”ſ†‹•Ї•ř†‹•Šɏ“—‡—‡ƀ
†‹•Šɏ“—‡—‡ŜŒ‘‹ſƀ
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

Различие между модулями —Ž–‹’”‘ ‡••‹‰ и –Š”‡ƒ†‹‰ заключается в том, что


модуль –Š”‡ƒ†‹‰ не имеет функции –‡”‹ƒ–‡ſƀ. Не существует простого способа
завершить запущенный поток, поскольку это может вызвать разнообразные про-
блемы в коде и, возможно, даже в пространственно-временном континууме.
Потоки могут быть опасны. Как и управление памятью вручную в таких языках,
как С и С++, они могут вызвать появление ошибок, которые ужасно трудно найти
и исправить. Для того чтобы задействовать потоки, весь код программы — и код
внешних библиотек, которые он использует, — должен быть потокобезопасным.
В предыдущем примере кода потоки не имели дела с глобальными переменными,
поэтому могли работать независимо, ничего не разрушая.
Представьте, что вы исследуете паранормальную активность в доме с привиде-
ниями. Привидения скитаются по коридорам, но ни одно из них не знает о суще-
ствовании другого, и в любой момент каждое привидение может просматривать,
добавлять, удалять или перемещать любую вещь из домашней обстановки.
Вы настороженно идете по дому, снимая показания своими впечатляющими ин-
струментами. И внезапно замечаете, что подсвечник, мимо которого вы проходили
несколько секунд назад, пропал.
Содержимое дома похоже на переменные в программе. Привидения — это потоки
процесса (дома). Если бы привидения только просматривали содержимое дома, это
не было бы проблемой — как поток, который просто читает значение константы или
переменной, не пытаясь его изменить.
Однако некая невидимая сущность может схватить ваш фонарик, дунуть холод-
ной струей воздуха на вашу шею, рассыпать шарики на ступеньках или заставить
вспыхнуть огонь в камине. Особо утонченные привидения могут так изменить вещи
в других комнатах, что вы даже не заметите.
Несмотря на все ваши причудливые инструменты, вам будет очень трудно разо-
браться в том, кто, когда и как это сделал.
Если бы вместо потоков вы использовали несколько процессов, это можно
было бы сравнить с несколькими домами, в каждом из которых обитает только одно
(живое) существо. Если поставить бутылку бренди перед камином, через час она все
еще будет там. Возможно, немного жидкости испарится, но сама бутылка останется
на том же месте.
Потоки могут быть полезны и безопасны, когда речь не идет о глобальных дан-
ных. В частности, рекомендуется использовать потоки для экономии времени при
ожидании завершения некоторых операций ввода/вывода. В этом случае потокам
не нужно сражаться за данные, поскольку у каждого из них имеется свой набор
переменных.
Но у потоков иногда есть веские причины для изменения глобальных данных.
Фактически самая распространенная причина для использования нескольких пото-
ков — это возможность разделить между ними работу над определенными данными,
поэтому ожидается, что какие-то данные будут изменены.
Классический способ разделить данные безопасно — разместить программную
блокировку перед изменением переменной в потоке. Это позволит оградить ее зна-
чение от других потоков и внести свои изменения. В примере с домом вы бы просто
оставили бригаду охотников за привидениями в той комнате, которая должна остаться
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

свободной от привидений. Нужно лишь не забыть ее разблокировать. Блокировки


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

Ǫ3\WKRQȗȖȚȖȒȐȕȍțșȒȖȘȧȦȚȏȈȌȈȟȐșȊȧȏȈȕȕȣȍșȖȋȘȈȕȐȟȍȕȐȧȔȐȗȘȖȞȍșșȖȘȈȐȏȏȈ
ȖȌȕȖȑȌȍȚȈȓȐȘȍȈȓȐȏȈȞȐȐșȚȈȕȌȈȘȚȕȖȑșȐșȚȍȔȣ3\WKRQȒȖȚȖȘȈȧȕȈȏȣȊȈȍȚșȧ*OREDO
,QWHUSUHWHU/RFN *,/ ǶȕȈȗȘȍȌȕȈȏȕȈȟȍȕȈȌȓȧȚȖȋȖȟȚȖȉȣȐȏȉȍȎȈȚȤȗȖȚȖȒȖȊȣȝȗȘȖ
ȉȓȍȔȊȐȕȚȍȘȗȘȍȚȈȚȖȘȍ3\WKRQȐȌȍȑșȚȊȐȚȍȓȤȕȖȔȖȎȍȚȏȈȔȍȌȓȐȚȤȔȕȖȋȖȗȖȚȖȟȕțȦ
ȗȘȖȋȘȈȔȔțȗȖșȘȈȊȕȍȕȐȦșȖȌȕȖȗȖȚȖȟȕȖȑȐȓȐȌȈȎȍȔȕȖȋȖȗȘȖȞȍșșȖȘȕȖȑȊȍȘșȐȍȑ

Итак, для Python рекомендации следующие:


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

&RQFXUUHQWIXWXUHV
Как вы только что видели, использование потоков или нескольких процессов тре-
бует отслеживания большого количества деталей. Модуль ‘ —””‡–Ŝˆ—–—”‡• был
добавлен в стандартную библиотеку в версии Python 3.2 для того, чтобы упростить
эту задачу. Он позволяет вам спроектировать асинхронный пул так называемых
работников с помощью потоков (с ограничением по вводу-выводу) и процессов
(с ограничением по ЦП). Вы получаете объект типа future, который позволяет от-
слеживать состояние заданий и собирать результаты работы.
В примере 15.7 вы видите тестовую программу, которую можно сохранить под
именем ˆŜ’›. Функция-задача ƒŽ ſƀ спит в течение одной секунды (наш способ
симулировать бурную деятельность), вычисляет квадратный корень своего аргу-
мента и возвращает его. Программа принимает необязательный аргумент командной
строки — количество работников, которых следует задействовать (по умолчанию ŷɪ),
запускает заданное количество из пула потоков, затем из пула процессов, а затем вы-
водит на экран затраченное время. Список values содержит пять чисел, отправленных
функции ƒŽ ſƀ по одному с помощью работника-потока или работника-процесса.

ǷȘȐȔȍȘFIS\
ˆ”‘ ‘ —””‡–‹’‘”–ˆ—–—”‡•
‹’‘”–ƒ–Š
‹’‘”––‹‡
‹’‘”–•›•

†‡ˆ ƒŽ ſ˜ƒŽƀś
–‹‡Ŝ•އ‡’ſɨƀ
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

”‡•—Ž–ʰƒ–ŠŜ•“”–ſˆŽ‘ƒ–ſ˜ƒŽƀƀ
”‡–—””‡•—Ž–

†‡ˆ—•‡ɏ–Š”‡ƒ†•ſ—ř˜ƒŽ—‡•ƀś
–ɨʰ–‹‡Ŝ–‹‡ſƀ
™‹–Šˆ—–—”‡•ŜŠ”‡ƒ†‘‘Žš‡ —–‘”ſ—ƀƒ•–‡šś
”‡•—Ž–•ʰ–‡šŜƒ’ſ ƒŽ ř˜ƒŽ—‡•ƀ
–ɩʰ–‹‡Ŝ–‹‡ſƀ
”‡–—”–ɩŷ–ɨ

†‡ˆ—•‡ɏ’”‘ ‡••‡•ſ—ř˜ƒŽ—‡•ƀś
–ɨʰ–‹‡Ŝ–‹‡ſƀ
™‹–Šˆ—–—”‡•Ŝ”‘ ‡••‘‘Žš‡ —–‘”ſ—ƀƒ•’‡šś
”‡•—Ž–•ʰ’‡šŜƒ’ſ ƒŽ ř˜ƒŽ—‡•ƀ
–ɩʰ–‹‡Ŝ–‹‡ſƀ
”‡–—”–ɩŷ–ɨ

†‡ˆƒ‹ſ™‘”‡”•ř˜ƒŽ—‡•ƀś
’”‹–ſˆɑ•‹‰Ƈ™‘”‡”•ƈ™‘”‡”•ˆ‘”Ƈއſ˜ƒŽ—‡•ƀƈ˜ƒŽ—‡•ɑƀ
–ɏ•‡ ʰ—•‡ɏ–Š”‡ƒ†•ſ™‘”‡”•ř˜ƒŽ—‡•ƀ
’”‹–ſˆɑŠ”‡ƒ†•–‘‘Ƈ–ɏ•‡ śŜɫˆƈ•‡ ‘†•ɑƀ
’ɏ•‡ ʰ—•‡ɏ’”‘ ‡••‡•ſ™‘”‡”•ř˜ƒŽ—‡•ƀ
’”‹–ſˆɑ”‘ ‡••‡•–‘‘Ƈ’ɏ•‡ śŜɫˆƈ•‡ ‘†•ɑƀ

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
™‘”‡”•ʰ‹–ſ•›•Ŝƒ”‰˜ƃɨƄƀ
˜ƒŽ—‡•ʰŽ‹•–ſ”ƒ‰‡ſɨřɭƀƀɤɨŜŜɬ
ƒ‹ſ™‘”‡”•ř˜ƒŽ—‡•ƀ

Я получил следующие результаты:


$ python [Link] 1
•‹‰ɨ™‘”‡”•ˆ‘”ɬ˜ƒŽ—‡•
Š”‡ƒ†•–‘‘ɬŜɥɮɪɭ•‡ ‘†•
”‘ ‡••‡•–‘‘ɬŜɬɪɰɬ•‡ ‘†•
$ python [Link] 3
•‹‰ɪ™‘”‡”•ˆ‘”ɬ˜ƒŽ—‡•
Š”‡ƒ†•–‘‘ɩŜɥɥɫɥ•‡ ‘†•
”‘ ‡••‡•–‘‘ɩŜɥɪɬɨ•‡ ‘†•
$ python [Link] 5
•‹‰ɬ™‘”‡”•ˆ‘”ɬ˜ƒŽ—‡•
Š”‡ƒ†•–‘‘ɨŜɥɥɬɩ•‡ ‘†•
”‘ ‡••‡•–‘‘ɨŜɥɫɫɫ•‡ ‘†•

Вызов функции •Ž‡‡’ſƀ заставил каждого работника потратить секунду на каж-


дое вычисление.
‰Если мы задействуем всего одного работника, вычисления выполнятся последо-
вательно, а общее время составит более пяти секунд.
‰Если мы задействуем пять работников, то их количество совпадет с количеством
проверяемых значений, поэтому программа будет выполняться чуть дольше чем
одну секунду.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰Если мы задействуем трех работников, нам понадобятся два запуска, чтобы об-
работать все пять значений, поэтому пройдет всего две секунды.
В программе я проигнорировал реальные результаты (рассчитанные нами ква-
дратные корни) для того, чтобы сделать акцент на затраченном времени. Важно
отметить, что использование функции ƒ’ſƀ для определения пула заставит нас
дожидаться выполнения действий всех работников перед тем, как возвращать
результаты. Если вы хотите получать каждый отдельный результат по завер-
шении работы, создайте еще одну тестовую программу (назовем ее ˆɩŜ’› ),
в которой каждый работник будет возвращать значения по мере их вычисления
(пример 15.8).

ǷȘȐȔȍȘFIS\
ˆ”‘ ‘ —””‡–‹’‘”–ˆ—–—”‡•
‹’‘”–ƒ–Š
‹’‘”–•›•

†‡ˆ ƒŽ ſ˜ƒŽƀś
”‡•—Ž–ʰƒ–ŠŜ•“”–ſˆŽ‘ƒ–ſ˜ƒŽƀƀ
”‡–—”˜ƒŽř”‡•—Ž–

†‡ˆ—•‡ɏ–Š”‡ƒ†•ſ—ř˜ƒŽ—‡•ƀś
™‹–Šˆ—–—”‡•ŜŠ”‡ƒ†‘‘Žš‡ —–‘”ſ—ƀƒ•–‡šś
–ƒ••ʰƃ–‡šŜ•—„‹–ſ ƒŽ ř˜ƒŽ—‡ƀˆ‘”˜ƒŽ—‡‹˜ƒŽ—‡•Ƅ
ˆ‘”ˆ‹ˆ—–—”‡•Ŝƒ•ɏ ‘’އ–‡†ſ–ƒ••ƀś
›‹‡Ž†ˆŜ”‡•—Ž–ſƀ

†‡ˆ—•‡ɏ’”‘ ‡••‡•ſ—ř˜ƒŽ—‡•ƀś
™‹–Šˆ—–—”‡•Ŝ”‘ ‡••‘‘Žš‡ —–‘”ſ—ƀƒ•’‡šś
–ƒ••ʰƃ’‡šŜ•—„‹–ſ ƒŽ ř˜ƒŽ—‡ƀˆ‘”˜ƒŽ—‡‹˜ƒŽ—‡•Ƅ
ˆ‘”ˆ‹ˆ—–—”‡•Ŝƒ•ɏ ‘’އ–‡†ſ–ƒ••ƀś
›‹‡Ž†ˆŜ”‡•—Ž–ſƀ

†‡ˆƒ‹ſ™‘”‡”•ř˜ƒŽ—‡•ƀś
’”‹–ſˆɑ•‹‰Ƈ™‘”‡”•ƈ™‘”‡”•ˆ‘”Ƈއſ˜ƒŽ—‡•ƀƈ˜ƒŽ—‡•ɑƀ
’”‹–ſɑ•‹‰–Š”‡ƒ†•śɑƀ
ˆ‘”˜ƒŽř”‡•—Ž–‹—•‡ɏ–Š”‡ƒ†•ſ™‘”‡”•ř˜ƒŽ—‡•ƀś
’”‹–ſˆɐƇ˜ƒŽƈƇ”‡•—Ž–śŜɫˆƈɐƀ
’”‹–ſɑ•‹‰’”‘ ‡••‡•śɑƀ
ˆ‘”˜ƒŽř”‡•—Ž–‹—•‡ɏ’”‘ ‡••‡•ſ™‘”‡”•ř˜ƒŽ—‡•ƀś
’”‹–ſˆɐƇ˜ƒŽƈƇ”‡•—Ž–śŜɫˆƈɐƀ

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
™‘”‡”•ʰɪ
‹ˆއſ•›•Ŝƒ”‰˜ƀʴɨś
™‘”‡”•ʰ‹–ſ•›•Ŝƒ”‰˜ƃɨƄƀ
˜ƒŽ—‡•ʰŽ‹•–ſ”ƒ‰‡ſɨřɭƀƀɤɨŜŜɬ
ƒ‹ſ™‘”‡”•ř˜ƒŽ—‡•ƀ
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

Наши функции —•‡ɏ–Š”‡ƒ†•ſƀ и —•‡ɏ’”‘ ‡••‡•ſƀ теперь являются функциями-


генераторами, которые вызывают ›‹‡Ž† для того, чтобы вернуть значение на каждой
итерации. По результатам одного запуска на моей машине вы можете увидеть, что
работники не всегда выполняют задачи в порядке от 1 до 5:
$ python [Link] 5
•‹‰ɬ™‘”‡”•ˆ‘”ɬ˜ƒŽ—‡•
•‹‰–Š”‡ƒ†•ś
ɪɨŜɮɪɩɨ
ɨɨŜɥɥɥɥ
ɩɨŜɫɨɫɩ
ɫɩŜɥɥɥɥ
ɬɩŜɩɪɭɨ
•‹‰’”‘ ‡••‡•ś
ɨɨŜɥɥɥɥ
ɩɨŜɫɨɫɩ
ɪɨŜɮɪɩɨ
ɫɩŜɥɥɥɥ
ɬɩŜɩɪɭɨ

Вы можете использовать модуль ‘ —””‡–Ŝˆ—–—”‡• всякий раз, когда вам нужно


запустить несколько конкурирующих задач, например таких, как:
‰поиск (crawling) URL в Интернете;
‰обработка файлов, например изменение размера изображений;
‰вызов API какой-либо службы.
Как обычно, в документации (KWWSVGRFVS\WKRQRUJOLEUDU\FRQFXUUHQWIXWXUHVKWPO) вы
можете найти дополнительную информацию с большим количеством технических
деталей.

ǯȍȓȍȕȣȍȗȖȚȖȒȐȐJHYHQW
Как вы уже видели, разработчики стремятся избежать медленных мест в програм-
мах, запуская их в отдельных потоках или процессах. Примером такого дизайна
является веб-сервер Apache.
Альтернативой является программирование, основанное на событиях (event-
based programming). Программа, основанная на событиях, запускает центральный
цикл обработки событий, раздает задачи и повторяет цикл. Так устроен веб-сервер
NGINX, работающий быстрее, чем Apache.
Библиотека gevent основана на событиях и позволяет достичь следующего: вы
пишете обычный императивный код, и волшебным образом его части превращаются
в сопрограммы. Они похожи на генераторы, которые могут взаимодействовать друг
с другом и отслеживать свое текущее состояние. Библиотека gevent модифицирует
многие стандартные объекты Python, такие как •‘ ‡–, для того чтобы использовать
их механизм вместо блокирования. Это не работает для кода надстроек Python, ко-
торый написан на С, например для некоторых драйверов баз данных.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Вы можете установить библиотеку gevent с помощью pip:


ɛpip install gevent

Вот вариант примера кода на сайте библиотеки gevent (KWWSZZZJHYHQWRUJ).


Вы увидите функцию ‰‡–Š‘•–„›ƒ‡ſƀ класса •‘ ‡– в следующем разделе DNS.
Эта функция работает синхронно, поэтому вам придется подождать (возможно,
много секунд), пока она не получит имена серверов со всего мира, чтобы найти
нужный адрес. Но вы можете использовать версию gevent, чтобы искать несколько
сайтов независимо друг от друга. Сохраните этот файл как ‰‡˜‡–ɏ–‡•–Ŝ’› (при-
мер 15.9).

ǷȘȐȔȍȘJHYHQWBWHVWS\
‹’‘”–‰‡˜‡–
ˆ”‘‰‡˜‡–‹’‘”–•‘ ‡–
Š‘•–•ʰƃɐ™™™Ŝ ”ƒ’’›–ƒš‹†‡”›Ŝ ‘ɐřɐ™™™Ŝ™ƒŽ–‡”’‘––‡”–ƒš‹†‡”›Ŝ ‘ɐř
ɐ™™™Ŝƒ–‹“—‡Ş–ƒš‹†‡”›Ŝ ‘ɐƄ
Œ‘„•ʰƃ‰‡˜‡–Ŝ•’ƒ™ſ‰‡˜‡–Ŝ•‘ ‡–Ŝ‰‡–Š‘•–„›ƒ‡řŠ‘•–ƀˆ‘”Š‘•–‹Š‘•–•Ƅ
‰‡˜‡–ŜŒ‘‹ƒŽŽſŒ‘„•ř–‹‡‘—–ʰɬƀ
ˆ‘”Œ‘„‹Œ‘„•ś
’”‹–ſŒ‘„Ŝ˜ƒŽ—‡ƀ

В этом примере вы можете увидеть однострочный цикл for. Каждое имя хоста
по очереди передается в вызов ‰‡–Š‘•–„›ƒ‡ſƀ, но запустить их можно асинхронно
благодаря версии функции ‰‡–Š‘•–„›ƒ‡ſƀ из библиотеки gevent.
Запустите файл ‰‡˜‡–ɏ–‡•–Ŝ’›:
ɛpython gevent_test.py
ɭɭŜɭŜɫɫŜɫ
ɮɫŜɨɩɬŜɨɫɩŜɨɩɨ
ɮɯŜɨɪɭŜɨɩŜɬɥ

Функция ‰‡˜‡–Ŝ•’ƒ™ſƀ создает гринлет (greenlet) (называемый также зеленым


потоком и микропотоком) для выполнения каждого вызова ‰‡˜‡–Ŝ•‘ ‡–Ŝ‰‡–Ş
Š‘•–„›ƒ‡ſ—”Žƀ.
Разница между ним и обычным потоком заключается в том, что зеленый поток
не блокируется. Если произошло какое-то событие, которое заблокировало обычный
поток, gevent переключит управление на другой зеленый поток.
Метод ‰‡˜‡–ŜŒ‘‹ƒŽŽſƀ ожидает завершения всех созданных задач. Наконец, мы
выводим на экран IP-адреса, полученные для заданных имен хостов.
Вместо версии •‘ ‡– из модуля gevent вы можете использовать его функции,
называемые monkey-patching (обезьяний патч). Они модифицируют стандартные
модули, такие как •‘ ‡–, для использования гринлетов вместо того, чтобы каждый
раз вызывалась версия модуля gevent. Это полезно, если вы хотите использовать
gevent везде, даже в коде, к которому вы можете не иметь доступа.
Добавьте в начало программы следующий вызов:
ˆ”‘‰‡˜‡–‹’‘”–‘‡›
‘‡›Ŝ’ƒ– Šɏ•‘ ‡–ſƀ
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

Таким образом, все обычные сокеты заменятся на сокеты gevent даже в стандарт-
ной библиотеке. Опять же это работает только для кода Python, но не для библиотек,
написанных на С.
Еще одна функция ‘‡›Ş’ƒ– Š‹‰ даже больше модулей стандартной библио-
теки:
ˆ”‘‰‡˜‡–‹’‘”–‘‡›
‘‡›Ŝ’ƒ– ŠɏƒŽŽſƀ

Разместите этот код в начале программы, чтобы максимально воспользоваться


ускорением, обеспечиваемым gevent.
Сохраните программу под именем ‰‡˜‡–ɏ‘‡›Ŝ’› (пример 15.10).

ǷȘȐȔȍȘJHYHQWBPRQNH\S\
‹’‘”–‰‡˜‡–
ˆ”‘‰‡˜‡–‹’‘”–‘‡›Ś‘‡›Ŝ’ƒ– ŠɏƒŽŽſƀ
‹’‘”–•‘ ‡–
Š‘•–•ʰƃɐ™™™Ŝ ”ƒ’’›–ƒš‹†‡”›Ŝ ‘ɐřɐ™™™Ŝ™ƒŽ–‡”’‘––‡”–ƒš‹†‡”›Ŝ ‘ɐř
ɐ™™™Ŝƒ–‹“—‡Ş–ƒš‹†‡”›Ŝ ‘ɐƄ
Œ‘„•ʰƃ‰‡˜‡–Ŝ•’ƒ™ſ•‘ ‡–Ŝ‰‡–Š‘•–„›ƒ‡řŠ‘•–ƀˆ‘”Š‘•–‹Š‘•–•Ƅ
‰‡˜‡–ŜŒ‘‹ƒŽŽſŒ‘„•ř–‹‡‘—–ʰɬƀ
ˆ‘”Œ‘„‹Œ‘„•ś
’”‹–ſŒ‘„Ŝ˜ƒŽ—‡ƀ

Запустите программу:
ɛpython gevent_monkey.py
ɭɭŜɭŜɫɫŜɫ
ɮɫŜɨɩɬŜɨɰɩŜɨɩɨ
ɮɯŜɨɪɭŜɨɩŜɬɥ

Использование gevent может нести потенциальную опасность. Как и в случае


с любой другой системой, основанной на событиях, каждый исполняемый вами
фрагмент кода должен быть относительно быстрым. Несмотря на то что код, который
выполняет много работы, не блокируется, он будет работать медленно.
Сама идея monkey-patching заставляет нервничать некоторых людей. Несмотря
на это, многие крупные сайты, такие как Pinterest, используют gevent для значи-
тельного ускорения своей работы. Используйте gevent строго по назначению, как
таблетки по рецепту.
Чтобы увидеть больше примеров, обратитесь к этому руководству — KWWS
VGLHKOJLWKXELRJHYHQWWXWRULDO.

ǹțȡȍșȚȊțȍȚ ȌȊȈ ȌȘțȋȐȝ ȗȖȗțȓȧȘȕȣȝ ȜȘȍȑȔȊȖȘȒȈ ȖșȕȖȊȈȕȕȣȝ ȕȈ șȖȉȣȚȐȧȝ ²


WRUQDGR KWWSZZZWRUQDGRZHERUJ ȐJXQLFRUQ KWWSJXQLFRUQRUJ ǶȕȐȗȖȔȖȋȈȦȚ
ȖȉȘȈȉȈȚȣȊȈȚȤșȖȉȣȚȐȧȕȈȕȐȏȒȖȔțȘȖȊȕȍȈȚȈȒȎȍȗȘȍȌȖșȚȈȊȓȧȦȚȉȣșȚȘȣȑȊȍȉ
șȍȘȊȍȘǰȝșȚȖȐȚȘȈșșȔȖȚȘȍȚȤȍșȓȐȊȣȝȖȚȐȚȍșȖȏȌȈȚȤȉȣșȚȘȣȑșȈȑȚȉȍȏȗȘȐȔȍȕȍȕȐȧ
ȚȘȈȌȐȞȐȖȕȕȣȝȊȍȉșȍȘȊȍȘȖȊȚȈȒȐȝȒȈȒ$SDFKH
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

WZLVWHG
–™‹•–‡† (KWWSWZLVWHGPDWUL[FRPWUDF) — это асинхронный фреймворк, управляемый
событиями, для работы с сетями. Вы подключаете функции к таким событиям, как
получение данных или закрытие соединения, и функции вызываются, когда событие
происходит. В данном случае речь идет о функциях обратного вызова. Если вы уже
писали код на языке JavaScript, это может показаться вам знакомым. По мере роста
приложения некоторым разработчикам бывает сложнее управлять кодом, основан-
ным на функциях обратного вызова.
Чтобы установить фреймворк, введите следующую команду:
$ pip install twisted

–™‹•–‡† — это крупный пакет, который поддерживает множество интернет-про-


токолов на базе TCP и UDP. Для краткости мы рассмотрим небольшой сервер
и клиент, созданные на базе примеров для WZLVWHG (KWWSELWO\WZLVWHGH[). Сначала об-
ратимся к серверу ‘ ɏ•‡”˜‡”Ŝ’› (пример 15.11).

ǷȘȐȔȍȘNQRFNBVHUYHUS\
ˆ”‘–™‹•–‡†Ŝ‹–‡”‡–‹’‘”–’”‘–‘ ‘Žř”‡ƒ –‘”

Žƒ••‘ ſ’”‘–‘ ‘ŽŜ”‘–‘ ‘Žƀś


†‡ˆ†ƒ–ƒ‡ ‡‹˜‡†ſ•‡Žˆř†ƒ–ƒƀś
’”‹–ɐŽ‹‡–śɐř†ƒ–ƒ
‹ˆ†ƒ–ƒŜ•–ƒ”–•™‹–Šſɑ‘ ‘ ɑƀś
”‡•’‘•‡ʰɑŠ‘ɐ•–Ї”‡ţɑ
‡Ž•‡ś
”‡•’‘•‡ʰ†ƒ–ƒʫɑ™Š‘ţɑ
’”‹–ɐ‡”˜‡”śɐř”‡•’‘•‡
•‡ŽˆŜ–”ƒ•’‘”–Ŝ™”‹–‡ſ”‡•’‘•‡ƀ

Žƒ••‘  ƒ –‘”›ſ’”‘–‘ ‘ŽŜ ƒ –‘”›ƀś


†‡ˆ„—‹Ž†”‘–‘ ‘Žſ•‡Žˆřƒ††”ƀś
”‡–—”‘ ſƀ
”‡ƒ –‘”ŜŽ‹•–‡ſɯɥɥɥř‘  ƒ –‘”›ſƀƀ
”‡ƒ –‘”Ŝ”—ſƀ

Теперь взглянем на его верного компаньона ‘ ɏ Ž‹‡–Ŝ’› (пример 15.12).

ǷȘȐȔȍȘNQRFNBFOLHQWS\
ˆ”‘–™‹•–‡†Ŝ‹–‡”‡–‹’‘”–”‡ƒ –‘”ř’”‘–‘ ‘Ž

Žƒ••‘ Ž‹‡–ſ’”‘–‘ ‘ŽŜ”‘–‘ ‘Žƀś


†‡ˆ ‘‡ –‹‘ƒ†‡ſ•‡Žˆƀś
•‡ŽˆŜ–”ƒ•’‘”–Ŝ™”‹–‡ſɑ‘ ‘ ɑƀ

†‡ˆ†ƒ–ƒ‡ ‡‹˜‡†ſ•‡Žˆř†ƒ–ƒƀś
‹ˆ†ƒ–ƒŜ•–ƒ”–•™‹–ŠſɑŠ‘ɐ•–Ї”‡ţɑƀś
”‡•’‘•‡ʰɑ‹•ƒ’’‡ƒ”‹‰ Ž‹‡–ɑ
•‡ŽˆŜ–”ƒ•’‘”–Ŝ™”‹–‡ſ”‡•’‘•‡ƀ
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

‡Ž•‡ś
•‡ŽˆŜ–”ƒ•’‘”–ŜŽ‘•‡‘‡ –‹‘ſƀ
”‡ƒ –‘”Ŝ•–‘’ſƀ

Žƒ••‘  ƒ –‘”›ſ’”‘–‘ ‘ŽŜŽ‹‡– ƒ –‘”›ƀś


’”‘–‘ ‘Žʰ‘ Ž‹‡–

†‡ˆƒ‹ſƀś
ˆʰ‘  ƒ –‘”›ſƀ
”‡ƒ –‘”Ŝ ‘‡ –ſɑŽ‘ ƒŽŠ‘•–ɑřɯɥɥɥřˆƀ
”‡ƒ –‘”Ŝ”—ſƀ

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
ƒ‹ſƀ

Первым запустим сервер:


ɛpython knock_server.py

Вторым — клиент:
ɛpython knock_client.py

Сервер и клиент обмениваются сообщениями, и сервер выводит весь диалог:


Ž‹‡–ś‘ ‘ 
‡”˜‡”śŠ‘ɐ•–Ї”‡ţ
Ž‹‡–ś‹•ƒ’’‡ƒ”‹‰ Ž‹‡–
‡”˜‡”ś‹•ƒ’’‡ƒ”‹‰ Ž‹‡–™Š‘ţ

Наш клиент-шутник завершает работу, оставляя сервер ждать ударной реплики.


Если вы хотите забраться в дебри –™‹•–‡†, попробуйте запустить другие примеры
из его документации.

DV\QFLR
Библиотека ƒ•› ‹‘ была добавлена в версию Python 3.4. Она представляет собой
способ определения конкурентного кода с помощью новой функциональности,
предоставляемой ключевыми словами ƒ•› и await . Это очень обширная тема
с большим количеством деталей. Чтобы не перегружать эту главу, я переместил
рассмотрение библиотеки ƒ•› ‹‘ и связанных с ней тем в приложение В.

5HGLV
Приведенные ранее примеры кода для мытья посуды, где использовались про-
цессы или потоки, запускались на одной машине. Рассмотрим еще один подход
к очередям, которые могут запускаться на одной машине или во всей сети. Иногда
даже для нескольких процессов и/или потоков одной машины бывает недоста-
точно. Вы можете воспринимать этот подраздел как мостик между конкурентным
использованием одного блока (компьютера) и конкурентным использованием не-
скольких блоков.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Для запуска примеров из этого раздела вам понадобятся сервер Redis и его мо-
дуль для Python. Чтобы узнать, как их скачать, обратитесь к подразделу «Redis» на
с. 256. В этой главе Redis используется как база данных. Здесь же мы рассмотрим
его возможности для работы с конкурентностью.
Создать очередь можно с помощью списка Redis. Сервер Redis работает на одной
машине, на которой могут быть запущены и клиенты. Возможно также, что никакие
клиенты на ней не запускаются, а остальные машины получают доступ к серверу
по сети. В любом случае клиент общается с сервером с помощью протокола TCP.
Один или несколько клиентов-провайдеров помещают сообщения в конец списка.
Один или несколько клиентов-работников наблюдают за списком и используют
операцию «блокирующее выталкивание» (blocking pop). Если список пуст, то все
они просто тратят время впустую. Как только сообщение появляется, его получает
первый ожидающий работник.
Как и в предыдущих, основанных на процессах и потоках примерах, код файла
”‡†‹•ɏ™ƒ•Ї”Ŝ’› генерирует последовательность посуды (пример 15.13).

ǷȘȐȔȍȘUHGLVBZDVKHUS\
‹’‘”–”‡†‹•
‘ʰ”‡†‹•Ŝ‡†‹•ſƀ
’”‹–ſɐƒ•Ї”‹••–ƒ”–‹‰ɐƀ
†‹•Ї•ʰƃɐ•ƒŽƒ†ɐřɐ„”‡ƒ†ɐřɐ‡–”‡‡ɐřɐ†‡••‡”–ɐƄ
ˆ‘”†‹•Š‹†‹•Ї•ś
•‰ʰ†‹•ŠŜ‡ ‘†‡ſɐ—–ˆŞɯɐƀ
 ‘Ŝ”’—•Šſɐ†‹•Ї•ɐř•‰ƀ
’”‹–ſɐƒ•Ї†ɐř—ƀ
‘Ŝ”’—•Šſɐ†‹•Ї•ɐřɐ“—‹–ɐƀ
’”‹–ſɐƒ•Ї”‹•†‘‡ɐƀ

Цикл генерирует четыре сообщения с названиями тарелок, за которыми следует


заключительное сообщение со словом quit. Каждое сообщение добавляется в список
тарелок на сервере Redis по принципу, сходному с принципами Python.
Как только первая тарелка готова, в работу вступает код файла ”‡†‹•ɏ†”›‡”Ŝ’›
(пример 15.14).

ǷȘȐȔȍȘUHGLVBGU\HUS\
‹’‘”–”‡†‹•
‘ʰ”‡†‹•Ŝ‡†‹•ſƀ
’”‹–ſɐ”›‡”‹••–ƒ”–‹‰ɐƀ
™Š‹Ž‡”—‡ś
•‰ʰ ‘Ŝ„Ž’‘’ſɐ†‹•Ї•ɐƀ
‹ˆ‘–•‰ś
„”‡ƒ
˜ƒŽʰ•‰ƃɨƄŜ†‡ ‘†‡ſɐ—–ˆŞɯɐƀ
‹ˆ˜ƒŽʰʰɐ“—‹–ɐś
„”‡ƒ
’”‹–ſɐ”‹‡†ɐř˜ƒŽƀ
’”‹–ſɐ‹•Ї•ƒ”‡†”‹‡†ɐƀ
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

Этот код ожидает сообщения, в котором первым токеном будет слово †‹•Ї•,
и выводит сообщение о каждой высушенной тарелке. Подчиняясь сообщению quit,
он завершает цикл.
Запустите сначала сушильщика, а затем мойщика. Использование символа ĺ
в конце команды ставит первую программу в фоновый режим: она продолжает
выполняться, но больше не принимает команды с клавиатуры. Это работает для
операционных систем Linux, OS X и Windows, однако вы можете получить разные
результаты в следующей строке. В нашем случае (OS X) этим результатом является
некоторая информация о фоновом процессе сушильщика. Далее мы запускаем про-
цесс мойщика как обычно (на переднем плане). Вы увидите смешанную выходную
информацию двух процессов:
ɛpython redis_dryer.py &
ƃɩƄɯɨɭɰɨ
”›‡”‹••–ƒ”–‹‰
ɛpython redis_washer.py
ƒ•Ї”‹••–ƒ”–‹‰
ƒ•Ї†•ƒŽƒ†
”‹‡†•ƒŽƒ†
ƒ•Ї†„”‡ƒ†
”‹‡†„”‡ƒ†
ƒ•Ї†‡–”‡‡
”‹‡†‡–”‡‡
ƒ•Ї††‡••‡”–
ƒ•Ї”‹•†‘‡
”‹‡††‡••‡”–
‹•Ї•ƒ”‡†”‹‡†
ƃɩƄʫ‘‡’›–Š‘”‡†‹•ɏ†”›‡”Ŝ’›

Как только идентификаторы посуды начинают приходить от мойщика, наш


трудолюбивый процесс сушильщика начинает их обрабатывать. Каждый иден-
тификатор посуды, за исключением финального контрольного значения (строки
quit) является числом. После того как процесс сушильщика считывает этот иден-
тификатор quit , он завершает работу и выводит на терминал дополнительную
информацию о фоновом процессе (что также зависит от системы). Вы можете
использовать контрольное значение (или по-другому — некорректное значение),
чтобы указать на что-то особенное в потоке данных. В нашей ситуации мы говорим,
что закончили работу. В противном случае придется добавить больше программной
логики, например:
‰заранее оговорить некоторое максимальное количество посуды, что также будет
похоже на контрольное значение;
‰выполнять определенную специфическую коммуникацию вне потока данных
между процессами;
‰завершать работу по прошествии какого-то времени, если данных не посту-
пало.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Внесем еще несколько изменений.


‰Создадим несколько процессов-сушильщиков.
‰Заставим их завершаться по прошествии некоторого времени вместо того, чтобы
ожидать контрольного значения.
Новый файл ”‡†‹•ɏ†”›‡”ɩŜ’› показан в примере 15.15.

ǷȘȐȔȍȘUHGLVBGU\HUS\
†‡ˆ†”›‡”ſƀś
‹’‘”–”‡†‹•
‹’‘”–‘•
‹’‘”––‹‡
 ‘ʰ”‡†‹•Ŝ‡†‹•ſƀ
’‹†ʰ‘•Ŝ‰‡–’‹†ſƀ
–‹‡‘—–ʰɩɥ
’”‹–ſɐ”›‡”’”‘ ‡••ʩ•‹••–ƒ”–‹‰ɐʩ’‹†ƀ
™Š‹Ž‡”—‡ś
•‰ʰ ‘Ŝ„Ž’‘’ſɐ†‹•Ї•ɐř–‹‡‘—–ƀ
‹ˆ‘–•‰ś
„”‡ƒ
˜ƒŽʰ•‰ƃɨƄŜ†‡ ‘†‡ſɐ—–ˆŞɯɐƀ
‹ˆ˜ƒŽʰʰɐ“—‹–ɐś
„”‡ƒ
’”‹–ſɐʩ•ś†”‹‡†ʩ•ɐʩſ’‹†ř˜ƒŽƀƀ
–‹‡Ŝ•އ‡’ſɥŜɨƀ
’”‹–ſɐ”›‡”’”‘ ‡••ʩ•‹•†‘‡ɐʩ’‹†ƀ

‹’‘”–—Ž–‹’”‘ ‡••‹‰
ʰɪ
ˆ‘”—‹”ƒ‰‡ſƀś
’ʰ—Ž–‹’”‘ ‡••‹‰Ŝ”‘ ‡••ſ–ƒ”‰‡–ʰ†”›‡”ƀ
’Ŝ•–ƒ”–ſƀ

Запустим процессы сушильщиков в фоновом режиме и процесс мойщика на


переднем плане:
ɛpython redis_dryer2.py &
”›‡”’”‘ ‡••ɫɫɫɫɮ‹••–ƒ”–‹‰
”›‡”’”‘ ‡••ɫɫɫɫɯ‹••–ƒ”–‹‰
”›‡”’”‘ ‡••ɫɫɫɫɭ‹••–ƒ”–‹‰
$ python redis_washer.py
ƒ•Ї”‹••–ƒ”–‹‰
ƒ•Ї†•ƒŽƒ†
ɫɫɫɫɮś†”‹‡†•ƒŽƒ†
ƒ•Ї†„”‡ƒ†
ɫɫɫɫɯś†”‹‡†„”‡ƒ†
ƒ•Ї†‡–”‡‡
ɫɫɫɫɭś†”‹‡†‡–”‡‡
ƒ•Ї††‡••‡”–
ƒ•Ї”‹•†‘‡
ɫɫɫɫɮś†”‹‡††‡••‡”–
ǫȓȈȊȈǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣȐȒȖȕȒțȘȍȕȚȕȖșȚȤ  

Один процесс сушильщика считывает идентификатор quit и завершает работу:


”›‡”’”‘ ‡••ɫɫɫɫɯ‹•†‘‡

Через 20 секунд другие процессы-сушильщики получают значение ‘‡ от вызо-


ва blpop (это указывает на то, что они завершились по таймеру). Процессы выводят
свои последние сообщения и завершаются:
”›‡”’”‘ ‡••ɫɫɫɫɮ‹•†‘‡
”›‡”’”‘ ‡••ɫɫɫɫɭ‹•†‘‡

После того как завершается последний подпроцесс-сушильщик, завершается


и основная программа-сушильщик:
ƃɨƄʫ‘‡’›–Š‘”‡†‹•ɏ†”›‡”ɩŜ’›

ǷȖȔȐȔȖȖȟȍȘȍȌȍȑ
С увеличением числа работающих элементов растет вероятность сбоев в работе на-
шего конвейера. Хватит ли нам работников, если нужно будет вымыть посуду после
банкета? А что, если сушильщики напьются до чертиков? А если забьется раковина?
Ох уж эти проблемы!
Как же с ними справиться? К счастью, есть некоторые приемы.
‰Запустить и забыть. Просто передавайте обработанные объекты дальше и не за-
ботьтесь о последствиях, даже если там никого нет. Этот подход похож на сбра-
сывание посуды на пол.
‰Запрос — ответ. Мойщик получает подтверждение от сушильщика, а сушиль-
щик — от того, кто откладывает посуду в сторону. Все это выполняется для
каждой тарелки.
‰Регулирование нагрузки. Этот прием указывает самому быстрому работнику при-
тормозить, если один из работников, стоящих после него, не поспевает за ним.
В реальных системах вам нужно внимательно следить за тем, чтобы все работни-
ки успевали за графиком, в противном случае вы услышите звук бьющейся посуды.
Вы можете добавлять в список ожидания новые задачи, а какой-то процесс будет
доставать из этого списка последнее сообщение и помещать его в список обработки.
Обработанное сообщение будет удалено из списка обработки и добавлено в список
завершенных задач. Это позволит вам узнать, какие задачи не были выполнены
или затрачивают слишком много времени. Вы можете сделать это самостоятельно
с помощью Redis или использовать систему, которую кто-то другой уже написал
и протестировал. Некоторые основанные на Python пакеты для работы с очередями
(часть из них используют Redis) позволяют удобно управлять процессом:
‰celery (KWWSZZZFHOHU\SURMHFWRUJ ) может выполнять распределенные задачи
как синхронно, так и асинхронно, используя рассмотренные нами методы —
—Ž–‹’”‘ ‡••‹‰, gevent и др.;
‰rq (KWWSS\WKRQUTRUJ) — это библиотека Python для очередей задач, также осно-
ванная на Redis.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǿȐȚȈȑȚȍȌȈȓȍȍ
В этой главе мы пропустили данные сквозь процессы. В следующей главе вы уви-
дите, как сохранять и получать данные, используя разные форматы файлов и баз
данных.

ǻȗȘȈȎȕȍȕȐȧ
15.1. Используйте модуль —Ž–‹’”‘ ‡••‹‰, чтобы создать три отдельных процес-
са. Заставьте каждый из них подождать случайное количество секунд между
нулем и единицей, вывести текущее время, а затем завершить работу.
ƋƓƈƊƈ
ǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍ
ȝȘȈȕȐȓȐȡȈ

Огромная ошибка — делать выводы, не имея


необходимой информации.

Артур Конан Дойль

Активная программа работает с данными, которые хранятся в запоминающем


устройстве с произвольным доступом (Random Access Memory, RAM). RAM — очень
быстрая память, но дорогая и требующая постоянного питания: если питание пропа-
дет, то все данные, которые в ней хранятся, будут утеряны. Жесткие диски медленнее
оперативной памяти, но более емкие, стоят дешевле и могут хранить данные даже
после того, как кто-то выдернет шнур питания. Поэтому много усилий при создании
компьютерных систем было потрачено на поиск оптимального соотношения между
хранением данных на диске и в оперативной памяти. Как программистам, нам важно
постоянство: хранение и извлечение данных с использованием энергонезависимых
носителей, таких как диски.
В этой главе мы рассмотрим разнообразные способы хранения данных, каждый
из которых оптимизирован для разных целей: плоские файлы, структурированные
файлы и базы данных. Операции с файлами, не касающиеся ввода-вывода, рассма-
триваются в главе 14.
Запись — это термин, обозначающий некоторые связанные между собой данные.
Запись состоит из отдельных полей.

ǷȓȖșȒȐȍȚȍȒșȚȖȊȣȍȜȈȑȓȣ
Самый простой пример постоянного хранилища — это старый добрый файл, кото-
рый иногда называют еще плоским файлом. Он хорошо работает в том случае, когда
у данных очень простая структура и вы полностью записываете их на диск или счи-
тываете с него. Такой подход годится для простых текстовых данных.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǺȍȒșȚȖȊȣȍȜȈȑȓȣȌȖȗȖȓȕȍȕȕȣȍȗȘȖȉȍȓȈȔȐ
В этом формате каждое поле записи имеет фиксированную длину и при необхо-
димости дополняется до требуемой длины (как правило, пробелами) так, чтобы
все записи имели одинаковый размер. Программист может использовать функцию
•‡‡ſƀ для перемещения по файлу, для записи или только для чтения необходимых
записей и полей.

ǹȚȘțȒȚțȘȐȘȖȊȈȕȕȣȍȚȍȒșȚȖȊȣȍȜȈȑȓȣ
Для простых текстовых файлов единственным уровнем организации является
строка. Но иногда вам может понадобиться более структурированный файл, чтобы
сохранить данные из программы для дальнейшего использования или отправить их
другой программе.
Существует множество форматов, и у каждого есть свои особенности.
‰Разделитель (separator или delimiter) — такие символы, как табуляция (ɐɎ–ɐ),
запятая (ɐřɐ ), вертикальная черточка (ɐŶɐ ). Это пример CSV — формата со
значениями, разделенными запятой.
‰Символы ɐʳɐ и ɐʴɐ в окружении тегов. Примеры включают в себя XML и HTML.
‰Знаки препинания. Примером является JavaScript Object Notation (JSON).
‰Выделение пробелами. Примером является YAML (аббревиатура расшифровы-
вается как YAML Ain’t Markup Language — «YAML — не язык разметки»).
‰Другие файлы, например конфигурационные.
Каждый из этих форматов структурированных файлов может быть считан и за-
писан с помощью как минимум одного модуля Python.

&69
Файлы с разделителями часто используются в качестве формата обмена данными
для электронных таблиц и баз данных. Вы можете считать файл CSV вручную, по
одной строке за раз, разделяя каждую строку на поля, расставляя запятые и добавляя
результат в структуру данных, такую как список или словарь. Но лучшим решением
будет использовать стандартный модуль •˜, поскольку парсинг этих файлов может
оказаться сложнее, чем вы думаете. Ознакомьтесь с важными характеристиками
файлов CSV, о которых нужно помнить:
‰некоторые имеют альтернативные разделители вместо запятой: самыми по-
пулярными являются ɐŶɐ и ɐɎ–ɐ;
‰некоторые имеют escape-последовательности. Если символ-разделитель встре-
чается внутри поля, все поле может быть окружено кавычками или же ему будет
предшествовать escape-последовательность;
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

‰некоторые имеют разные символы конца строк. В Unix используется ɐɎɐ ,


в Microsoft — ɐɎ” Ɏɐ. Apple раньше применяла символ ɐɎ”ɐ, но теперь перешла
на использование ɐɎɐ;
‰некоторые в первой строке могут иметь названия столбцов.
Сначала мы посмотрим, как читать и записывать список строк, каждая из которых
содержит список столбцов:
ʴʴʴ‹’‘”– •˜
ʴʴʴ˜‹ŽŽƒ‹•ʰƃ
ŜŜŜƃɐ‘ –‘”ɐřɐ‘ɐƄř
ŜŜŜƃɐ‘•ƒɐřɐއ„„ɐƄř
ŜŜŜƃɐ‹•–‡”ɐřɐ‹‰ɐƄř
ŜŜŜƃɐ—”‹ ɐřɐ ‘ކˆ‹‰‡”ɐƄř
ƃɐ”•–ɐřɐŽ‘ˆ‡Ž†ɐƄř
ŜŜŜƄ
ʴʴʴ™‹–Š‘’‡ſɐ˜‹ŽŽƒ‹•ɐřɐ™–ɐƀƒ•ˆ‘—–śɤȠșȡșȘȚșȤȞȢȡȦșȞȥȦȔ
ŜŜŜ •˜‘—–ʰ •˜Ŝ™”‹–‡”ſˆ‘—–ƀ
ŜŜŜ •˜‘—–Ŝ™”‹–‡”‘™•ſ˜‹ŽŽƒ‹•ƀ

Этот код создает пять записей:


‘ –‘”ř‘
‘•ƒřއ„„
‹•–‡”ř‹‰
—”‹ ř ‘ކˆ‹‰‡”
”•–řŽ‘ˆ‡Ž†

Теперь попробуем считать их обратно:


ʴʴʴ‹’‘”– •˜
ʴʴʴ™‹–Š‘’‡ſɐ˜‹ŽŽƒ‹•ɐřɐ”–ɐƀƒ•ˆ‹śɤȠșȡșȘȚșȤȞȢȡȦșȞȥȦȔ
ŜŜŜ ‹ʰ •˜Ŝ”‡ƒ†‡”ſˆ‹ƀ
ŜŜŜ˜‹ŽŽƒ‹•ʰƃ”‘™ˆ‘””‘™‹ ‹ƄɤțȘșȥȰȜȥȣȢȟȰțȧșȦȥȳȖȞȟȲȫșȡȜșȥȣȜȥȞȔ
ŜŜŜ
ʴʴʴ’”‹–ſ˜‹ŽŽƒ‹•ƀ
ƃƃɐ‘ –‘”ɐřɐ‘ɐƄřƃɐ‘•ƒɐřɐއ„„ɐƄřƃɐ‹•–‡”ɐřɐ‹‰ɐƄř
ƃɐ—”‹ ɐřɐ ‘ކˆ‹‰‡”ɐƄřƃɐ”•–ɐřɐŽ‘ˆ‡Ž†ɐƄƄ

Мы воспользовались структурой, созданной функцией ”‡ƒ†‡”ſƀ. Она услужливо


создала в объекте ‹ ряды, которые мы можем извлечь с помощью цикла for.
Используя функции ”‡ƒ†‡”ſƀ и ™”‹–‡”ſƀ с их стандартными опциями, мы получим
столбцы, разделенные запятыми, и ряды, разделенные символами перевода строки.
Данные могут иметь формат списка словарей, а не списка списков. Снова счита-
ем файл villains, на этот раз используя новую функцию ‹ –‡ƒ†‡”ſƀ и указывая
имена столбцов:
ʴʴʴ‹’‘”– •˜
ʴʴʴ™‹–Š‘’‡ſɐ˜‹ŽŽƒ‹•ɐřɐ”–ɐƀƒ•ˆ‹ś
ŜŜŜ ‹ʰ •˜Ŝ‹ –‡ƒ†‡”ſˆ‹řˆ‹‡Ž†ƒ‡•ʰƃɐˆ‹”•–ɐřɐŽƒ•–ɐƄƀ
ŜŜŜ˜‹ŽŽƒ‹•ʰƃ”‘™ˆ‘””‘™‹ ‹Ƅ
ŜŜŜ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ʴʴʴ’”‹–ſ˜‹ŽŽƒ‹•ƀ
ƃ”†‡”‡†‹ –ſƃſɐˆ‹”•–ɐřɐ‘ –‘”ɐƀřſɐŽƒ•–ɐřɐ‘ɐƀƄƀř
”†‡”‡†‹ –ſƃſɐˆ‹”•–ɐřɐ‘•ƒɐƀřſɐŽƒ•–ɐřɐއ„„ɐƀƄƀř
”†‡”‡†‹ –ſƃſɐˆ‹”•–ɐřɐ‹•–‡”ɐƀřſɐŽƒ•–ɐřɐ‹‰ɐƀƄƀř
”†‡”‡†‹ –ſƃſɐˆ‹”•–ɐřɐ—”‹ ɐƀřſɐŽƒ•–ɐřɐ ‘ކˆ‹‰‡”ɐƀƄƀř
”†‡”‡†‹ –ſƃſɐˆ‹”•–ɐřɐ”•–ɐƀřſɐŽƒ•–ɐřɐŽ‘ˆ‡Ž†ɐƀƄƀƄ

Словарь ”†‡”‡†‹ – используется для обеспечения совместимости с версиями


Python ниже 3.6, в которых словари сохраняли порядок элементов по умолчанию.
Перепишем CSV-файл с помощью новой функции ‹ –”‹–‡”ſƀ . Мы также
вызовем функцию ™”‹–‡Š‡ƒ†‡”ſƀ, чтобы записать начальную строку, содержащую
имена столбцов, в CSV-файл:
‹’‘”– •˜
˜‹ŽŽƒ‹•ʰƃ
Ƈɐˆ‹”•–ɐśɐ‘ –‘”ɐřɐŽƒ•–ɐśɐ‘ɐƈř
Ƈɐˆ‹”•–ɐśɐ‘•ƒɐřɐŽƒ•–ɐśɐއ„„ɐƈř
Ƈɐˆ‹”•–ɐśɐ‹•–‡”ɐřɐŽƒ•–ɐśɐ‹‰ɐƈř
Ƈɐˆ‹”•–ɐśɐ—”‹ ɐřɐŽƒ•–ɐśɐ ‘ކˆ‹‰‡”ɐƈř
Ƈɐˆ‹”•–ɐśɐ”•–ɐřɐŽƒ•–ɐśɐŽ‘ˆ‡Ž†ɐƈř
Ƅ
™‹–Š‘’‡ſɐ˜‹ŽŽƒ‹•ɐřɐ™–ɐƀƒ•ˆ‘—–ś
 ‘—–ʰ •˜Ŝ‹ –”‹–‡”ſˆ‘—–řƃɐˆ‹”•–ɐřɐŽƒ•–ɐƄƀ
 ‘—–Ŝ™”‹–‡Š‡ƒ†‡”ſƀ
 ‘—–Ŝ™”‹–‡”‘™•ſ˜‹ŽŽƒ‹•ƀ

Этот код создает файл ˜‹ŽŽƒ‹•Ŝ •˜ со строкой заголовка (пример 16.1).

ǷȘȐȔȍȘYLOODLQVFVY
ˆ‹”•–řŽƒ•–
‘ –‘”ř‘
‘•ƒřއ„„
‹•–‡”ř‹‰
—”‹ ř ‘ކˆ‹‰‡”
”•–řŽ‘ˆ‡Ž†

Теперь считаем его обратно. Опуская аргумент ˆ‹‡Ž†ƒ‡• в вызове ‹ –‡ƒ†‡”ſƀ,


мы указываем функции использовать значения первой строки файла ſˆ‹”•–ř Žƒ•–ƀ
как имена столбцов и соответствующие ключи словаря:
ʴʴʴ‹’‘”– •˜
ʴʴʴ™‹–Š‘’‡ſɐ˜‹ŽŽƒ‹•ɐřɐ”–ɐƀƒ•ˆ‹ś
ŜŜŜ ‹ʰ •˜Ŝ‹ –‡ƒ†‡”ſˆ‹ƀ
ŜŜŜ˜‹ŽŽƒ‹•ʰƃ”‘™ˆ‘””‘™‹ ‹Ƅ
ŜŜŜ
ʴʴʴ’”‹–ſ˜‹ŽŽƒ‹•ƀ
ƃ”†‡”‡†‹ –ſƃſɐˆ‹”•–ɐřɐ‘ –‘”ɐƀřſɐŽƒ•–ɐřɐ‘ɐƀƄƀř
”†‡”‡†‹ –ſƃſɐˆ‹”•–ɐřɐ‘•ƒɐƀřſɐŽƒ•–ɐřɐއ„„ɐƀƄƀř
”†‡”‡†‹ –ſƃſɐˆ‹”•–ɐřɐ‹•–‡”ɐƀřſɐŽƒ•–ɐřɐ‹‰ɐƀƄƀř
”†‡”‡†‹ –ſƃſɐˆ‹”•–ɐřɐ—”‹ ɐƀřſɐŽƒ•–ɐřɐ ‘ކˆ‹‰‡”ɐƀƄƀř
”†‡”‡†‹ –ſƃſɐˆ‹”•–ɐřɐ”•–ɐƀřſɐŽƒ•–ɐřɐŽ‘ˆ‡Ž†ɐƀƄƀƄ
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

;0/
Файлы с разделителями отображают только два измерения: ряды (строки) и столбцы
(поля внутри строк). Если вы хотите обмениваться структурами данных между про-
граммами, вам нужен способ кодирования иерархий, последовательностей, множеств
и других структур в виде текста.
XML является самым известным форматом разметки, который можно применять
в этом случае. Для разделения данных он использует теги, как показано в следую-
щем примере (файл ‡—ŜšŽ):
ʳţšŽ˜‡”•‹‘ʰɑɨŜɥɑţʴ
ʳ‡—ʴ
ʳ„”‡ƒˆƒ•–Š‘—”•ʰɑɮŞɨɨɑʴ
ʳ‹–‡’”‹ ‡ʰɑɛɭŜɥɥɑʴ„”‡ƒˆƒ•–„—””‹–‘•ʳŵ‹–‡ʴ
ʳ‹–‡’”‹ ‡ʰɑɛɫŜɥɥɑʴ’ƒ ƒ‡•ʳŵ‹–‡ʴ
ʳŵ„”‡ƒˆƒ•–ʴ
ʳŽ— ŠŠ‘—”•ʰɑɨɨŞɪɑʴ
ʳ‹–‡’”‹ ‡ʰɑɛɬŜɥɥɑʴŠƒ„—”‰‡”ʳŵ‹–‡ʴ
ʳŵŽ— Šʴ
ʳ†‹‡”Š‘—”•ʰɑɪŞɨɥɑʴ
ʳ‹–‡’”‹ ‡ʰɑɯŜɥɥɑʴ•’ƒ‰Š‡––‹ʳŵ‹–‡ʴ
ʳŵ†‹‡”ʴ
ʳŵ‡—ʴ

Рассмотрим основные характеристики формата XML.


‰Теги начинаются с символа ʳ. В этом примере использованы теги ‡—, „”‡ƒˆƒ•–,
Ž— Š, †‹‡” и ‹–‡.
‰Пробелы игнорируются.
‰Обычно контент размещается после начального тега, такого как ʳ‡—ʴ. Имеется
и соответствующий конечный тег, такой как ʳŵ‡—ʴ.
‰Теги могут быть вложены в другие теги на любой глубине. В этом примере теги
‹–‡ являются потомками тегов „”‡ƒˆƒ•–, Ž— Š и †‹‡”, которые, в свою оче-
редь, являются потомками тега ‡—.
‰Внутри начального тега могут встретиться опциональные атрибуты. В этом
примере ’”‹ ‡ является опциональным атрибутом тега ‹–‡.
‰Теги могут содержать значения. В этом примере каждый тег ‹–‡ имеет значение
’ƒ ƒ‡• для второго элемента тега „”‡ƒˆƒ•–.
‰Если у тега с именем thing нет значений или потомков, он может быть оформлен
как единственный тег путем включения прямого слеша прямо перед закрыва-
ющей угловой скобкой (ʳ–Š‹‰ŵʴ), вместо того чтобы использовать начальный
и конечный теги ʳ–Š‹‰ʴ и ʳŵ–Š‹‰ʴ.
‰Место размещения данных — атрибутов, значений или тегов-потомков — являет-
ся в какой-то мере произвольным. Например, мы могли бы написать последний
тег ‹–‡ как ʳ‹–‡ ’”‹ ‡ʰɑɛɯŜɥɥɑ ˆ‘‘†ʰɑ•’ƒ‰Š‡––‹ɑŵʴ.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

XML часто используется в каналах данных и сообщениях, у него есть такие


подформаты, как RSS и Atom. В некоторых отраслях существует множество
специализированных форматов XML, например в сфере в финансов (KWWSELWO\
[POILQDQFH).
Сверхгибкость формата XML вдохновила многих людей на создание библио-
тек для Python, каждая из которых отличается от других подходом и возмож-
ностями.
Самый простой способ проанализировать XML в Python — использовать стан-
дартный модуль އ‡–”‡‡. Рассмотрим небольшую программу, которая анализи-
рует файл ‡—ŜšŽ и выводит на экран некоторые теги и атрибуты:
ʴʴʴ‹’‘”–šŽŜ‡–”‡‡Ŝއ‡–”‡‡ƒ•‡–
ʴʴʴ–”‡‡ʰ‡–Ŝއ‡–”‡‡ſˆ‹Ž‡ʰɐ‡—ŜšŽɐƀ
ʴʴʴ”‘‘–ʰ–”‡‡Ŝ‰‡–”‘‘–ſƀ
ʴʴʴ”‘‘–Ŝ–ƒ‰
ɐ‡—ɐ
ʴʴʴˆ‘” Ћކ‹”‘‘–ś
ŜŜŜ’”‹–ſɐ–ƒ‰śɐř ЋކŜ–ƒ‰řɐƒ––”‹„—–‡•śɐř ЋކŜƒ––”‹„ƀ
ŜŜŜˆ‘”‰”ƒ† Ћކ‹ Ћކś
ŜŜŜ’”‹–ſɐɎ––ƒ‰śɐř‰”ƒ† ЋކŜ–ƒ‰řɐƒ––”‹„—–‡•śɐř‰”ƒ† ЋކŜƒ––”‹„ƀ
ŜŜŜ
–ƒ‰ś„”‡ƒˆƒ•–ƒ––”‹„—–‡•śƇɐŠ‘—”•ɐśɐɮŞɨɨɐƈ
–ƒ‰ś‹–‡ƒ––”‹„—–‡•śƇɐ’”‹ ‡ɐśɐɛɭŜɥɥɐƈ
–ƒ‰ś‹–‡ƒ––”‹„—–‡•śƇɐ’”‹ ‡ɐśɐɛɫŜɥɥɐƈ
–ƒ‰śŽ— Šƒ––”‹„—–‡•śƇɐŠ‘—”•ɐśɐɨɨŞɪɐƈ
–ƒ‰ś‹–‡ƒ––”‹„—–‡•śƇɐ’”‹ ‡ɐśɐɛɬŜɥɥɐƈ
–ƒ‰ś†‹‡”ƒ––”‹„—–‡•śƇɐŠ‘—”•ɐśɐɪŞɨɥɐƈ
–ƒ‰ś‹–‡ƒ––”‹„—–‡•śƇɐ’”‹ ‡ɐśɐɯŜɥɥɐƈ
ʴʴʴއſ”‘‘–ƀɤȞȢȟȜȫșȥȦȖȢȤȔțȘșȟȢȖȠșȡȲ
ɪ
ʴʴʴއſ”‘‘–ƃɥƄƀɤȞȢȟȜȫșȥȦȖȢȕȟȲȘȘȟȳțȔȖȦȤȔȞȔ
ɩ

Для каждого элемента вложенных списков tag — это строка тега, а attrib — это
словарь его атрибутов. Библиотека އ‡–”‡‡ имеет множество других способов
поиска данных, организованных в формате XML, модификации этих данных и даже
записи XML-файлов. Все детали изложены в документации библиотеки އ‡–”‡‡
(KWWSELWO\HOHPHQWWUHH).
Среди других библиотек Python для работы с XML можно отметить следующие:
‰šŽŜ†‘ . The Document Object Model (DOM) (знакомая разработчикам на
JavaScript) представляет веб-документы в виде иерархических структур. Этот
модуль загружает XML-файл в память целиком и позволяет получать доступ ко
всем его частям;
‰šŽŜ•ƒš. Simple API for XML, или SAX, разбирает XML на ходу, поэтому не за-
гружает в память сразу весь документ. Она может быть хорошим выбором, если
нужно обработать очень большие потоки XML.
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

ǷȘȐȔȍȟȈȕȐȍȖȉȍȏȖȗȈșȕȖșȚȐ;0/
Вы можете использовать любой формат, описанный в этой главе, чтобы сохранять
объекты в файлы и снова их читать. Однако при этом существует вероятность полу-
чить проблемы с безопасностью.
Например, в следующем фрагменте XML-файла со страницы «Википедии» об
атаках billion laughs (KWWSVHQZLNLSHGLDRUJZLNL%LOOLRQBODXJKVBDWWDFN) (это разновидность
атаки «отказ в обслуживании») определяется десять вложенных сущностей, каждая
из которых расширяет более низкий уровень в десять раз, порождая в сумме один
миллиард сущностей:
ʳţšŽ˜‡”•‹‘ʰɑɨŜɥɑţʴ
ʳŠŽ‘Žœƃ
ʳŠ Ž‘ŽɑŽ‘Žɑʴ
ʳŠ Ž‘Žɨɑ厑ŽŚĺŽ‘ŽŚĺŽ‘ŽŚĺŽ‘ŽŚĺŽ‘ŽŚĺŽ‘ŽŚĺŽ‘ŽŚĺŽ‘ŽŚĺŽ‘ŽŚĺŽ‘ŽŚɑʴ
ʳŠ Ž‘Žɩɑ厑ŽɨŚĺŽ‘ŽɨŚĺŽ‘ŽɨŚĺŽ‘ŽɨŚĺŽ‘ŽɨŚĺŽ‘ŽɨŚĺŽ‘ŽɨŚĺŽ‘ŽɨŚĺŽ‘ŽɨŚĺŽ‘ŽɨŚɑʴ
ʳŠ Ž‘Žɪɑ厑ŽɩŚĺŽ‘ŽɩŚĺŽ‘ŽɩŚĺŽ‘ŽɩŚĺŽ‘ŽɩŚĺŽ‘ŽɩŚĺŽ‘ŽɩŚĺŽ‘ŽɩŚĺŽ‘ŽɩŚĺŽ‘ŽɩŚɑʴ
ʳŠ Ž‘Žɫɑ厑ŽɪŚĺŽ‘ŽɪŚĺŽ‘ŽɪŚĺŽ‘ŽɪŚĺŽ‘ŽɪŚĺŽ‘ŽɪŚĺŽ‘ŽɪŚĺŽ‘ŽɪŚĺŽ‘ŽɪŚĺŽ‘ŽɪŚɑʴ
ʳŠ Ž‘Žɬɑ厑ŽɫŚĺŽ‘ŽɫŚĺŽ‘ŽɫŚĺŽ‘ŽɫŚĺŽ‘ŽɫŚĺŽ‘ŽɫŚĺŽ‘ŽɫŚĺŽ‘ŽɫŚĺŽ‘ŽɫŚĺŽ‘ŽɫŚɑʴ
ʳŠ Ž‘Žɭɑ厑ŽɬŚĺŽ‘ŽɬŚĺŽ‘ŽɬŚĺŽ‘ŽɬŚĺŽ‘ŽɬŚĺŽ‘ŽɬŚĺŽ‘ŽɬŚĺŽ‘ŽɬŚĺŽ‘ŽɬŚĺŽ‘ŽɬŚɑʴ
ʳŠ Ž‘Žɮɑ厑ŽɭŚĺŽ‘ŽɭŚĺŽ‘ŽɭŚĺŽ‘ŽɭŚĺŽ‘ŽɭŚĺŽ‘ŽɭŚĺŽ‘ŽɭŚĺŽ‘ŽɭŚĺŽ‘ŽɭŚĺŽ‘ŽɭŚɑʴ
ʳŠ Ž‘Žɯɑ厑ŽɮŚĺŽ‘ŽɮŚĺŽ‘ŽɮŚĺŽ‘ŽɮŚĺŽ‘ŽɮŚĺŽ‘ŽɮŚĺŽ‘ŽɮŚĺŽ‘ŽɮŚĺŽ‘ŽɮŚĺŽ‘ŽɮŚɑʴ
ʳŠ Ž‘Žɰɑ厑ŽɯŚĺŽ‘ŽɯŚĺŽ‘ŽɯŚĺŽ‘ŽɯŚĺŽ‘ŽɯŚĺŽ‘ŽɯŚĺŽ‘ŽɯŚĺŽ‘ŽɯŚĺŽ‘ŽɯŚĺŽ‘ŽɯŚɑʴ
Ƅʴ
ʳŽ‘Žœʴ厑ŽɰŚʳŵŽ‘Žœʴ

Плохая новость: атака подорвет работоспособность всех XML-библиотек, упо-


мянутых в предыдущем подразделе. На ресурсе Defused XML (KWWSVELWEXFNHWRUJ
WLUDQGHIXVHG[PO) эта и другие атаки перечислены наряду с уязвимостями библиотек
Python. Перейдя по ссылке, вы увидите, как изменять настройки многих библиотек
так, чтобы избежать подобных проблем. Вы также можете использовать библиотеку
†‡ˆ—•‡†šŽ в качестве внешнего интерфейса безопасности для других библиотек:
ʴʴʴɤȡșȕșțȢȣȔȥȡȢś
ʴʴʴˆ”‘šŽŜ‡–”‡‡Ŝއ‡–”‡‡‹’‘”–’ƒ”•‡
ʴʴʴ‡–ʰ’ƒ”•‡ſšŽˆ‹Ž‡ƀ
ʴʴʴɤȕșțȢȣȔȥȡȢś
ʴʴʴˆ”‘†‡ˆ—•‡†šŽŜއ‡–”‡‡‹’‘”–’ƒ”•‡
ʴʴʴ‡–ʰ’ƒ”•‡ſšŽˆ‹Ž‡ƀ

Стандартный сайт Python также имеет свою собственную страницу об уязвимо-


стях XML.

+70/
Огромные объемы данных сохраняются в формате гипертекстового языка размет-
ки — Hypertext Markup Language (HTML). Это основной формат документов в Ин-
тернете. Проблема заключается в том, что значительная часть этих документов не со-
ответствует правилам формата HTML, что затрудняет анализ. Кроме того, большая
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

часть HTML предназначена для форматирования выводимой информации, а не для


обмена данными. Поскольку эта глава предназначена для описания относительно
хорошо определенных форматов данных, я вынес рассмотрение HTML в главу 18.

-621
JavaScript Object Notation (JSON) (KWWSZZZMVRQRUJ) стал очень популярным
форматом обмена данными, вышедшим за пределы языка JavaScript. Формат JSON
является частью языка JavaScript и часто содержит легальный с точки зрения
Python синтаксис. Он прекрасно подходит Python, что делает его хорошим выбором
для обмена данными между программами. Вы увидите множество примеров JSON
для веб-разработки в главе 18.
В отличие от XML, для которого написано множество модулей, для JSON су-
ществует всего один модуль с простым именем Œ•‘. Эта программа кодирует (вы-
гружает) данные в строку JSON и декодирует (загружает) строку JSON обратно.
В следующем примере мы создадим структуру данных, содержащую данные из
более раннего примера XML:
ʴʴʴ‡—ʰɎ
ŜŜŜƇ
ŜŜŜɑ„”‡ƒˆƒ•–ɑśƇ
ŜŜŜɑŠ‘—”•ɑśɑɮŞɨɨɑř
ŜŜŜɑ‹–‡•ɑśƇ
ŜŜŜɑ„”‡ƒˆƒ•–„—””‹–‘•ɑśɑɛɭŜɥɥɑř
ŜŜŜɑ’ƒ ƒ‡•ɑśɑɛɫŜɥɥɑ
ŜŜŜƈ
ŜŜŜƈř
ŜŜŜɑŽ— ŠɑśƇ
ŜŜŜɑŠ‘—”•ɑśɑɨɨŞɪɑř
ŜŜŜɑ‹–‡•ɑśƇ
ŜŜŜɑŠƒ„—”‰‡”ɑśɑɛɬŜɥɥɑ
ŜŜŜƈ
ŜŜŜƈř
ŜŜŜɑ†‹‡”ɑśƇ
ŜŜŜɑŠ‘—”•ɑśɑɪŞɨɥɑř
ŜŜŜɑ‹–‡•ɑśƇ
ŜŜŜɑ•’ƒ‰Š‡––‹ɑśɑɛɯŜɥɥɑ
ŜŜŜƈ
ŜŜŜƈ
ŜŜŜƈ
Ŝ

Далее закодируем структуру данных ‡— в строку JSON ‡—ɏŒ•‘ с помощью


функции †—’•ſƀ:
ʴʴʴ‹’‘”–Œ•‘
ʴʴʴ‡—ɏŒ•‘ʰŒ•‘Ŝ†—’•ſ‡—ƀ
ʴʴʴ‡—ɏŒ•‘
ɐƇɑ†‹‡”ɑśƇɑ‹–‡•ɑśƇɑ•’ƒ‰Š‡––‹ɑśɑɛɯŜɥɥɑƈřɑŠ‘—”•ɑśɑɪŞɨɥɑƈř
ɑŽ— ŠɑśƇɑ‹–‡•ɑśƇɑŠƒ„—”‰‡”ɑśɑɛɬŜɥɥɑƈřɑŠ‘—”•ɑśɑɨɨŞɪɑƈř
ɑ„”‡ƒˆƒ•–ɑśƇɑ‹–‡•ɑśƇɑ„”‡ƒˆƒ•–„—””‹–‘•ɑśɑɛɭŜɥɥɑřɑ’ƒ ƒ‡•ɑś
ɑɛɫŜɥɥɑƈřɑŠ‘—”•ɑśɑɮŞɨɨɑƈƈɐ
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

А теперь превратим строку JSON ‡—ɏŒ•‘ обратно в структуру данных ‡—ɩ


с помощью функции Ž‘ƒ†•ſƀ:
ʴʴʴ‡—ɩʰŒ•‘ŜŽ‘ƒ†•ſ‡—ɏŒ•‘ƀ
ʴʴʴ‡—ɩ
Ƈɐ„”‡ƒˆƒ•–ɐśƇɐ‹–‡•ɐśƇɐ„”‡ƒˆƒ•–„—””‹–‘•ɐśɐɛɭŜɥɥɐřɐ’ƒ ƒ‡•ɐś
ɐɛɫŜɥɥɐƈřɐŠ‘—”•ɐśɐɮŞɨɨɐƈřɐŽ— ŠɐśƇɐ‹–‡•ɐśƇɐŠƒ„—”‰‡”ɐśɐɛɬŜɥɥɐƈř
ɐŠ‘—”•ɐśɐɨɨŞɪɐƈřɐ†‹‡”ɐśƇɐ‹–‡•ɐśƇɐ•’ƒ‰Š‡––‹ɐśɐɛɯŜɥɥɐƈřɐŠ‘—”•ɐśɐɪŞɨɥɐƈƈ

‡— и ‡—ɩ являются словарями с одинаковыми ключами и значениями.


Вы можете получить исключение, пытаясь закодировать или декодировать не-
которые объекты, например †ƒ–‡–‹‡ (этот вопрос детально рассматривается в гла-
ве 13), как показано здесь:
ʴʴʴ‹’‘”–†ƒ–‡–‹‡
ʴʴʴ‹’‘”–Œ•‘
ʴʴʴ‘™ʰ†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡Ŝ—– ‘™ſƀ
ʴʴʴ‘™
†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ſɩɥɨɪřɩřɩɩřɪřɫɰřɩɮřɫɯɪɪɪɭƀ
ʴʴʴŒ•‘Ŝ†—’•ſ‘™ƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
ɤŜŜŜſȢȣȧȥȦȜȟȜȥȦșȞȖȯțȢȖȢȖřȫȦȢȕȯȥȣȔȥȦȜȘșȤșȖȰȳƀ
›’‡””‘”ś†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ſɩɥɨɪřɩřɩɩřɪřɫɰřɩɮřɫɯɪɪɪɭƀ‹•‘– 
•‡”‹ƒŽ‹œƒ„އ
ʴʴʴ

Это может случиться, поскольку стандарт JSON не определяет типы даты или
времени — он ожидает, что вы укажете ему, как с ними работать. Вы можете преоб-
разовать формат †ƒ–‡–‹‡ в то, что JSON понимает, например в строку или значение
времени ‡’‘ Š (см. главу 13):
ʴʴʴ‘™ɏ•–”ʰ•–”ſ‘™ƀ
ʴʴʴŒ•‘Ŝ†—’•ſ‘™ɏ•–”ƀ
ɐɑɩɥɨɪŞɥɩŞɩɩɥɪśɫɰśɩɮŜɫɯɪɪɪɭɑɐ
ʴʴʴˆ”‘–‹‡‹’‘”––‹‡
ʴʴʴ‘™ɏ‡’‘ Šʰ‹–ſ–‹‡ſ‘™Ŝ–‹‡–—’އſƀƀƀ
ʴʴʴŒ•‘Ŝ†—’•ſ‘™ɏ‡’‘ Šƀ
ɐɨɪɭɨɬɩɭɬɭɮɐ

Если значение †ƒ–‡–‹‡ встретится между обычно сконвертированными типами


данных, может быть неудобно выполнять такие особые преобразования. Вы мо-
жете изменить способ кодирования JSON с помощью наследования, описанного
в главе 10. Документация JSON для Python (KWWSVGRFVS\WKRQRUJOLEUDU\MVRQKWPO)
содержит пример такого переопределения для комплексных чисел, что также за-
ставляет JSON притвориться мертвым. Напишем переопределение для †ƒ–‡–‹‡:
ʴʴʴ‹’‘”–†ƒ–‡–‹‡
ʴʴʴ‘™ʰ†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡Ŝ—– ‘™ſƀ
ʴʴʴ Žƒ•• ‘†‡”ſŒ•‘Ŝ  ‘†‡”ƀś
ŜŜŜ†‡ˆ†‡ˆƒ—Ž–ſ•‡Žˆř‘„Œƀś
ŜŜŜɤ‹•‹•–ƒ ‡ſƀ Ї •–Ї–›’‡‘ˆ‘„Œ
ŜŜŜ‹ˆ‹•‹•–ƒ ‡ſ‘„Œř†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ƀś
ŜŜŜ”‡–—”‹–ſ–‹‡ſ‘„ŒŜ–‹‡–—’އſƀƀƀ
ŜŜŜɤ‡Ž•‡‹–ɐ••‘‡–Š‹‰–Ї‘”ƒŽ†‡ ‘†‡”‘™•ś
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ŜŜŜ”‡–—”Œ•‘Ŝ  ‘†‡”Ŝ†‡ˆƒ—Ž–ſ•‡Žˆř‘„Œƀ


ŜŜŜ
ʴʴʴŒ•‘Ŝ†—’•ſ‘™ř Ž•ʰ ‘†‡”ƀ
ɐɨɪɭɨɬɩɭɬɭɮɐ

Новый класс  ‘†‡” является подклассом, или классом-потомком, класса


 ‘†‡”. Нам нужно лишь переопределить его метод †‡ˆƒ—Ž–ſƀ, добавив об-
работку †ƒ–‡–‹‡. Наследование гарантирует, что все остальное будет обработано
родительским классом.
Функция ‹•‹•–ƒ ‡ſƀ проверяет, является ли объект ‘„Œ объектом класса
†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡. Поскольку в Python все является объектом, функция ‹•‹•–ƒ ‡ſƀ
работает везде:
ʴʴʴ‹’‘”–†ƒ–‡–‹‡
ʴʴʴ‘™ʰ†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡Ŝ—– ‘™ſƀ
ʴʴʴ–›’‡ſ‘™ƀ
ʳ Žƒ••ɐ†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ɐʴ
ʴʴʴ‹•‹•–ƒ ‡ſ‘™ř†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ƀ
”—‡
ʴʴʴ–›’‡ſɩɪɫƀ
ʳ Žƒ••ɐ‹–ɐʴ
ʴʴʴ‹•‹•–ƒ ‡ſɩɪɫř‹–ƀ
”—‡
ʴʴʴ–›’‡ſɐЇ›ɐƀ
ʳ Žƒ••ɐ•–”ɐʴ
ʴʴʴ‹•‹•–ƒ ‡ſɐЇ›ɐř•–”ƀ
”—‡

ǷȘȐȘȈȉȖȚȍș-621ȐȌȘțȋȐȔȐȜȖȘȔȈȚȈȔȐșȚȘțȒȚțȘȐȘȖȊȈȕȕȖȋȖȚȍȒșȚȈȊȣȔȖȎȍȚȍ
ȏȈȋȘțȏȐȚȤȜȈȑȓȊȗȈȔȧȚȤȐȘȈȏȔȍșȚȐȚȤȍȋȖȊșȚȘțȒȚțȘȍȌȈȕȕȣȝȕȍȏȕȈȧȖșȈȔȐȝ
șȚȘțȒȚțȘȈȝȏȈȘȈȕȍȍǯȈȚȍȔȊȣȔȖȎȍȚȍȗȘȖȑȚȐșȤȗȖșȚȘțȒȚțȘȈȔȐșȗȖȓȤȏțȧȜțȕȒȞȐȦ
LVLQVWDQFH ȐȔȍȚȖȌȣșȖȖȚȊȍȚșȚȊțȦȡȐȍȚȐȗțȟȚȖȉȣȗȘȖȊȍȘȐȚȤȏȕȈȟȍȕȐȧșȚȘțȒȚțȘ
ǵȈȗȘȐȔȍȘȍșȓȐȖȌȐȕȐȏȥȓȍȔȍȕȚȖȊȧȊȓȧȍȚșȧșȓȖȊȈȘȍȔȊȣȔȖȎȍȚȍȐȏȊȓȍȟȤȍȋȖșȖ
ȌȍȘȎȐȔȖȍșȗȖȔȖȡȤȦȜțȕȒȞȐȑNH\V YDOXHV ȐLWHPV 

После того как вы сделали это сложным способом, сообщу вам, что существует
более простой способ преобразовать объекты типа †ƒ–‡–‹‡ в JSON:
ʴʴʴ‹’‘”–†ƒ–‡–‹‡
ʴʴʴ‹’‘”–Œ•‘
ʴʴʴ‘™ʰ†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡Ŝ—– ‘™ſƀ
ʴʴʴŒ•‘Ŝ†—’•ſ‘™ř†‡ˆƒ—Ž–ʰ•–”ƀ
ɐɑɩɥɨɰŞɥɫŞɨɮɩɨśɬɫśɫɪŜɭɨɮɪɪɮɑɐ

Инструкция †‡ˆƒ—Ž–ʰ•–” указывает функции Œ•‘Ŝ†—’•ſƀ применить функцию


преобразования •–”ſƀ к тем типам данных, которые она не понимает. Это сработает,
поскольку в определении класса †ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ присутствует метод ɏɏ•–”ɏɏſƀ.
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

<$0/
Как и JSON, YAML (KWWSZZZ\DPORUJ) имеет ключи и значения, но обрабатывает
большее количество типов данных, включая дату и время. Стандартная библиотека
Python не содержит модулей, работающих с YAML, поэтому вам нужно установить
стороннюю библиотеку ›ƒŽ (KWWSS\\DPORUJZLNL3\<$0/). Функция Ž‘ƒ†ſƀ преоб-
разует строку в формате YAML к данным Python, а функция †—’ſƀ предназначена
для противоположного действия.
Следующий YAML-файл,  ‹–›”‡Ŝ›ƒŽ, содержит информацию о канадском
поэте Джеймсе Макинтайре и два его стихотворения:
ƒ‡ś
ˆ‹”•–ś ƒ‡•
Žƒ•–ś –›”‡
†ƒ–‡•ś
„‹”–ŠśɨɯɩɯŞɥɬŞɩɬ
†‡ƒ–ŠśɨɰɥɭŞɥɪŞɪɨ
†‡–ƒ‹Ž•ś
„‡ƒ”†‡†ś–”—‡
–Ї‡•śƃ Ї‡•‡řƒƒ†ƒƄ
„‘‘•ś
—”ŽśŠ––’śŵŵ™™™Ŝ‰—–‡„‡”‰Ŝ‘”‰ŵˆ‹Ž‡•ŵɪɭɥɭɯŵɪɭɥɭɯŞŠŵɪɭɥɭɯŞŠŜŠ–
’‘‡•ś
Ş–‹–އśɐ‘––‘ɐ
–‡š–śŶ
‘Ž‹–‡‡••ř’‡”•‡˜‡”ƒ ‡ƒ†’Ž— ř
‘–Ї‹”’‘••‡••‘”™‹ŽŽ„”‹‰‰‘‘†Ž— Ŝ
Ş–‹–އśɐƒƒ†‹ƒŠƒ”•ɐ
–‡š–śŶ
 ‡”‡‹†—•–”›‹•‘–‹˜ƒ‹ř
 ‘”™‡Šƒ˜‡„‘—–‡‘—• ”‘’•‘ˆ‰”ƒ‹ř
†›‘—„‡Š‘ކ‘‡˜‡”›ˆ‹‡Ž†
ˆ‰”ƒ••ƒ†”‘‘–•ƒ„—†ƒ–›‹‡Ž†ř
—–ƒˆ–‡”ƒŽŽ–Ї‰”‡ƒ–‡•– Šƒ”
 •–Ї•—‰Š‘‡—’‘–Їˆƒ”ř
†•–‘‡™ƒŽŽ•‘™‡‡’ ƒ––އ™ƒ”Ŝ

Такие значения, как true, false, on и off, преобразуются в булевы переменные.


Целые числа и строки преобразуются в их эквиваленты в Python. Для остального
синтаксиса создаются списки и словари:
ʴʴʴ‹’‘”–›ƒŽ
ʴʴʴ™‹–Š‘’‡ſɐ ‹–›”‡Ŝ›ƒŽɐřɐ”–ɐƀƒ•ˆ‹ś
ʴʴʴ–‡š–ʰˆ‹Ŝ”‡ƒ†ſƀ
ʴʴʴ†ƒ–ƒʰ›ƒŽŜŽ‘ƒ†ſ–‡š–ƀ
ʴʴʴ†ƒ–ƒƃɐ†‡–ƒ‹Ž•ɐƄ
Ƈɐ–Ї‡•ɐśƃɐ Ї‡•‡ɐřɐƒƒ†ƒɐƄřɐ„‡ƒ”†‡†ɐś”—‡ƈ
ʴʴʴއſ†ƒ–ƒƃɐ’‘‡•ɐƄƀ
ɩ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Создаваемые структуры данных совпадают со структурами YAML-файла, ко-


торые в данном случае имеют глубину более одного уровня. Вы можете получить
заголовок второго стихотворения с помощью следующей ссылки:
ʴʴʴ†ƒ–ƒƃɐ’‘‡•ɐƄƃɨƄƃɐ–‹–އɐƄ
ɐƒƒ†‹ƒŠƒ”•ɐ

3\<$0/ȔȖȎȍȚȏȈȋȘțȎȈȚȤȖȉȢȍȒȚȣ3\WKRQȐȏșȚȘȖȒȈȥȚȖȖȗȈșȕȖǰșȗȖȓȤȏțȑȚȍȔȍȚȖȌ
VDIHBORDG  ȊȔȍșȚȖ ȔȍȚȖȌȈ ORDG  ȍșȓȐ ȐȔȗȖȘȚȐȘțȍȚȍ ȌȈȕȕȣȍ Ȋ ȜȖȘȔȈȚȍ <$0/
ȒȖȚȖȘȣȔȕȍȌȖȊȍȘȧȍȚȍǨȓțȟȠȍȊșȍȋȌȈȐșȗȖȓȤȏțȑȚȍȔȍȚȖȌVDIHBORDG ǷȘȖȟȚȐȚȍ
șȚȈȚȤȦ ǵȍȌȈ ǩȈȚȟȍȓȌȍȘȈ :DU LV SHDFH KWWSQHGEDWFKHOGHUFRPEORJ
ZDUBLVBSHDFHKWPO ȟȚȖȉȣțȏȕȈȚȤȖȚȖȔȒȈȒȕȍȏȈȡȐȡȍȕȕȈȧȏȈȋȘțȏȒȈ<$0/șȒȖȔ
ȗȘȖȔȍȚȐȘȖȊȈȓȈȗȓȈȚȜȖȘȔț5XE\RQ5DLOV

7DEOLE
Теперь, когда вы прочитали все предыдущие разделы, я расскажу вам, что существу-
ет сторонний пакет, который позволяет импортировать, экспортировать и изменять
табличные данные в форматах CSV, JSON или YAML1, а также данные в Microsoft
Excel, Pandas DataFrame и некоторые другие. Вы можете установить его при-
вычным способом (pip install tablib), а также заглянуть в документацию (KWWS
GRFVS\WKRQWDEOLERUJHQPDVWHU).

3DQGDV
Сейчас самое время познакомиться с Pandas (KWWSVSDQGDVS\GDWDRUJ) — библиотекой
Python для структурированных данных. Это отличный инструмент для решения
реальных проблем с данными. Она позволяет:
‰читать и записывать данные во множестве текстовых и бинарных форматов,
таких как:
y текст, поля которого разделены запятыми (CSV), символами табуляции (TSV)
или другими символами;
y текст фиксированной длины;
y Excel;
y JSON;
y таблицы HTML;
y SQL;
y HDF5;
y и др. (KWWSVSDQGDVS\GDWDRUJSDQGDVGRFVVWDEOHXVHUBJXLGHLRKWPO);

1
Однако на данный момент XML не поддерживается.
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

‰группировать, разбивать, объединять, разделять, сортировать, выбирать и по-


мечать;
‰преобразовывать типы данных;
‰изменять размер или форму;
‰обрабатывать случаи, когда данные отсутствуют;
‰генерировать случайные значения;
‰управлять временными последовательностями.
Функции чтения возвращают объект типа ƒ–ƒ ”ƒ‡ (KWWSVSDQGDVS\GDWDRUJ
SDQGDVGRFVVWDEOHUHIHUHQFHDSLSDQGDV'DWD)UDPHKWPO). Это является стандартным пред-
ставлением для двумерных данных (которые делятся на строки и столбцы) в Pandas.
Объект этого типа похож на электронную таблицу или таблицу реляционной базы
данных. Его одномерный младший брат называется ‡”‹‡• (KWWSVSDQGDVS\GDWDRUJ
SDQGDVGRFVVWDEOHUHIHUHQFHVHULHVKWPO).
В примере 16.2 показывается простое приложение, которое считывает данные из
нашего файла ˜‹ŽŽƒ‹•Ŝ •˜ из примера 16.1.

ǷȘȐȔȍȘǿȐȚȈȍȔȌȈȕȕȣȍȊȜȖȘȔȈȚȍ&69șȗȖȔȖȡȤȦ3DQGDV
ʴʴʴ‹’‘”–’ƒ†ƒ•
ʴʴʴ
ʴʴʴ†ƒ–ƒʰ’ƒ†ƒ•Ŝ”‡ƒ†ɏ •˜ſɐ˜‹ŽŽƒ‹•Ŝ •˜ɐƀ
ʴʴʴ’”‹–ſ†ƒ–ƒƀ
ˆ‹”•–Žƒ•–
ɥ‘ –‘”‘
ɨ‘•ƒއ„„
ɩ‹•–‡”‹‰
ɪ—”‹  ‘ކˆ‹‰‡”
ɫ”•–Ž‘ˆ‡Ž†

Переменная †ƒ–ƒ имеет тип ƒ–ƒ ”ƒ‡: у этого типа данных возможностей боль-
ше, чем у простого словаря Python. Он особенно полезен для обработки большого
количества чисел с помощью NumPy, а также для подготовки данных для машинного
обучения.
Обратитесь к разделам Getting Started (KWWSVSDQGDVS\GDWDRUJSDQGDVGRFVVWDEOH
JHWWLQJBVWDUWHGLQGH[KWPO) документации Pandas, чтобы узнать подробнее о ее осо-
бенностях, и к разделу 10 Minutes to Pandas (KWWSVSDQGDVS\GDWDRUJSDQGDVGRFVVWDEOH
JHWWLQJBVWDUWHGPLQKWPO) для того, чтобы увидеть рабочие примеры.
Воспользуемся Pandas для того, чтобы создать небольшой календарь — список,
содержащий первый день первых трех месяцев 2019 года:
ʴʴʴ‹’‘”–’ƒ†ƒ•
ʴʴʴ†ƒ–‡•ʰ’ƒ†ƒ•Ŝ†ƒ–‡ɏ”ƒ‰‡ſɐɩɥɨɰŞɥɨŞɥɨɐř’‡”‹‘†•ʰɪřˆ”‡“ʰɐɐƀ
ʴʴʴ†ƒ–‡•
ƒ–‡–‹‡ †‡šſƃɐɩɥɨɰŞɥɨŞɥɨɐřɐɩɥɨɰŞɥɩŞɥɨɐřɐɩɥɨɰŞɥɪŞɥɨɐƄř
†–›’‡ʰɐ†ƒ–‡–‹‡ɭɫƃ•Ƅɐřˆ”‡“ʰɐɐƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Создать такой календарь можно было бы и с помощью функций даты и време-


ни, которые мы рассмотрели в главе 13. Но это намного сложнее, особенно отладка
(дата и время добавляют работы). Pandas также позволяет обрабатывать множество
особых деталей даты и времени (KWWSVSDQGDVS\GDWDRUJSDQGDVGRFVVWDEOHXVHUBJXLGH
WLPHVHULHVKWPO), например бизнес-месяцы и годы.
Мы еще поговорим о Pandas, когда речь пойдет о картах (см. подраздел «Geopandas»
на с. 498) и научных приложениях (см. раздел «Pandas» на с. 516).

DzȖȕȜȐȋțȘȈȞȐȖȕȕȣȍȜȈȑȓȣ
Большинство программ предлагают различные параметры или настройки. Дина-
мические настройки могут быть переданы как аргументы программы, но долговре-
менные настройки должны где-то храниться. Соблазн на скорую руку определить
собственный формат конфигурационного файла очень силен, но вы должны устоять.
Как правило, это бывает и неточно, и не так уж быстро. Вам нужно обслуживать
как программу-писатель, так и программу-читатель (которая иногда называется
парсером). Существуют хорошие альтернативы, которые вы можете добавить в свою
программу, включая те, что были показаны в предыдущих подразделах.
Здесь мы используем стандартный модуль ‘ˆ‹‰’ƒ”•‡”, который обрабатывает
файлы с расширением Ŝ‹‹, характерные для Windows. Такие файлы имеют разделы
с определениями ȞȟȲȫ ʰ țȡȔȫșȡȜș. Так выглядит минимальный файл •‡––‹‰•Ŝ ˆ‰:
ƃ‡‰Ž‹•ŠƄ
‰”‡‡–‹‰ʰ ‡ŽŽ‘

ƃˆ”‡ ŠƄ
‰”‡‡–‹‰ʰ‘Œ‘—”

ƃˆ‹Ž‡•Ƅ
Š‘‡ʰŵ—•”ŵŽ‘ ƒŽ
ɤ•‹’އ‹–‡”’‘Žƒ–‹‘ś
„‹ʰʩſŠ‘‡ƀ•ŵ„‹

А так выглядит код, который позволяет считать его и разместить в структурах


данных:
ʴʴʴ‹’‘”– ‘ˆ‹‰’ƒ”•‡”
ʴʴʴ ˆ‰ʰ ‘ˆ‹‰’ƒ”•‡”Ŝ‘ˆ‹‰ƒ”•‡”ſƀ
ʴʴʴ ˆ‰Ŝ”‡ƒ†ſɐ•‡––‹‰•Ŝ ˆ‰ɐƀ
ƃɐ•‡––‹‰•Ŝ ˆ‰ɐƄ
ʴʴʴ ˆ‰
ʳ ‘ˆ‹‰’ƒ”•‡”Ŝ‘ˆ‹‰ƒ”•‡”‘„Œ‡ –ƒ–ɥšɨɥɥɭ„‡ɫ†ɥʴ
ʴʴʴ ˆ‰ƃɐˆ”‡ ŠɐƄ
ʳ‡ –‹‘śˆ”‡ Šʴ
ʴʴʴ ˆ‰ƃɐˆ”‡ ŠɐƄƃɐ‰”‡‡–‹‰ɐƄ
ɐ‘Œ‘—”ɐ
ʴʴʴ ˆ‰ƃɐˆ‹Ž‡•ɐƄƃɐ„‹ɐƄ
ɐŵ—•”ŵŽ‘ ƒŽŵ„‹ɐ
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

Доступны и другие опции, в том числе более мощная интерполяция. Обратитесь


к документации ‘ˆ‹‰’ƒ”•‡” (KWWSELWO\FRQILJSDUVHU). Если вам нужно более двух
уровней вложенности, попробуйте использовать YAML или JSON.

ǩȐȕȈȘȕȣȍȜȈȑȓȣ
Некоторые файловые форматы были разработаны для хранения определенных
структур данных и не являются ни реляционными базами данных, ни базами данных
NoSQL. В следующих подразделах рассказывается о некоторых из них.
Заполненные пробелами бинарные файлы и управление памятью. Такие файлы
похожи на заполненные пробелами текстовые файлы, но содержимое может быть
бинарным, а в качестве заполнителя может использоваться байт Ɏšɥɥ. Каждая за-
пись имеет фиксированный размер, как и каждое поле внутри записи. Это позволяет
легче искать нужные записи и поля с помощью функции •‡‡ſƀ. Каждая операция
с данными выполняется вручную, поэтому такой подход должен применяться только
в очень низкоуровневых (близких к «железу») ситуациях.
Данные в таком формате могут быть размещены в ОЗУ с помощью стандартной
библиотеки ƒ’. Взгляните на примеры (KWWSVS\PRWZFRPPPDS) и стандартную
документацию (KWWSVGRFVS\WKRQRUJOLEUDU\PPDSKWPO).

ȅȓȍȒȚȘȖȕȕȣȍȚȈȉȓȐȞȣ
Электронные таблицы, в частности Microsoft Excel, — это широко распространенный
бинарный формат данных. Если вы можете сохранить свою таблицу в CSV-файл, то
можете считать его с помощью стандартного модуля •˜, который был описан ранее.
Это распространяется на бинарный файл šŽ•: для его считывания и записи можно
использовать стороннюю библиотеку šŽ”† (KWWSVS\SLRUJSURMHFW[OUG) или tablib (она
упоминалась ранее в подразделе «Tablib» на с. 338).

+')
HDF5 (KWWSZZZKGIJURXSRUJZK\BKGI) — это бинарный формат данных, предназначен-
ный для хранения многомерных или иерархических числовых данных. Обычно он
используется в научных целях, где быстрый случайный доступ к крупным наборам
данных (от гигабайтов до терабайтов) является распространенным требованием.
Несмотря на то что HDF5 в некоторых случаях мог бы стать хорошей альтернативой
базам данных, по каким-то причинам этот формат практически неизвестен в современ-
ном мире. Он лучше всего подходит для приложений вида WORM (write once — read
many — «запиши однажды — считай много раз»), которые не нуждаются в защите от
конфликтующих записей. Вам могут быть полезными следующие модули:
‰Šɬ’› — интерфейс низкого уровня с широкими возможностями. Прочтите его
документацию (KWWSZZZKS\RUJ) и код (KWWSVJLWKXEFRPKS\KS\);
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰›ƒ„އ• — интерфейс немного более высокого уровня, имеющий некоторые


особенности, характерные для баз данных. Прочтите его документацию (KWWS
ZZZS\WDEOHVRUJ) и код (KWWSS\WDEOHVJLWKXEFRP).

Оба этих формата рассматриваются в главе 22 с точки зрения применения в науч-


ных приложениях, написанных на Python. Здесь я упоминаю об HDF5 затем, чтобы
у вас был под рукой нестандартный вариант на случай, когда вам нужно сохранять
и высчитывать крупные объемы данных. Хорошим примером использования этого
формата является Million Song Dataset (KWWSELWO\PLOOLRQVRQJ) с записями песен
в форматах HDF5 и SQLite.

7LOH'%
У формата HDF5 недавно появился последователь, который позволяет хранить
как плотные, так и разреженные массивы — TileDB (KWWSVWLOHGEFRP). Установите
интерфейс Python (KWWSVJLWKXEFRP7LOH'%,QF7LOH'%3\) (он включает в себя и саму
библиотеку TileDB), запустив команду pip install –‹Ž‡†„. Эта библиотека предна-
значена для работы с научными данными и приложениями.

ǸȍȓȧȞȐȖȕȕȣȍȉȈȏȣȌȈȕȕȣȝ
Реляционным базам данных всего около 40 лет, но в компьютерном мире они ис-
пользуются повсеместно. Вам практически наверняка придется поработать с ними.
В эти моменты вы сможете оценить следующие их преимущества.
‰Доступ к данным возможен для нескольких пользователей одновременно.
‰Действует защита от повреждения данных пользователями.
‰Существуют эффективные методы сохранения и считывания данных.
‰Данные определены схемами и имеют ограничения.
‰Объединения позволяют найти отношения между различными типами данных.
‰Декларативный (в противоположность императивному) язык запросов SQL
(Structured Query Language).
Такие базы данных называются реляционными, поскольку они показывают
отношения между различными типами данных в форме прямоугольных таблиц.
Например, в нашем более раннем примере меню есть отношение между каждым
элементом и его ценой.
Таблица представляет собой прямоугольную сетку столбцов (полей данных)
и строк (отдельных записей), похожую на электронную таблицу. Пересечение стро-
ки и столбца называется ячейкой. Чтобы создать таблицу, необходимо указать ее имя
и порядок, имена и типы ее столбцов. Каждая строка имеет одинаковые столбцы,
хотя столбец может быть определен так, чтобы в ячейках отсутствовали данные
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

(null ). В примере с меню вы могли бы создать таблицу, содержащую по одной


строке для каждого продаваемого элемента. Каждый элемент имеет одинаковые
столбцы, включая и тот, который хранит цену.
Первичным ключом таблицы является столбец или группа столбцов. Значения
ключа должны быть уникальными — таким образом предотвращается ввод одина-
ковых данных в таблицу. Этот ключ индексируется для быстрого поиска во время
выполнения запроса. Работа индекса немного похожа на работу алфавитного ука-
зателя, который позволяет быстро найти определенный ряд.
Каждая таблица находится внутри родительской базы данных, как файлы
в каталоге. Два уровня иерархии позволяют немного лучше организовывать
данные.

ǬȈșȓȖȊȖșȖȟȍȚȈȕȐȍ©ȉȈȏȈȌȈȕȕȣȝªȐșȗȖȓȤȏțȍȚșȧȊȘȈȏȕȣȝȏȕȈȟȍȕȐȧȝȕȈȏȣȊȈȍȚ
ȐșȍȘȊȍȘȐȝȘȈȕȐȓȐȡȍȚȈȉȓȐȞȐșȈȔȐȌȈȕȕȣȍǭșȓȐȊȈȔȕțȎȕȖȋȖȊȖȘȐȚȤȖȉȖȊșȍȝ
ȕȐȝ ȖȌȕȖȊȘȍȔȍȕȕȖ ȔȖȎȕȖ ȐșȗȖȓȤȏȖȊȈȚȤ ȚȍȘȔȐȕȣ ©șȍȘȊȍȘ ȉȈȏȣ ȌȈȕȕȣȝª ©ȉȈȏȈ
ȌȈȕȕȣȝªȐ©ȌȈȕȕȣȍª

Если вы хотите найти строки по определенному неключевому значению, опреде-


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

64/
SQL не является API или протоколом. Это декларативный язык: вы говорите, что
вам нужно, а не как это сделать. SQL — универсальный язык реляционных баз дан-
ных. Запросы SQL являются текстовыми строками: клиент отсылает их серверу базы
данных, а тот определяет, что с ними делать дальше.
Существует несколько стандартов определения SQL, но все поставщики баз дан-
ных добавили свои собственные настройки и расширения, что привело к появлению
множества диалектов SQL. Если вы храните данные в реляционной базе данных,
SQL дает вам некоторую переносимость данных. Однако наличие диалектов и опе-
рационных различий может усложнить перенос данных в другую базу.
Есть две основные категории утверждений SQL.
‰DDL (Data Definition Language — язык определения данных). Обрабатывает
создание, удаление, ограничения и разрешения для таблиц, баз данных и поль-
зователей.
‰DML (Data Manipulation Language — язык манипулирования данными). Обраба-
тывает добавление данных, их выборку, обновление и удаление.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

В табл. 16.1 перечислены основные команды SQL DDL.


ǺȈȉȓȐȞȈǶșȕȖȊȕȣȍȒȖȔȈȕȌȣ64/''/

ǶȗȍȘȈȞȐȧ ȀȈȉȓȖȕ64/ ǷȘȐȔȍȘ64/


Создание базы данных CREATE DATABASE имя_базы CREATE DATABASE d
Выбор текущей базы данных USE имя_базы USE d
Удаление базы данных и ее DROP DATABASE имя_базы DROP DATABASE d
таблиц
Создание таблицы CREATE TABLE имя_таблицы CREATE TABLE t
(описания_столбцов) (id INT, count INT)
Удаление таблицы DROP TABLE имя_таблицы DROP TABLE t
Удаление всех строк таблицы TRUNCATE TABLE имя_таблицы TRUNCATE TABLE t

ǷȖȟȍȔțȊșȍȗȐȠȍȚșȧǩǶdzȄȀǰǴǰǩǻDzǪǨǴǰ"ȇȏȣȒ64/ȕȍȏȈȊȐșȐȚȖȚȘȍȋȐșȚȘȈȕȖ
ȗȖȚȘȈȌȐȞȐȐ ȕȍșȗȘȈȠȐȊȈȑȚȍȔȍȕȧȗȖȟȍȔț ȒȓȦȟȍȊȣȍșȓȖȊȈǪȃDzǸǰDzǰǪǨȆǺǹȇ
ȟȚȖȉȣȐȝȔȖȎȕȖȉȣȓȖȖȚȓȐȟȐȚȤȖȚȐȔȍȕșȚȖȓȉȞȖȊ

Основные операции DML реляционной базы данных можно запомнить с по-


мощью акронима CRUD:
‰Create — создание с помощью оператора SQL ;
‰Read — чтение с помощью ;
‰Update — обновление с помощью ;
‰Delete — удаление с помощью .
В табл. 16.2 показаны команды, доступные SQL DML.
ǺȈȉȓȐȞȈǶșȕȖȊȕȣȍȒȖȔȈȕȌȣ64/'0/

ǶȗȍȘȈȞȐȧ ȀȈȉȓȖȕ64/ ǷȘȐȔȍȘ64/


Добавление строки INSERT INTO имя_таблицы INSERT INTO t VALUES(7, 40)
VALUES(…)
Выборка всех строк SELECT * FROM имя_таблицы SELECT * FROM t
и столбцов SELECT * FROM t
Выборка всех строк SELECT cols FROM SELECT id, count FROM t
и некоторых столбцов имя_таблицы
Выборка некоторых строк SELECT cols FROM SELECT id, count from t
и некоторых столбцов имя_таблицы WHERE условие WHERE count > 5 AND id = 9
Изменение некоторых UPDATE имя_таблицы SET UPDATE t SET count = 3
строк в столбце col = значение WHERE условие WHERE id = 5
Удаление некоторых строк DELETE FROM имя_таблицы DELETE FROM t WHERE
WHERE условие count <= 10 OR id = 16
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

'%$3,
Программный интерфейс приложения (Application Programming Interface, API) —
это набор функций, которые вы можете вызвать, чтобы получить доступ к какой-
либо услуге. DB-API (KWWSELWO\GEDSL) — это стандартный API в Python, предна-
значенный для получения доступа к реляционным базам данных. С его помощью
вы можете написать одну программу, которая работает с несколькими видами
реляционных баз данных, вместо того чтобы писать несколько программ для работы
с каждым видом баз данных по отдельности. Этот API похож на JDBC в Java или
dbi в Perl.
Рассмотрим его основные функции:
‰ ‘‡ –ſƀ — создание соединения с базой данных. Этот вызов может включать
в себя такие аргументы, как имя пользователя, пароль, адреса сервера и пр.;
‰ —”•‘”ſƀ — создание объекта курсора, предназначенного для работы с запросами;
‰‡š‡ —–‡ſƀ и ‡š‡ —–‡ƒ›ſƀ — запуск одной или нескольких команд SQL;
‰ˆ‡– Š‘‡ſƀ, ˆ‡– Šƒ›ſƀ и ˆ‡– ŠƒŽŽſƀ — получение результатов работы функции
‡š‡ —–‡ſƀ.
Модули базы данных в Python, которые будут рассмотрены в следующих подраз-
делах, соответствуют DB-API, но часто имеют некоторые расширения или разницу
в деталях.

64/LWH
SQLite (KWWSZZZVTOLWHRUJ) — это хорошая легкая реляционная база данных с от-
крытым исходным кодом. Она реализована как стандартная библиотека Python
и хранит базы данных в обычных файлах. Эти файлы можно переносить в другие
машины и операционные системы, что делает SQLite портативным решением для
простых приложений реляционных баз данных. У нее не так много возможностей,
как у MySQL или PostgreSQL, но она поддерживает SQL и позволяет нескольким
пользователям работать с ней одновременно. Браузеры, смартфоны и другие опера-
ционные системы используют SQLite как встроенную базу данных.
Работа начинается с вызова ‘‡ –ſƀ для установки соединения с локальным
файлом базы данных, который вы хотите создать или использовать. Этот файл
эквивалентен похожей на каталог базе данных, которая хранит таблицы на других
серверах. С помощью специальной строки ɐś‡‘”›śɐ можно создать базу данных
только в памяти — это быстро и удобно для тестирования, но данные будут потеряны
при завершении программы или выключении компьютера.
Для следующего примера создадим базу данных ‡–‡”’”‹•‡Ŝ†„ и таблицу œ‘‘,
чтобы управлять нашим процветающим бизнесом по содержанию придорожного
контактного зоопарка. В таблице будут следующие столбцы:
‰ ”‹––‡” — строка переменной длины, наш первичный ключ;
‰ ‘—– — целочисленное количество единиц используемого инвентаря для этого
животного;
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰†ƒƒ‰‡• — сумма, выраженная в долларах, наших убытков из-за взаимодействий


людей с животными:
ʴʴʴ‹’‘”–•“Ž‹–‡ɪ
ʴʴʴ ‘ʰ•“Ž‹–‡ɪŜ ‘‡ –ſɐ‡–‡”’”‹•‡Ŝ†„ɐƀ
ʴʴʴ —”•ʰ ‘Ŝ —”•‘”ſƀ
ʴʴʴ —”•Ŝ‡š‡ —–‡ſɐɐɐœ‘‘
ſ ”‹––‡” ſɩɥƀ ř
 ‘—– ř
†ƒƒ‰‡• ƀɐɐɐƀ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɭƒɩɩ†ɥʴ

Тройные кавычки в Python очень полезны при создании длинных строк, таких
как запросы SQL.
Теперь добавим в зоопарк несколько животных:
ʴʴʴ —”•Ŝ‡š‡ —–‡ſɐ  œ‘‘ſɑ†— ɑřɬřɥŜɥƀɐƀ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɭƒɩɩ†ɥʴ
ʴʴʴ —”•Ŝ‡š‡ —–‡ſɐ  œ‘‘ſɑ„‡ƒ”ɑřɩřɨɥɥɥŜɥƀɐƀ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɭƒɩɩ†ɥʴ

Существует более безопасный способ добавить данные — использовать запол-


нитель:
ʴʴʴ‹•ʰɐ  œ‘‘ſ ”‹––‡”ř ‘—–ř†ƒƒ‰‡•ƀſţřţřţƀɐ
ʴʴʴ —”•Ŝ‡š‡ —–‡ſ‹•řſɐ™‡ƒ•‡ŽɐřɨřɩɥɥɥŜɥƀƀ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɭƒɩɩ†ɥʴ

На этот раз мы использовали в запросе три вопросительных знака, чтобы пока-


зать, что мы планируем вставить три значения, а затем передать эти значения в виде
кортежа в функцию ‡š‡ —–‡ſƀ. Заполнители помогают нам справляться с утоми-
тельными деталями, например с расстановкой кавычек. Они защищают от внедрений
SQL-кода — внешней атаки, распространенной в Сети, которая внедряет в систему
вредные команды SQL (такие атаки часто происходят в Интернете).
Теперь проверим, сможем ли мы вывести всех наших животных снова:
ʴʴʴ —”•Ŝ‡š‡ —–‡ſɐƋ œ‘‘ɐƀ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɭƒɩɩ†ɥʴ
ʴʴʴ”‘™•ʰ —”•Ŝˆ‡– ŠƒŽŽſƀ
ʴʴʴ’”‹–ſ”‘™•ƀ
ƃſɐ†— ɐřɬřɥŜɥƀřſɐ„‡ƒ”ɐřɩřɨɥɥɥŜɥƀřſɐ™‡ƒ•‡ŽɐřɨřɩɥɥɥŜɥƀƄ

Получим их еще раз, но упорядочим список по количеству животных:


ʴʴʴ —”•Ŝ‡š‡ —–‡ſɐƋˆ”‘œ‘‘ ‘—–ɐƀ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɭƒɩɩ†ɥʴ
ʴʴʴ —”•Ŝˆ‡– ŠƒŽŽſƀ
ƃſɐ™‡ƒ•‡ŽɐřɨřɩɥɥɥŜɥƀřſɐ„‡ƒ”ɐřɩřɨɥɥɥŜɥƀřſɐ†— ɐřɬřɥŜɥƀƄ

Эй, мы хотели получить список в нисходящем порядке:


ʴʴʴ —”•Ŝ‡š‡ —–‡ſɐƋˆ”‘œ‘‘ ‘—–ɐƀ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɭƒɩɩ†ɥʴ
ʴʴʴ —”•Ŝˆ‡– ŠƒŽŽſƀ
ƃſɐ†— ɐřɬřɥŜɥƀřſɐ„‡ƒ”ɐřɩřɨɥɥɥŜɥƀřſɐ™‡ƒ•‡ŽɐřɨřɩɥɥɥŜɥƀƄ
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

Какие животные обходятся нам дороже всего?


ʴʴʴ —”•Ŝ‡š‡ —–‡ſɐɐɐƋ œ‘‘ 
ŜŜŜ†ƒƒ‰‡•ʰſſ†ƒƒ‰‡•ƀ œ‘‘ƀɐɐɐƀ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɭƒɩɩ†ɥʴ
ʴʴʴ —”•Ŝˆ‡– ŠƒŽŽſƀ
ƃſɐ™‡ƒ•‡ŽɐřɨřɩɥɥɥŜɥƀƄ

Вы бы подумали, что это медведи. Лучше всегда проверять фактические


данные.
Перед тем как попрощаться с SQLite, следует очиститься. Если мы открывали
соединение и курсор, их нужно закрыть после того, как работа будет закончена:
ʴʴʴ —”•Ŝ Ž‘•‡ſƀ
ʴʴʴ ‘Ŝ Ž‘•‡ſƀ

0\64/
MySQL (KWWSZZZP\VTOFRP) — очень популярная реляционная база данных с от-
крытым исходным кодом. В отличие от SQLite она является настоящим сервером,
поэтому клиенты могут получать к ней доступ с разных устройств всей сети.
В табл. 16.3 перечислены драйверы, которые вы можете использовать для того,
чтобы получить доступ к MySQL из Python. За более подробной информацией обо
всех драйверах MySQL для Python обратитесь к энциклопедии на ’›–Š‘Ŝ‘”‰ (KWWSV
ZLNLS\WKRQRUJPRLQ0\64/).

ǺȈȉȓȐȞȈǬȘȈȑȊȍȘȣ0\64/

ǵȈȏȊȈȕȐȍ ǹșȣȓȒȈ ǷȈȒȍȚ3\3L ǰȔȗȖȘȚȐȘȖȊȈȚȤ ǷȘȐȔȍȟȈȕȐȍ


ȒȈȒ
mysqlclient [Link] mysql-connector- MySQLdb
[Link] python
MySQL [Link] mysql-connector- [Link]
Connector python
PYMySQL [Link] pymysql pymysql
petehunt/PyMySQL/
oursql [Link] oursql oursql Требует наличия
клиентской
библиотеки
MySQL C

3RVWJUH64/
PostgreSQL (KWWSZZZSRVWJUHVTORUJ) — полнофункциональная реляционная база
данных с открытым исходным кодом, гораздо более продвинутая, чем MySQL.
В табл. 16.4 показаны драйверы Python, которые можно использовать для того,
чтобы получить к ней доступ.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǺȈȉȓȐȞȈǬȘȈȑȊȍȘȣ3RVWJUH64/

ǵȈȏȊȈȕȐȍ ǹșȣȓȒȈ ǷȈȒȍȚ3\3L ǰȔȗȖȘȚȐȘȖȊȈȚȤ ǷȘȐȔȍȟȈȕȐȍ


ȒȈȒ
psycopg2 [Link] psycopg2 psycopg2 Необходим pg_config из
клиентских инструментов
PostgreSQL
py-postgresq [Link] py-postgresq py-postgresq
py-postgresql

Самым популярным драйвером является psycopg2, но для его установки требу-


ется наличие клиентских библиотек PostgreSQL.

64/$OFKHP\
SQL не для всех реляционных баз данных одинаков, а DB-API дает вам ограничен-
ный набор возможностей. Каждая база данных реализует определенный диалект,
отражая свои особенности и философию. Многие библиотеки пытаются тем или
иным способом компенсировать эти различия. Самая популярная библиотека для
работы с разными базами данных — SQLAlchemy (KWWSZZZVTODOFKHP\RUJ).
Она не является стандартной, тем не менее широко известна и многими исполь-
зуется. Вы можете установить ее в свою систему с помощью следующей команды:
$ pip install sqlalchemy

Использовать SQLAlchemy можно на нескольких уровнях.


‰Самый низкий уровень управляет пулами соединений с базами данных, выпол-
няет команды SQL и возвращает результат. Это ближе всего к DB-API.
‰Следующий уровень — язык выражений SQL, который позволяет вам выражать
запросы более Python-ориентированным способом.
‰Самый высокий уровень — это ORM (Object Relational Model — объектно-реля-
ционная модель), который использует язык выражений SQL Expression Language
и связывает код приложения с реляционными структурами данных.
По мере углубления в материал вы поймете, что означают эти термины. SQLAlchemy
работает с драйверами базы данных, задокументированными в предыдущих под-
разделах. Вам не нужно импортировать драйвер — он будет определен с помощью
строки соединения, которую вы предоставите SQLAlchemy. Эта строка выглядит
примерно так:
ȘȜȔȟșȞȦʫȘȤȔȝȖșȤśŵŵȣȢȟȰțȢȖȔȦșȟȰśȣȔȤȢȟȰɒȩȢȥȦśȣȢȤȦŵȜȠȳɕȕȔțȯ

В нее нужно поместить следующие значения:


‰ȘȜȔȟșȞȦ — тип базы данных;
‰ȘȤȔȝȖșȤ — драйвер, который вы хотите использовать для этой базы данных;
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

‰ȣȢȟȰțȢȖȔȦșȟȰ и ȣȔȤȢȟȰ — строки аутентификации для этой базы данных;


‰ȩȢȥȦ и ȣȢȤȦ — расположение сервера базы данных (значение port нужно указы-
вать только в том случае, если вы используете нестандартный порт);
‰ȜȠȳɕȕȔțȯ — имя базы данных, к которой нужно подключиться.
В табл. 16.5 перечислены диалекты и драйверы.
ǺȈȉȓȐȞȈǹȖȍȌȐȕȍȕȐȍș64/$OFKHP\

ǬȐȈȓȍȒȚ ǬȘȈȑȊȍȘ

sqlite pysqlite (можно опустить)


mysql Mysqlconnector
mysql Pymysql
mysql Oursql
postgresql psycopg2
postgresql Pypostgresql

Почитайте более подробно о диалектах SQLAlchemy для MySQL (KWWSVGRFVVTODO


FKHP\RUJHQGLDOHFWVP\VTOKWPO ), SQLite ( KWWSVGRFVVTODOFKHP\RUJHQGLDOHFWV
VTOLWHKWPO), PostgreSQL (KWWSVGRFVVTODOFKHP\RUJHQGLDOHFWVSRVWJUHVTOKWPO) и других
баз данных (KWWSVGRFVVTODOFKHP\RUJHQGLDOHFWV).
Уровень движка. Сначала обратимся к самому низкому уровню SQLAlchemy,
возможности которого почти не отличаются от функций DB-API.
Попробуем поработать с SQLite, поскольку его поддержка уже встроена в Python.
Строка соединения для SQLite опускает значения параметров ȩȢȥȦ, ȣȢȤȦ, ȜȠȳɕȣȢȟȰ-
țȢȖȔȦșȟȳ и ȣȔȤȢȟȰ. Имя ȜȠȳɕȕȔțȯ информирует SQLite о том, какой файл использо-
вать для хранения вашей базы данных. Если вы опустите параметр ȜȠȳɕȕȔțȯ, SQLite
создаст базу данных в памяти. Если ȜȠȳɕȕȔțȯ начинается со слеша ŵ, значит, это
абсолютное имя файла на вашем компьютере (как в Linux и macOS). В противном
случае это относительное имя текущего каталога.
Следующие сегменты являются частью одной программы, которую мы разде-
лили для удобства объяснения.
Для начала нужно импортировать все, что нам понадобится. Следующая строка
является примером импортирования псевдонима, который позволяет использовать
строку sa для того, чтобы ссылаться на методы SQLAlchemy. Я делаю это в основном
потому, что sa написать гораздо проще, чем •“ŽƒŽ Š‡›:
ʴʴʴ‹’‘”–•“ŽƒŽ Š‡›ƒ••ƒ

Соединимся с базой данных и создадим хранилище в памяти (строка аргументов


ɐ•“Ž‹–‡śŵŵŵś‡‘”›ś ɐ также сработает):
ʴʴʴ ‘ʰ•ƒŜ ”‡ƒ–‡ɏ‡‰‹‡ſɐ•“Ž‹–‡śŵŵɐƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Создадим таблицу, которая называется œ‘‘ и имеет три столбца:


ʴʴʴ ‘Ŝ‡š‡ —–‡ſɐɐɐœ‘‘
ŜŜŜſ ”‹––‡” ſɩɥƀ ř
ŜŜŜ ‘—– ř
ŜŜŜ†ƒƒ‰‡• ƀɐɐɐƀ
ʳ•“ŽƒŽ Š‡›Ŝ‡‰‹‡Ŝ”‡•—Ž–Ŝ‡•—Ž–”‘𛑄Œ‡ –ƒ–ɥšɨɥɨɮ‡ˆ„ɨɥʴ

Вызов ‘Ŝ‡š‡ —–‡ſƀ возвращает объект SQLAlchemy, который называется


‡•—Ž–”‘š›. Скоро вы увидите, что с ним можно сделать.
Кстати, если раньше вы никогда не создавали базы данных, примите мои по-
здравления. Можете вычеркнуть этот пункт из своего списка дел, которые в жизни
обязательно нужно реализовать.
Далее вставьте три набора данных в новую пустую таблицу:
ʴʴʴ‹•ʰɐ  œ‘‘ſ ”‹––‡”ř ‘—–ř†ƒƒ‰‡•ƀſţřţřţƀɐ
ʴʴʴ ‘Ŝ‡š‡ —–‡ſ‹•řɐ†— ɐřɨɥřɥŜɥƀ
ʳ•“ŽƒŽ Š‡›Ŝ‡‰‹‡Ŝ”‡•—Ž–Ŝ‡•—Ž–”‘𛑄Œ‡ –ƒ–ɥšɨɥɨɮ‡ˆ„ɬɥʴ
ʴʴʴ ‘Ŝ‡š‡ —–‡ſ‹•řɐ„‡ƒ”ɐřɩřɨɥɥɥŜɥƀ
ʳ•“ŽƒŽ Š‡›Ŝ‡‰‹‡Ŝ”‡•—Ž–Ŝ‡•—Ž–”‘𛑄Œ‡ –ƒ–ɥšɨɥɨɮ‡ˆɥɰɥʴ
ʴʴʴ ‘Ŝ‡š‡ —–‡ſ‹•řɐ™‡ƒ•‡ŽɐřɨřɩɥɥɥŜɥƀ
ʳ•“ŽƒŽ Š‡›Ŝ‡‰‹‡Ŝ”‡•—Ž–Ŝ‡•—Ž–”‘𛑄Œ‡ –ƒ–ɥšɨɥɨɮ‡ˆɫɬɥʴ

Сделайте выборку того, что только что разместили в базе:


ʴʴʴ”‘™•ʰ ‘Ŝ‡š‡ —–‡ſɐƋ œ‘‘ɐƀ

В SQLAlchemy rows не является списком — это специальный объект ‡•—Ž–”‘š›,


который мы не можем отобразить непосредственно:
ʴʴʴ’”‹–ſ”‘™•ƀ
ʳ•“ŽƒŽ Š‡›Ŝ‡‰‹‡Ŝ”‡•—Ž–Ŝ‡•—Ž–”‘𛑄Œ‡ –ƒ–ɥšɨɥɨɮ‡ˆɰ†ɥʴ

Однако вы можете итерировать по нему, как по списку, и получать по одному


ряду за раз:
ʴʴʴˆ‘””‘™‹”‘™•ś
ŜŜŜ’”‹–ſ”‘™ƀ
ŜŜŜ
ſɐ†— ɐřɨɥřɥŜɥƀ
ſɐ„‡ƒ”ɐřɩřɨɥɥɥŜɥƀ
ſɐ™‡ƒ•‡ŽɐřɨřɩɥɥɥŜɥƀ

Этот пример очень похож на тот, в котором использовался SQLite DB-API.


Единственное преимущество подобного подхода состоит в том, что нам не нужно
импортировать драйвер — SQLAlchemy сам определит драйвер на основе строки
соединения. Простое изменение строки соединения позволит перенести код на базу
данных другого типа. Еще один плюс SQLAlchemy заключается в наличии пула со-
единений, о котором вы можете прочитать в документации (KWWSVGRFVVTODOFKHP\RUJ
HQFRUHSRROLQJKWPO).
Язык выражений SQL. Следующий уровень SQLAlchemy — язык выражений
SQL. Он предоставляет функции, которые позволяют создать SQL для разных опе-
раций. Язык выражений обрабатывает большее количество различий в диалектах,
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

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


решением для приложений, работающих с реляционными базами данных.
Рассмотрим создание и наполнение таблицы œ‘‘ . И снова все последующие
фрагменты принадлежат одной программе.
Импортирование и подключение не изменяются:
ʴʴʴ‹’‘”–•“ŽƒŽ Š‡›ƒ••ƒ
ʴʴʴ ‘ʰ•ƒŜ ”‡ƒ–‡ɏ‡‰‹‡ſɐ•“Ž‹–‡śŵŵɐƀ

Для того чтобы определить таблицу œ‘‘, вместо SQL начнем использовать язык
выражений:
ʴʴʴ‡–ƒʰ•ƒŜ‡–ƒƒ–ƒſƀ
ʴʴʴœ‘‘ʰ•ƒŜƒ„އſɐœ‘‘ɐř‡–ƒř
ŜŜŜ•ƒŜ‘Ž—ſɐ ”‹––‡”ɐř•ƒŜ–”‹‰ř’”‹ƒ”›ɏ‡›ʰ”—‡ƀř
ŜŜŜ•ƒŜ‘Ž—ſɐ ‘—–ɐř•ƒŜ –‡‰‡”ƀř
ŜŜŜ•ƒŜ‘Ž—ſɐ†ƒƒ‰‡•ɐř•ƒŜ Ž‘ƒ–ƀ
ŜŜŜƀ
ʴʴʴ‡–ƒŜ ”‡ƒ–‡ɏƒŽŽſ ‘ƀ

Обратите внимание на круглые скобки в операции, которая занимает несколько


строк в предыдущем примере. Структура метода ƒ„އſƀ совпадает со структурой
таблицы. Поскольку наша таблица содержит три столбца, в методе ƒ„އſƀтоже три
вызова метода ‘Ž—ſƀ.
œ‘‘ представляет собой некий волшебный объект, который соединяет мир баз
данных SQL и мир структур данных Python.
Запишите в таблицу данные с помощью новых функций языка выражений:
ŜŜŜ ‘Ŝ‡š‡ —–‡ſœ‘‘Ŝ‹•‡”–ſſɐ„‡ƒ”ɐřɩřɨɥɥɥŜɥƀƀƀ
ʳ•“ŽƒŽ Š‡›Ŝ‡‰‹‡Ŝ”‡•—Ž–Ŝ‡•—Ž–”‘𛑄Œ‡ –ƒ–ɥšɨɥɨɮ‡ƒɰɨɥʴ
ʴʴʴ ‘Ŝ‡š‡ —–‡ſœ‘‘Ŝ‹•‡”–ſſɐ™‡ƒ•‡ŽɐřɨřɩɥɥɥŜɥƀƀƀ
ʳ•“ŽƒŽ Š‡›Ŝ‡‰‹‡Ŝ”‡•—Ž–Ŝ‡•—Ž–”‘𛑄Œ‡ –ƒ–ɥšɨɥɨɮ‡ƒ„ɨɥʴ
ʴʴʴ ‘Ŝ‡š‡ —–‡ſœ‘‘Ŝ‹•‡”–ſſɐ†— ɐřɨɥřɥƀƀƀ
ʳ•“ŽƒŽ Š‡›Ŝ‡‰‹‡Ŝ”‡•—Ž–Ŝ‡•—Ž–”‘𛑄Œ‡ –ƒ–ɥšɨɥɨɮ‡ƒ ɬɥʴ

Далее создадим оператор . Функция œ‘‘Ŝ•‡Ž‡ –ſƀ делает выборку всего,
что содержится в таблице, представленной объектом œ‘‘, как это сделала бы ин-
струкция  *  œ‘‘ в простом SQL:
ʴʴʴ”‡•—Ž–ʰ ‘Ŝ‡š‡ —–‡ſœ‘‘Ŝ•‡Ž‡ –ſƀƀ

Наконец, получим результат:


ʴʴʴ”‘™•ʰ”‡•—Ž–Ŝˆ‡– ŠƒŽŽſƀ
ʴʴʴ’”‹–ſ”‘™•ƀ
ƃſɐ„‡ƒ”ɐřɩřɨɥɥɥŜɥƀřſɐ™‡ƒ•‡ŽɐřɨřɩɥɥɥŜɥƀřſɐ†— ɐřɨɥřɥŜɥƀƄ

Object-Relational Mapper (ORM). В предыдущем подразделе объект œ‘‘ был


промежуточным звеном между SQL и Python. В самом верхнем слое SQLAlchemy
объектно-реляционное отображение (Object-Relational Mapper, ORM) использует
язык выражений SQL, но старается сделать реальные механизмы базы данных неви-
димыми. Вы определяете классы, а ORM обрабатывает способ, с помощью которого
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

они получают данные из базы данных и возвращают их обратно. Основная идея, на


которой базируется сложный термин «объектно-реляционное отображение», заклю-
чается в том, что вы можете ссылаться на объекты в своем коде и придерживаться
таким образом принципов работы с Python, но при этом использовать реляционную
базу данных.
Мы определим класс Zoo и свяжем его с ORM. На этот раз мы укажем SQLite
использовать файл œ‘‘Ŝ†„ так, чтобы мы могли убедиться в работе ORM.
Как и в предыдущих двух статьях, следующие фрагменты являются частью одной
программы, разделенной пояснениями. Не переживайте, если чего-то не поймете.
В документации к SQLAlchemy содержатся все необходимые подробности — работа
с SQLALchemy может оказаться довольно сложной.
Я просто хочу, чтобы вы поняли, как много придется поработать, и чтобы сами
могли решить, какой из подходов, рассмотренных в этой главе, подходит вам больше
других.
Импорт остается неизменным, но в этот раз нам нужно кое-что еще:
ʴʴʴ‹’‘”–•“ŽƒŽ Š‡›ƒ••ƒ
ʴʴʴˆ”‘•“ŽƒŽ Š‡›Ŝ‡š–Ŝ†‡ Žƒ”ƒ–‹˜‡‹’‘”–†‡ Žƒ”ƒ–‹˜‡ɏ„ƒ•‡

Вот так создается соединение:


ʴʴʴ ‘ʰ•ƒŜ ”‡ƒ–‡ɏ‡‰‹‡ſɐ•“Ž‹–‡śŵŵŵœ‘‘Ŝ†„ɐƀ

Теперь мы начинаем работать с SQLAlchemy ORM. Определяем класс Zoo и свя-


зываем его атрибуты со столбцами таблицы:
ʴʴʴƒ•‡ʰ†‡ Žƒ”ƒ–‹˜‡ɏ„ƒ•‡ſƀ
ʴʴʴ Žƒ••‘‘ſƒ•‡ƀś
ŜŜŜɏɏ–ƒ„އƒ‡ɏɏʰɐœ‘‘ɐ
ŜŜŜ ”‹––‡”ʰ•ƒŜ‘Ž—ſɐ ”‹––‡”ɐř•ƒŜ–”‹‰ř’”‹ƒ”›ɏ‡›ʰ”—‡ƀ
ŜŜŜ ‘—–ʰ•ƒŜ‘Ž—ſɐ ‘—–ɐř•ƒŜ –‡‰‡”ƀ
ŜŜŜ†ƒƒ‰‡•ʰ•ƒŜ‘Ž—ſɐ†ƒƒ‰‡•ɐř•ƒŜ Ž‘ƒ–ƀ
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆř ”‹––‡”ř ‘—–ř†ƒƒ‰‡•ƀś
ŜŜŜ•‡ŽˆŜ ”‹––‡”ʰ ”‹––‡”
ŜŜŜ•‡ŽˆŜ ‘—–ʰ ‘—–
ŜŜŜ•‡ŽˆŜ†ƒƒ‰‡•ʰ†ƒƒ‰‡•
ŜŜŜ†‡ˆɏɏ”‡’”ɏɏſ•‡Žˆƀś
ŜŜŜ”‡–—”ɑʳ‘‘ſƇƈřƇƈřƇƈƀʴɑŜˆ‘”ƒ–ſ•‡ŽˆŜ ”‹––‡”ř•‡ŽˆŜ ‘—–ř
ŜŜŜ•‡ŽˆŜ†ƒƒ‰‡•ƀ

Следующая строка как по волшебству создает базу данных и таблицу:


ʴʴʴƒ•‡Ŝ‡–ƒ†ƒ–ƒŜ ”‡ƒ–‡ɏƒŽŽſ ‘ƀ

Добавить данные в таблицу можно путем создания объектов Python. ORM управ-
ляет данными изнутри:
ʴʴʴˆ‹”•–ʰſɐ†— ɐřɨɥřɥŜɥƀ
ʴʴʴ•‡ ‘†ʰ‘‘ſɐ„‡ƒ”ɐřɩřɨɥɥɥŜɥƀ
ʴʴʴ–Š‹”†ʰ‘‘ſɐ™‡ƒ•‡ŽɐřɨřɩɥɥɥŜɥƀ
ʴʴʴˆ‹”•–
ʳ‘‘ſ†— řɨɥřɥŜɥƀʴ
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

Далее мы указываем ORM перенести нас в страну SQL. Создаем сессию для
коммуникации с базой данных:
ʴʴʴˆ”‘•“ŽƒŽ Š‡›Ŝ‘”‹’‘”–•‡••‹‘ƒ‡”
ʴʴʴ‡••‹‘ʰ•‡••‹‘ƒ‡”ſ„‹†ʰ ‘ƀ
ʴʴʴ•‡••‹‘ʰ‡••‹‘ſƀ

Внутри сессии записываем три созданных нами объекта в базу данных. Функция
ƒ††ſƀ добавляет один объект, а функция ƒ††ɏƒŽŽſƀ добавляет список:
ʴʴʴ•‡••‹‘Ŝƒ††ſˆ‹”•–ƀ
ʴʴʴ•‡••‹‘Ŝƒ††ɏƒŽŽſƃ•‡ ‘†ř–Š‹”†Ƅƀ

Наконец, нам нужно завершить сессию:


ʴʴʴ•‡••‹‘Ŝ ‘‹–ſƀ

Сработало? Файл œ‘‘Ŝ†„ был создан в текущем каталоге. Вы можете использо-


вать программу командной строки •“Ž‹–‡ɪ, чтобы в этом убедиться:
ɛsqlite3 [Link]
‹–‡˜‡”•‹‘ɪŜɭŜɨɩ
–‡”ɑŜЇޒɑˆ‘”‹•–”— –‹‘•
–‡”•–ƒ–‡‡–•–‡”‹ƒ–‡†™‹–ŠƒɑŚɑ
•“Ž‹–‡ʴ.tables
œ‘‘
•“Ž‹–‡ʴselect * from zoo;
†— ŶɨɥŶɥŜɥ
„‡ƒ”ŶɩŶɨɥɥɥŜɥ
™‡ƒ•‡ŽŶɨŶɩɥɥɥŜɥ

Целью этого статьи было показать, что такое ORM и как оно работает на высо-
ком уровне. Автор SQLAlchemy написал полное руководство к нему (KWWSELWO\
REMUHOWXWRULDO). После прочтения статьи определитесь, какой из следующих уровней
наиболее подходит для ваших нужд:
‰простой DB-API, показанный ранее в этой главе в подразделе «SQLite»;
‰движок SQLAlchemy;
‰язык выражений SQLAlchemy;
‰SQLAlchemy ORM.
Естественным выбором выглядит ORM, что позволит избежать всех сложностей
SQL. Стоит ли им пользоваться? Некоторые люди считают, что ORM следует из-
бегать, а другие полагают, что критика незаслуженна. Кто бы ни был прав, ORM —
это абстракция, а все абстракции в какой-то момент разрушаются — они допускают
утечки памяти (KWWSVZZZMRHORQVRIWZDUHFRPWKHODZRIOHDN\DEVWUDFWLRQV).
Если ORM не делает того, что вам нужно, вы должны понять, как он работает,
а затем разобраться, как это исправить с помощью SQL. Перефразируя интернет-
мем: «Столкнувшись с проблемой, некоторые люди думают: “Точно, обращусь-ка
я к ORM!” Теперь у них две проблемы».
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Используйте ORM для простых приложений или приложений, которые довольно


точно отображают данные в таблицах базы данных. Но если приложение кажется про-
стым, то вам, возможно, стоит использовать простой SQL (или язык выражений SQL).

ǬȘțȋȐȍȗȈȒȍȚȣȌȓȧȘȈȉȖȚȣșȉȈȏȈȔȐȌȈȕȕȣȝ
Если вы ищете инструменты Python, которые позволяют работать со многими ба-
зами данных и имеют больше возможностей, чем простой DB-API, но меньше, чем
SQLAlchemy, рассмотрите следующие варианты:
‰†ƒ–ƒ•‡– (KWWSVGDWDVHWUHDGWKHGRFVLRHQODWHVW). Его девиз — «Базы данных для
ленивых». Он создан на основе SQLAlchemy и предоставляет простой ORM для
хранилищ SQL, JSON и CSV;
‰”‡ ‘”†• (KWWSVS\SLRUJSURMHFWUHFRUGV). Его разработчики считают, что это «SQL
для людей». Он поддерживает только запросы SQL, используя SQLAlchemy для
обработки проблем с диалектами SQL, пулами соединений и т. д., и интегриру-
ется с tablib (упоминается в подразделе «Tablib» на с. 338), что позволяет экс-
портировать данные в форматах CSV, JSON и многих других.

ǽȘȈȕȐȓȐȡȈȌȈȕȕȣȝ1R64/
Реляционные таблицы имеют форму прямоугольника, но поступающие данные
могут иметь разную форму и их размещение требует больших усилий. Это похоже
на проблему квадратного колышка и круглой дырки.
Отдельные нереляционные базы данных позволяют более гибко определять
данные, работают с очень крупными наборами и поддерживают пользовательские
операции с данными. Такие базы данных называют NoSQL (раньше это означало
«не SQL», теперь же расшифровка звучит как «не только SQL»).
Простейшей вариацией баз данных NoSQL являются хранилища ключей-значений.
О некоторых из них, которые попали в рейтинг популярности (KWWSVGEHQJLQHVFRP
HQUDQNLQJNH\YDOXHVWRUH), поговорим в следующих подразделах.

ǹȍȔȍȑșȚȊȖGEP
Форматы †„ существовали задолго до того, как появился NoSQL. Они представляют
собой простые хранилища, работающие по принципу «ключ — значение». Их часто
встраивают в приложения вроде браузеров, чтобы поддерживать различные на-
стройки. База данных dbm похожа на обычный словарь в следующих отношениях:
‰вы присваиваете значение ключу, и оно автоматически сохраняется в базе дан-
ных на диске;
‰вы можете получить ключ по его значению.
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

Рассмотрим простой пример. Второй аргумент следующего метода ‘’‡ſƀ может


принимать значения ɐ”ɐ для чтения, ɐ™ɐ для записи и ɐ ɐ для того и другого, созда-
вая файл, если его не существует:
ʴʴʴ‹’‘”–†„
ʴʴʴ†„ʰ†„Ŝ‘’‡ſɐ†‡ˆ‹‹–‹‘•ɐřɐ ɐƀ

Для того чтобы создать пары «ключ — значение», просто присвойте значение
ключу, как если бы вы работали со словарем:
ʴʴʴ†„ƃɐ—•–ƒ”†ɐƄʰɐ›‡ŽŽ‘™ɐ
ʴʴʴ†„ƃɐ‡– Š—’ɐƄʰɐ”‡†ɐ
ʴʴʴ†„ƃɐ’‡•–‘ɐƄʰɐ‰”‡‡ɐ

Приостановимся и посмотрим, что мы уже имеем:


ʴʴʴއſ†„ƀ
ɪ
ʴʴʴ†„ƃɐ’‡•–‘ɐƄ
„ɐ‰”‡‡ɐ

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


наши данные были сохранены:
ʴʴʴ†„Ŝ Ž‘•‡ſƀ
ʴʴʴ†„ʰ†„Ŝ‘’‡ſɐ†‡ˆ‹‹–‹‘•ɐřɐ”ɐƀ
ʴʴʴ†„ƃɐ—•–ƒ”†ɐƄ
„ɐ›‡ŽŽ‘™ɐ

Ключи и значения сохраняются как байты. Вы не можете итерировать по объ-


ектам базы данных †„, но можете получить количество ключей с помощью функции
އſƀ. Обратите внимание на то, что функции ‰‡–ſƀ и •‡–†‡ˆƒ—Ž–ſƀ работают точно
так же, как и для словарей.

0HPFDFKHG
‡ ƒ Ї† (KWWSPHPFDFKHGRUJ) — это быстрый сервер кэширования, располагаю-
щийся в памяти и работающий по принципу «ключ — значение». Часто его разме-
щают перед базой данных или используют для хранения данных сессии веб-сервера.
Вы можете загрузить версии для Linux, macOS (KWWSELWO\LQVWDOORV[) и Windows
(KWWSELWO\PHPFDFKHZLQ). Если хотите попробовать запустить примеры, показан-
ные в этом подразделе, вам понадобятся запущенный сервер ‡ ƒ Ї† и драйвер
Python.
Существует множество драйверов Python. Тот, что работает с Python 3, называ-
ется ’›–Š‘ɪޏ‡ ƒ Ї† (KWWSVJLWKXEFRPHJXYHQS\WKRQPHPFDFKHG). Установить его
можно с помощью такой команды:
ɛpip install python-memcached
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Чтобы его использовать, подключитесь к серверу memcached, после чего вы


сможете:
‰устанавливать и получать значения ключей;
‰увеличивать и уменьшать значения;
‰удалять ключи.
Ключи и значения, хранимые в базе, неустойчивы и могут исчезать. Это проис-
ходит из-за того, что memcached является сервером кэша, а не базой данных. Он из-
бегает ситуаций, когда у него заканчивается память, стирая старые данные.
Вы можете подключиться к нескольким серверам memcached одновременно.
В следующем примере мы беседуем с одним сервером на том же компьютере:
ʴʴʴ‹’‘”–‡ ƒ Ї
ʴʴʴ†„ʰ‡ ƒ ЇŜŽ‹‡–ſƃɐɨɩɮŜɥŜɥŜɨśɨɨɩɨɨɐƄƀ
ʴʴʴ†„Ŝ•‡–ſɐƒ” ‘ɐřɐ’‘Ž‘ɐƀ
”—‡
ʴʴʴ†„Ŝ‰‡–ſɐƒ” ‘ɐƀ
ɐ’‘Ž‘ɐ
ʴʴʴ†„Ŝ•‡–ſɐ†— •ɐřɥƀ
”—‡
ʴʴʴ†„Ŝ‰‡–ſɐ†— •ɐƀ
ɥ
ʴʴʴ†„Ŝ‹ ”ſɐ†— •ɐřɩƀ
ɩ
ʴʴʴ†„Ŝ‰‡–ſɐ†— •ɐƀ
ɩ

5HGLV
Redis — это сервер структур данных. Он работает с ключами и их значениями,
но значения имеют гораздо больше возможностей, чем в других хранилищах.
Как и в случае с memcached, все данные сервера Redis должны поместиться в па-
мять (хотя у нас имеется возможность сохранить все данные на диск). В отличие от
memcached Redis может делать следующее:
‰сохранять данные на диск для надежности в случае перезагрузки;
‰хранить старые данные;
‰предоставлять более сложные, по сравнению со строками, структуры данных.
Типы данных Redis близки к типам данных Python, и сервер Redis может быть
полезным посредником для обмена данными между приложениями. Мне это кажется
настолько важным, что я посвящу данной теме небольшой фрагмент книги.
Исходный код драйвера Python ”‡†‹•Ş’› и тесты находятся на GitHub (KWWSV
JLWKXEFRPDQG\PFFXUG\UHGLVS\), документация по нему находится по адресу KWWSELWO\
UHGLVS\GRFV. Драйвер устанавливается с помощью следующей команды:
ɛpip install redis
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

Сам по себе сервер Redis (KWWSUHGLVLR) хорошо задокументирован. Если вы


установите и запустите его на своем локальном компьютере, который имеет се-
тевое имя Ž‘ ƒŽŠ‘•–, вы сможете запустить программы, описанные в следующих
подразделах.
Строки. Ключ, имеющий одно значение, является строкой Redis. Простые типы
данных Python автоматически преобразуются. Подключимся к серверу Redis, рас-
положенному на определенных хосте (по умолчанию Ž‘ ƒŽŠ‘•–) и порте (по умол-
чанию ɭɪɮɰ):
ʴʴʴ‹’‘”–”‡†‹•
ʴʴʴ ‘ʰ”‡†‹•Ŝ‡†‹•ſƀ

Строки ”‡†‹•Ŝ‡†‹•ſɐŽ‘ ƒŽŠ‘•–ɐƀ или ”‡†‹•Ŝ‡†‹•ſɐŽ‘ ƒŽŠ‘•–ɐř ɭɪɮɰƀ дадут


тот же результат.
Перечислим все ключи (которых пока нет):
ʴʴʴ ‘Ŝ‡›•ſɐƋɐƀ
ƃƄ

Создадим простую строку (с ключом ɐ•‡ ”‡–ɐ), целое число (с ключом ɐ ƒ”ƒ–•ɐ)
и число с плавающей точкой (с ключом ɐˆ‡˜‡”ɐ):
ʴʴʴ ‘Ŝ•‡–ſɐ•‡ ”‡–ɐřɐ‹Šɐƀ
”—‡
ʴʴʴ ‘Ŝ•‡–ſɐ ƒ”ƒ–•ɐřɩɫƀ
”—‡
ʴʴʴ ‘Ŝ•‡–ſɐˆ‡˜‡”ɐřɐɨɥɨŜɬɐƀ
”—‡

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


ʴʴʴ ‘Ŝ‰‡–ſɐ•‡ ”‡–ɐƀ
„ɐ‹Šɐ
ʴʴʴ ‘Ŝ‰‡–ſɐ ƒ”ƒ–•ɐƀ
„ɐɩɫɐ
ʴʴʴ ‘Ŝ‰‡–ſɐˆ‡˜‡”ɐƀ
„ɐɨɥɨŜɬɐ

Метод •‡–šſƀ устанавливает значение, но только если ключа не существует:


ʴʴʴ ‘Ŝ•‡–šſɐ•‡ ”‡–ɐřɐ‹ ›Ş‹ ›Ş‹ ›Ş’–ƒ‰Şœ‘‘’Ş„‘‹‰Šɐƀ
ƒŽ•‡

Метод не сработал, поскольку мы уже определили ключ ɐ•‡ ”‡–ɐ:


ʴʴʴ ‘Ŝ‰‡–ſɐ•‡ ”‡–ɐƀ
„ɐ‹Šɐ

Метод ‰‡–•‡–ſƀ возвращает старое значение и одновременно устанавливает


новое:
ʴʴʴ ‘Ŝ‰‡–•‡–ſɐ•‡ ”‡–ɐřɐ‹ ›Ş‹ ›Ş‹ ›Ş’–ƒ‰Şœ‘‘’Ş„‘‹‰Šɐƀ
„ɐ‹Šɐ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Не будем сильно забегать вперед. Это сработало?


ʴʴʴ ‘Ŝ‰‡–ſɐ•‡ ”‡–ɐƀ
„ɐ‹ ›Ş‹ ›Ş‹ ›Ş’–ƒ‰Şœ‘‘’Ş„‘‹‰Šɐ

Теперь мы получим подстроку с помощью метода ‰‡–”ƒ‰‡ſƀ (как и в Python,


смещение ɥ означает начало списка, ʬɨ — конец):
ʴʴʴ ‘Ŝ‰‡–”ƒ‰‡ſɐ•‡ ”‡–ɐřŞɭřŞɨƀ
„ɐ„‘‹‰Šɐ

Заменим подстроку с помощью метода •‡–”ƒ‰‡ſƀ (используя смещение, которое


начинается с нуля):
ʴʴʴ ‘Ŝ•‡–”ƒ‰‡ſɐ•‡ ”‡–ɐřɥřɐ ɐƀ
ɪɩ
ʴʴʴ ‘Ŝ‰‡–ſɐ•‡ ”‡–ɐƀ
„ɐ Ş‹ ›Ş‹ ›Ş’–ƒ‰Şœ‘‘’Ş„‘‹‰Šɐ

Далее установим значения сразу нескольких ключей с помощью метода •‡–ſƀ:


ʴʴʴ ‘Ŝ•‡–ſƇɐ’‹‡ɐśɐ Ї””›ɐřɐ ‘”†‹ƒŽɐśɐ•Ї””›ɐƈƀ
”—‡

Получим более одного значения с помощью метода ‰‡–ſƀ:


ʴʴʴ ‘Ŝ‰‡–ſƃɐˆ‡˜‡”ɐřɐ ƒ”ƒ–•ɐƄƀ
ƃ„ɐɨɥɨŜɬɐř„ɐɩɫɐƄ

Удалим ключ с помощью метода †‡Ž‡–‡ſƀ:


ʴʴʴ ‘Ŝ†‡Ž‡–‡ſɐˆ‡˜‡”ɐƀ
”—‡

Выполним инкремент с помощью команд ‹ ”ſƀ и ‹ ”„›ˆŽ‘ƒ–ſƀ и декремент


с помощью команды †‡ ”ſƀ:
ʴʴʴ ‘Ŝ‹ ”ſɐ ƒ”ƒ–•ɐƀ
ɩɬ
ʴʴʴ ‘Ŝ‹ ”ſɐ ƒ”ƒ–•ɐřɨɥƀ
ɪɬ
ʴʴʴ ‘Ŝ†‡ ”ſɐ ƒ”ƒ–•ɐƀ
ɪɫ
ʴʴʴ ‘Ŝ†‡ ”ſɐ ƒ”ƒ–•ɐřɨɬƀ
ɨɰ
ʴʴʴ ‘Ŝ•‡–ſɐˆ‡˜‡”ɐřɐɨɥɨŜɬɐƀ
”—‡
ʴʴʴ ‘Ŝ‹ ”„›ˆŽ‘ƒ–ſɐˆ‡˜‡”ɐƀ
ɨɥɩŜɬ
ʴʴʴ ‘Ŝ‹ ”„›ˆŽ‘ƒ–ſɐˆ‡˜‡”ɐřɥŜɬƀ
ɨɥɪŜɥ

Команды †‡ ”„›ˆŽ‘ƒ–ſƀ не существует. Используйте отрицательный инкремент,


чтобы уменьшить значение ключа fever:
ʴʴʴ ‘Ŝ‹ ”„›ˆŽ‘ƒ–ſɐˆ‡˜‡”ɐřŞɩŜɥƀ
ɨɥɨŜɥ
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

Списки. Списки Redis могут содержать только строки. Список создается,


когда вы добавляете первые данные. Добавим данные в начало списка с помощью
метода Ž’—•Šſƀ:
ʴʴʴ ‘ŜŽ’—•Šſɐœ‘‘ɐřɐ„‡ƒ”ɐƀ
ɨ

Добавим в начало списка более одного элемента:


ʴʴʴ ‘ŜŽ’—•Šſɐœ‘‘ɐřɐƒŽŽ‹‰ƒ–‘”ɐřɐ†— ɐƀ
ɪ

Добавим один элемент до или после другого с помощью метода Ž‹•‡”–ſƀ:


ʴʴʴ ‘ŜŽ‹•‡”–ſɐœ‘‘ɐřɐ„‡ˆ‘”‡ɐřɐ„‡ƒ”ɐřɐ„‡ƒ˜‡”ɐƀ
ɫ
ʴʴʴ ‘ŜŽ‹•‡”–ſɐœ‘‘ɐřɐƒˆ–‡”ɐřɐ„‡ƒ”ɐřɐ ƒ••‘™ƒ”›ɐƀ
ɬ

Добавим элемент, указав смещение для него, с помощью метода Ž•‡–ſƀ (список
уже должен существовать):
ʴʴʴ ‘ŜŽ•‡–ſɐœ‘‘ɐřɩřɐƒ”‘•‡–ɐƀ
”—‡

Добавим элемент в конец с помощью метода ”’—•Šſƀ:


ʴʴʴ ‘Ŝ”’—•Šſɐœ‘‘ɐřɐ›ƒɐƀ
6

Получим элемент по заданному смещению с помощью метода Ž‹†‡šſƀ:


ʴʴʴ ‘ŜŽ‹†‡šſɐœ‘‘ɐřɪƀ
„ɐ„‡ƒ”ɐ

Получим все элементы, находящиеся в диапазоне смещений, с помощью метода


Ž”ƒ‰‡ſƀ (можно использовать любой индекс от 0 до –1):
ʴʴʴ ‘ŜŽ”ƒ‰‡ſɐœ‘‘ɐřɥřɩƀ
ƃ„ɐ†— ɐř„ɐƒŽŽ‹‰ƒ–‘”ɐř„ɐƒ”‘•‡–ɐƄ

Обрежем список с помощью метода Ž–”‹ſƀ, сохранив только элементы в за-


данном диапазоне:
ʴʴʴ ‘ŜŽ–”‹ſɐœ‘‘ɐřɨřɫƀ
”—‡

Получим диапазон значений (можно использовать любой индекс от 0 до –1)


с помощью метода Ž”ƒ‰‡ſƀ:
ʴʴʴ ‘ŜŽ”ƒ‰‡ſɐœ‘‘ɐřɥřŞɨƀ
ƃ„ɐƒŽŽ‹‰ƒ–‘”ɐř„ɐƒ”‘•‡–ɐř„ɐ„‡ƒ”ɐř„ɐ ƒ••‘™ƒ”›ɐƄ

В главе 15 показано, как использовать списки Redis и механизм публикации —


подписки, чтобы реализовать очереди задач.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Хеши. Хеши Redis похожи на словари в Python, но содержат только строки, по-
этому мы можем создать только одномерный словарь. Рассмотрим примеры, в ко-
торых создается и изменяется хеш с именем song.
Установим в хеше song значения полей †‘ и re одновременно с помощью мето-
да Š•‡–ſƀ:
ʴʴʴ ‘ŜŠ•‡–ſɐ•‘‰ɐřƇɐ†‘ɐśɐƒ†‡‡”ɐřɐ”‡ɐśɐƒ„‘—–ƒ†‡‡”ɐƈƀ
”—‡

Установим значение одного поля хеша с помощью метода Š•‡–ſƀ:


ʴʴʴ ‘ŜŠ•‡–ſɐ•‘‰ɐřɐ‹ɐřɐƒ‘–‡–‘ˆ‘ŽŽ‘™”‡ɐƀ
ɨ

Получим значение одного поля с помощью метода Š‰‡–ſƀ:


ʴʴʴ ‘ŜЉ‡–ſɐ•‘‰ɐřɐ‹ɐƀ
„ɐƒ‘–‡–‘ˆ‘ŽŽ‘™”‡ɐ

Получим значение нескольких полей с помощью метода Š‰‡–ſƀ:


ʴʴʴ ‘ŜŠ‰‡–ſɐ•‘‰ɐřɐ”‡ɐřɐ†‘ɐƀ
ƃ„ɐƒ„‘—–ƒ†‡‡”ɐř„ɐƒ†‡‡”ɐƄ

Получим ключи всех полей хеша с помощью метода Š‡›•ſƀ:


ʴʴʴ ‘ŜŠ‡›•ſɐ•‘‰ɐƀ
ƃ„ɐ†‘ɐř„ɐ”‡ɐř„ɐ‹ɐƄ

Получим значения всех полей хеша с помощью метода Š˜ƒŽ•ſƀ:


ʴʴʴ ‘ŜŠ˜ƒŽ•ſɐ•‘‰ɐƀ
ƃ„ɐƒ†‡‡”ɐř„ɐƒ„‘—–ƒ†‡‡”ɐř„ɐƒ‘–‡–‘ˆ‘ŽŽ‘™”‡ɐƄ

Получим количество полей хеша с помощью функции ŠŽ‡ſƀ:


ʴʴʴ ‘ŜŠŽ‡ſɐ•‘‰ɐƀ
ɪ

Получим ключи и значения всех полей хеша с помощью метода Š‰‡–ƒŽŽſƀ:


ʴʴʴ ‘ŜЉ‡–ƒŽŽſɐ•‘‰ɐƀ
Ƈ„ɐ†‘ɐś„ɐƒ†‡‡”ɐř„ɐ”‡ɐś„ɐƒ„‘—–ƒ†‡‡”ɐř„ɐ‹ɐś„ɐƒ‘–‡–‘ˆ‘ŽŽ‘™”‡ɐƈ

Создадим поле, если его ключ не существует, с помощью метода Š•‡–šſƀ:


ʴʴʴ ‘ŜŠ•‡–šſɐ•‘‰ɐřɐˆƒɐřɐƒ‘–‡–Šƒ–”Š›‡•™‹–ŠŽƒɐƀ
ɨ

Множества. Множества Redis похожи на множества Python, в чем вы сможете


убедиться в следующих примерах.
Добавим одно или несколько значений множества:
ʴʴʴ ‘Ŝ•ƒ††ſɐœ‘‘ɐřɐ†— ɐřɐ‰‘ƒ–ɐřɐ–—”‡›ɐƀ
ɪ
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

Получим количество значений множества:


ʴʴʴ ‘Ŝ• ƒ”†ſɐœ‘‘ɐƀ
ɪ

Получим все значения множества:


ʴʴʴ ‘Ŝ•‡„‡”•ſɐœ‘‘ɐƀ
Ƈ„ɐ†— ɐř„ɐ‰‘ƒ–ɐř„ɐ–—”‡›ɐƈ

Удалим значение из множества:


ʴʴʴ ‘Ŝ•”‡ſɐœ‘‘ɐřɐ–—”‡›ɐƀ
”—‡

Создадим второе множество, чтобы продемонстрировать некоторые операции:


ʴʴʴ ‘Ŝ•ƒ††ſɐ„‡––‡”ɏœ‘‘ɐřɐ–‹‰‡”ɐřɐ™‘Žˆɐřɐ†— ɐƀ
ɥ

Пересечение множеств (получение общих членов) œ‘‘ и „‡––‡”ɏœ‘‘:


ʴʴʴ ‘Ŝ•‹–‡”ſɐœ‘‘ɐřɐ„‡––‡”ɏœ‘‘ɐƀ
Ƈ„ɐ†— ɐƈ

Выполним пересечение множеств œ‘‘ и „‡––‡”ɏœ‘‘ и сохраним результат в мно-


жестве ˆ‘™Žɏœ‘‘:
ʴʴʴ ‘Ŝ•‹–‡”•–‘”‡ſɐˆ‘™Žɏœ‘‘ɐřɐœ‘‘ɐřɐ„‡––‡”ɏœ‘‘ɐƀ
ɨ

Есть кто живой?


ʴʴʴ ‘Ŝ•‡„‡”•ſɐˆ‘™Žɏœ‘‘ɐƀ
Ƈ„ɐ†— ɐƈ

Выполним объединение (всех членов) множеств œ‘‘ и „‡––‡”ɏœ‘‘:


ʴʴʴ ‘Ŝ•—‹‘ſɐœ‘‘ɐřɐ„‡––‡”ɏœ‘‘ɐƀ
Ƈ„ɐ†— ɐř„ɐ‰‘ƒ–ɐř„ɐ™‘Žˆɐř„ɐ–‹‰‡”ɐƈ

Сохраним результат этого пересечения в множестве ˆƒ„—Ž‘—•ɏœ‘‘:


ʴʴʴ ‘Ŝ•—‹‘•–‘”‡ſɐˆƒ„—Ž‘—•ɏœ‘‘ɐřɐœ‘‘ɐřɐ„‡––‡”ɏœ‘‘ɐƀ
ɫ
ʴʴʴ ‘Ŝ•‡„‡”•ſɐˆƒ„—Ž‘—•ɏœ‘‘ɐƀ
Ƈ„ɐ†— ɐř„ɐ‰‘ƒ–ɐř„ɐ™‘Žˆɐř„ɐ–‹‰‡”ɐƈ

Какие элементы присутствуют в множестве œ‘‘ и отсутствуют в множестве


„‡––‡”ɏœ‘‘? Используйте метод •†‹ˆˆſƀ, чтобы получить разницу множеств, и метод
•†‹ˆˆ•–‘”‡ſƀ, чтобы сохранить ее в множестве œ‘‘ɏ•ƒŽ‡:
ʴʴʴ ‘Ŝ•†‹ˆˆſɐœ‘‘ɐřɐ„‡––‡”ɏœ‘‘ɐƀ
Ƈ„ɐ‰‘ƒ–ɐƈ
ʴʴʴ ‘Ŝ•†‹ˆˆ•–‘”‡ſɐœ‘‘ɏ•ƒŽ‡ɐřɐœ‘‘ɐřɐ„‡––‡”ɏœ‘‘ɐƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ɨ
ʴʴʴ ‘Ŝ•‡„‡”•ſɐœ‘‘ɏ•ƒŽ‡ɐƀ
Ƈ„ɐ‰‘ƒ–ɐƈ

Упорядоченные множества. Один из самых гибких типов данных Redis — это


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

‰списки лидеров;
‰списки вторичных индексов;
‰временные ряды, где отметки времени используются как счетчик.

Мы рассмотрим последний вариант применения, отслеживая логины пользова-


телей с помощью временных меток. Мы будем использовать значение времени ‡’‘ Š
(подробнее об этом — в главе 10), которое возвращает функция –‹‡ſƀ:
ʴʴʴ‹’‘”––‹‡
ʴʴʴ‘™ʰ–‹‡Ŝ–‹‡ſƀ
ʴʴʴ‘™
ɨɪɭɨɯɬɮɥɬɮŜɬɮɭɫɯɪ

Добавим первого гостя (он немного нервничает):


ʴʴʴ ‘Ŝœƒ††ſɐŽ‘‰‹•ɐřɐ•‡ƒ‰‘Žɐř‘™ƀ
ɨ

Пять минут спустя добавим второго гостя:


ʴʴʴ ‘Ŝœƒ††ſɐŽ‘‰‹•ɐřɐ•ƒ—”‘ɐř‘™ʫſɬƋɭɥƀƀ
ɨ

Через два часа:


ʴʴʴ ‘Ŝœƒ††ſɐŽ‘‰‹•ɐřɐ„‹Ž„‘ɐř‘™ʫſɩƋɭɥƋɭɥƀƀ
ɨ

Еще один гость не торопился и пришел спустя сутки:


ʴʴʴ ‘Ŝœƒ††ſɐŽ‘‰‹•ɐřɐ–”‡‡„‡ƒ”†ɐř‘™ʫſɩɫƋɭɥƋɭɥƀƀ
ɨ

Каким по счету пришел bilbo?


ʴʴʴ ‘Ŝœ”ƒſɐŽ‘‰‹•ɐřɐ„‹Ž„‘ɐƀ
ɩ

Когда это было?


ʴʴʴ ‘Ŝœ• ‘”‡ſɐŽ‘‰‹•ɐřɐ„‹Ž„‘ɐƀ
ɨɪɭɨɯɭɫɩɬɮŜɬɮɭɫɯɪ
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

Посмотрим, каким по счету пришел каждый гость:


ʴʴʴ ‘Ŝœ”ƒ‰‡ſɐŽ‘‰‹•ɐřɥřŞɨƀ
ƃ„ɐ•‡ƒ‰‘Žɐř„ɐ•ƒ—”‘ɐř„ɐ„‹Ž„‘ɐř„ɐ–”‡‡„‡ƒ”†ɐƄ

И когда:
ʴʴʴ ‘Ŝœ”ƒ‰‡ſɐŽ‘‰‹•ɐřɥřŞɨř™‹–Š• ‘”‡•ʰ”—‡ƀ
ƃſ„ɐ•‡ƒ‰‘ŽɐřɨɪɭɨɯɬɮɥɬɮŜɬɮɭɫɯɪƀřſ„ɐ•ƒ—”‘ɐřɨɪɭɨɯɬɮɪɬɮŜɬɮɭɫɯɪƀř
ſ„ɐ„‹Ž„‘ɐřɨɪɭɨɯɭɫɩɬɮŜɬɮɭɫɯɪƀřſ„ɐ–”‡‡„‡ƒ”†ɐřɨɪɭɨɰɫɪɫɬɮŜɬɮɭɫɯɪƀƄ

Кэши и истечение срока действия. У всех ключей Redis есть время жизни, или
дата истечения срока действия. По умолчанию этот срок длится вечно. Мы можем
использовать функцию ‡š’‹”‡ſƀ, чтобы указать Redis, как долго хранить заданный
ключ. Значением является количество секунд:
ʴʴʴ‹’‘”––‹‡
ʴʴʴ‡›ʰɐ‘™›‘—•‡‡‹–ɐ
ʴʴʴ ‘Ŝ•‡–ſ‡›řɐ„—–‘–ˆ‘”Ž‘‰ɐƀ
”—‡
ʴʴʴ ‘Ŝ‡š’‹”‡ſ‡›řɬƀ
”—‡
ʴʴʴ ‘Ŝ––Žſ‡›ƀ
ɬ
ʴʴʴ ‘Ŝ‰‡–ſ‡›ƀ
„ɐ„—–‘–ˆ‘”Ž‘‰ɐ
ʴʴʴ–‹‡Ŝ•އ‡’ſɭƀ
ʴʴʴ ‘Ŝ‰‡–ſ‡›ƀ
ʴʴʴ

Команда ‡š’‹”‡ƒ–ſƀ указывает, что действие ключа истекает в заданное время


‡’‘ Š Unix. Истечение срока действия ключа полезно для поддержания свежести кэ-
шей и ограничения количества сеансов входа в систему. Рассмотрим аналогию: в хо-
лодильнике, расположенном за стойками с молоком в вашем продуктовом магазине,
работники избавляются от галлонов молока, когда у тех истекает срок годности.

ǬȖȒțȔȍȕȚȖȖȘȐȍȕȚȐȘȖȊȈȕȕȣȍȉȈȏȣȌȈȕȕȣȝ
Документоориентированные базы данных — это базы данных формата NoSQL,
которые хранят данные с разными полями. В сравнении с реляционной таблицей
(прямоугольной формы, с одинаковыми столбцами для каждой строки) данные, хра-
нящиеся в этих таблицах, являются ragged — могут содержать разные поля (столбцы)
в каждой строке, а также могут иметь вложенные поля. Можно обрабатывать такие
данные с помощью словарей и списков или же сохранять их в файлах JSON. Для со-
хранения таких данных в реляционную таблицу нужно определить все возможные
столбцы и использовать значения null для отсутствующих данных.
ODM может расшифровываться как Object Data Manager или Object Document
Mapper. ODM является документоориентированным аналогом ORM — реляционных
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

баз данных. Некоторые популярные (KWWSVGEHQJLQHVFRPHQUDQNLQJGRFXPHQWVWRUH)


документоориентированные базы данных и инструменты (драйверы и ODM) пере-
числены в табл. 16.6.
ǺȈȉȓȐȞȈǬȖȒțȔȍȕȚȖȖȘȐȍȕȚȐȘȖȊȈȕȕȣȍȉȈȏȣȌȈȕȕȣȝ

ǩȈȏȈȌȈȕȕȣȝ 3\WKRQ$3,
Mongo ([Link] tools ([Link]
[Link])
DynamoDB ([Link] boto3 ([Link]
ru/dynamodb/) latest/developerguide/[Link])
CouchDB ([Link] couchdb ([Link]
latest/[Link])

3RVWJUH64/ȔȖȎȍȚȊȣȗȖȓȕȧȚȤȕȍȒȖȚȖȘȣȍȏȈȌȈȟȐȒȖȚȖȘȣȍȊȣȗȖȓȕȧȦȚȐȌȖȒțȔȍȕȚȖ
ȖȘȐȍȕȚȐȘȖȊȈȕȕȣȍȉȈȏȣȌȈȕȕȣȝǭȋȖȘȈșȠȐȘȍȕȐȧȗȖȏȊȖȓȧȦȚȐȏȉȍȎȈȚȤȖȗȘȍȌȍȓȍȕȕȣȝ
ȔȐȕțșȖȊȘȍȓȧȞȐȖȕȕȣȝȉȈȏȌȈȕȕȣȝȕȖșȖȝȘȈȕȧȦȚȗȘȐȥȚȖȔȚȈȒȐȍȖșȖȉȍȕȕȖșȚȐȒȈȒ
ȚȘȈȕȏȈȒȞȐȐȊȈȓȐȌȈȞȐȧȌȈȕȕȣȝȐȊȕȍȠȕȐȍȒȓȦȟȐ ȔȕȖȋȖȔȍȘȕȣȍȔȈșșȐȊȣ KWWSV
ZZZSRVWJUHVTORUJGRFVDUUD\VKWPO ȗȖȏȊȖȓȧȦȚȝȘȈȕȐȚȤȉȖȓȍȍȖȌȕȖȋȖȏȕȈȟȍȕȐȧ
ȊȧȟȍȑȒȍȚȈȉȓȐȞȣ MVRQE KWWSVZZZSRVWJUHVTORUJGRFVGDWDW\SHMVRQKWPO 
ȗȖȏȊȖȓȧȍȚșȖȝȘȈȕȐȚȤȊȧȟȍȑȒȍȌȈȕȕȣȍȊȜȖȘȔȈȚȍ-621șȗȖȓȕȣȔȐȕȌȍȒșȐȘȖȊȈȕȐȍȔ
ȐȏȈȗȘȖșȈȔȐ

ǩȈȏȣȌȈȕȕȣȝȊȘȍȔȍȕȕȣȝȘȧȌȖȊ
Данные временных рядов могут быть собраны в фиксированные (например, метри-
ки производительности компьютера) или случайные интервалы времени. Это при-
вело к появлению множества методов их хранения (KWWSVGEHQJLQHVFRPHQUDQNLQJ
WLPHVHULHVGEPV). Методы, поддерживаемые Python, перечислены в табл. 16.7.

ǺȈȉȓȐȞȈǪȘȍȔȍȕȕȣȍȉȈȏȣȌȈȕȕȣȝ

ǩȈȏȈȌȈȕȕȣȝ 3\WKRQ$3,
InfluxDB ([Link] influx-client ([Link]
kdb+ ([Link] PyQ ([Link]
Prometheus ([Link] prometheus_client ([Link]
client_python/blob/master/[Link])
TimescaleDB ([Link] PostgreSQL-клиенты
OpenTSDB ([Link] potsdb ([Link]
PyStore ([Link] PyStore ([Link]
pystore)
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

ǫȘȈȜȖȊȣȍȉȈȏȣȌȈȕȕȣȝ
Последний вид данных, для которых нужна собственная база данных, представляет
собой графы: узлы (данные), соединенные ребрами (отношениями). Отдельный
пользователь Twitter может быть узлом с ребрами, ведущими к другим пользовате-
лям, на которых подписан он или которые подписаны на него.
Графовые данные стали появляться чаще по мере роста соцсетей, где связи так же
важны, как и содержимое. Некоторые популярные (KWWSVGEHQJLQHVFRPHQUDQNLQJ
JUDSKGEPV) графовые базы данных приведены в табл. 16.8.

ǺȈȉȓȐȞȈǫȘȈȜȖȊȣȍȉȈȏȣȌȈȕȕȣȝ

ǩȈȏȈȌȈȕȕȣȝ 3\WKRQ$3,

Neo4J ([Link] py2neo ([Link]


OrientDB ([Link] pyorient ([Link]
[Link])
ArangoDB ([Link] pyArango ([Link]
pyArango)

ǬȘțȋȐȍșȍȘȊȍȘȣ1R64/
Серверы NoSQL, перечисленные здесь, могут работать с данными, объем которых
превышает объем доступной памяти, — многие из них требуют использования не-
скольких компьютеров. В табл. 16.9 показаны наиболее популярные серверы и их
библиотеки Python.
ǺȈȉȓȐȞȈǩȈȏȣȌȈȕȕȣȝ1R64/

ǩȈȏȈȌȈȕȕȣȝ 3\WKRQ$3,

Cassandra ([Link] pycassa ([Link]


CouchDB ([Link] couchdb-python ([Link]
couchdb-python)
HBase ([Link] happybase ([Link]
happybase)
Kyoto ([Link] kyotocabinet ([Link]
pythondoc/)
MongoDB ([Link] mongodb ([Link]
current/)
Pilosa ([Link] python-pilosa ([Link]
python-pilosa)
Riak ([Link] riak-python-client ([Link]
riak-python-client)
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǷȖȓȕȖȚȍȒșȚȖȊȣȍȉȈȏȣȌȈȕȕȣȝ
Наконец, существует особая категория баз данных для полнотекстового поиска.
Они индексируют все, поэтому вы легко можете найти то стихотворение, в котором
говорится о ветряных мельницах и гигантских головках сыра. Популярные приме-
ры таких баз данных с открытым исходным кодом и их Python API представлены
в табл. 16.10.
ǺȈȉȓȐȞȈǷȖȓȕȖȚȍȒșȚȖȊȣȍȉȈȏȣȌȈȕȕȣȝ

ǹȈȑȚ 3\WKRQ$3,
Lucene ([Link] pylucene ([Link]
Solr ([Link] SolPython ([Link]
display/solr/SolPython)
ElasticSearch ([Link] elasticsearch ([Link]
en/master/)
Sphinx ([Link] sphinxapi ([Link]
source/browse/trunk/api/[Link])
Xapian ([Link] xappy ([Link]
Whoosh ([Link] Написан на Python, уже содержит API
whoosh/wiki/Home)

ǿȐȚȈȑȚȍȌȈȓȍȍ
В предыдущей главе рассматривался вопрос выполнения разных фрагментов кода за
разные промежутки времени (конкурентность). Следующая глава посвящена пере-
мещению данных в пространстве (сети) — его можно использовать для написания
конкурентного кода и для многого другого.

ǻȗȘȈȎȕȍȕȐȧ
16.1. Сохраните следующие несколько строк в файл „‘‘•Ŝ •˜. Обратите внимание
на то, что, если поля разделены запятыми, вам нужно заключить в кавычки
поле, содержащее запятую:
ƒ—–Š‘”ř„‘‘
‘Ž‹‡řЇ ‘„„‹–
›‡”—••řɑƒ–•řŠ‘‘–•ĺ‡ƒ˜‡•ɑ

16.2. Используйте модуль •˜ и его метод ‹ –‡ƒ†‡”, чтобы считать содержимое


файла „‘‘•Ŝ •˜ в переменную „‘‘•. Выведите на экран значения перемен-
ной „‘‘•. Обработал ли метод ‹ –‡ƒ†‡” кавычки и запятые в заголовке
второй книги?
ǫȓȈȊȈǬȈȕȕȣȍȊȒȖȘȖȉȒȍȕȈȌȍȎȕȣȍȝȘȈȕȐȓȐȡȈ  

16.3. Создайте CSV-файл „‘‘•Ŝ •˜ и запишите его в следующие строки:


–‹–އřƒ—–Š‘”ř›‡ƒ”
Ї‡‹”†•–‘‡‘ˆ”‹•‹‰ƒ‡řŽƒ ƒ”‡”řɨɰɭɥ
‡”†‹†‘–”‡‡––ƒ–‹‘řŠ‹ƒ‹²˜‹ŽŽ‡řɩɥɥɥ
Š—†Šř‡””›”ƒ– Ї––řɩɥɥɬ
Ї’‡ŽŽƒ ‹Ž‡•ř‹•ƒ—–œřɩɥɥɮ
ƒŽŽ ‘†•ř‡””›”ƒ– Ї––řɨɰɰɩ

16.4. Используйте модуль •“Ž‹–‡ɪ, чтобы создать базу данных SQLite „‘‘•Ŝ†„
и таблицу „‘‘•, содержащую следующие поля: title (текст), author (текст)
и year (целое число).
16.5. Считайте данные из файла „‘‘•Ŝ •˜ и добавьте их в таблицу „‘‘.
16.6. Считайте и выведите на экран столбец title таблицы „‘‘ в алфавитном по-
рядке.
16.7. Считайте и выведите на экран все столбцы таблицы „‘‘ в порядке публикации.
16.8. Используйте модуль •“ŽƒŽ Š‡›, чтобы подключиться к базе данных •“Ž‹–‡ɪ
„‘‘•Ŝ†„, которую вы создали в упражнении 16.4. Как и в упражнении 16.6,
считайте и выведите на экран столбец title таблицы „‘‘ в алфавитном по-
рядке.
16.9. Установите сервер Redis и библиотеку Python ”‡†‹• (с помощью команды pip
install ”‡†‹•) на свой компьютер. Создайте хеш ”‡†‹• с именем test, содер-
жащий поля ‘—–ſɨƀ и ƒ‡ſɐ ‡•–‡” ‡•–‡”–‡•–‡”ɐƀ. Выведите все поля хеша
test.
16.10. Увеличьте поле ‘—– хеша test и выведите его на экран.
ƋƓƈƊƈ
ǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ

Время — то, что удерживает все от того, чтобы


случаться сразу. Пространство — то, что удерживает
все от того, чтобы случаться со мной.

Цитаты о времени1

Из главы 15 вы узнали о конкурентности: способе выполнять больше одного дела


за раз. Теперь мы попробуем решать задачи более чем в одном месте. В этом нам по-
могут распределенные вычисления и сети. Существует несколько хороших причин
бросить вызов пространству и времени.
‰Производительность. Ваша цель заключается в том, чтобы быстрые компоненты
оставались занятыми, а не ждали, пока отработают медленные.
‰Устойчивость. Один в поле не воин, поэтому стоит дублировать задачи для того,
чтобы обойти проблемы, связанные с отказом аппаратного и программного обе-
спечения.
‰Простота. Лучше всего разбивать сложные задачи на множество простых, кото-
рые легче создавать, понимать и исправлять.
‰Масштабируемость. Увеличивайте количество серверов, чтобы справляться
с нагрузкой, и уменьшайте его для экономии денег.
В этой главе мы сначала рассмотрим примитивные концепции работы с сетями,
а затем поднимемся на самый высокий уровень. Начнем с модели TCP/IP и сокетов.

7&3,3
Интернет основан на правилах, по которым создаются соединения, идет обмен
данными, закрываются соединения, обрабатывается истечение срока действия и т. д.
Эти правила называются протоколами, и они упорядочены в слои. Цель существо-

1
[Link]
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

вания слоев — позволить быть инновациям и альтернативным способам выполне-


ния задач. Вы можете делать все что угодно в рамках одного слоя до тех пор, пока
следуете соглашениям, связанным с работой с более низкими и более высокими
слоями.
Самый нижний слой управляет такими аспектами, как электрические сигналы.
Каждый более высокий слой базируется на нижних. Примерно в середине нахо-
дится IP (Internet Protocol — интернет-протокол), на котором определяется, как
адресуются локации сети и перемещаются пакеты (фрагменты) данных. На слое,
расположенном выше IP, два протокола описывают, как перемещать байты между
локациями.
‰UDP (User Datagram Protocol — протокол датаграмм пользователя). Служит для
обмена небольшим объемом данных. Датаграмма — это небольшое сообщение,
которое отправляется целиком; оно похоже на открытку.
‰TCP (Transmission Control Protocol — протокол управления передачей). Использует-
ся для более длинных соединений. С его помощью отправляются потоки байтов,
он гарантирует, что они придут по порядку и без дупликаций.
Для сообщений, отправляемых по протоколу UDP, подтверждение не требу-
ется, поэтому вы никогда не можете быть уверены в том, что они придут в точку
назначения. Если бы вы хотели рассказать шутку по протоколу UDP, то она вы-
глядела бы так:
ǢȢȦȬȧȦȞȔȣȤȢŜǤȢȬȟȢţ

TCP устанавливает секретное рукопожатие между отправляющей и принима-


ющей стороной, чтобы гарантировать хорошее соединение. Шутка, отправленная
по протоколу TCP, начнется примерно так:
DzȯȩȢȫșȬȰȧȥȟȯȬȔȦȰȬȧȦȞȧȣȤȢţ
ǤȔřȳȩȢȫȧȧȥȟȯȬȔȦȰȬȧȦȞȧȣȤȢŜ
ǮɐȞșȝřȳȤȔȥȥȞȔȚȧȦșȕșȬȧȦȞȧȣȤȢŜ
ǮɐȞșȝřȳȖȯȥȟȧȬȔȲȬȧȦȞȧȣȤȢŜ
ǮɐȞșȝřȦșȣșȤȰȳȢȦȣȤȔȖȟȲȦșȕșȬȧȦȞȧȣȤȢŜ
ǮɐȞșȝřȦșȣșȤȰȳȣȤȜȠȧȬȧȦȞȧȣȤȢŜ
ŜŜŜſȜȦŜȘŜƀ

Ваша локальная машина всегда будет иметь IP-адрес  и имя ORFDOKRVW.
Вы можете встретить название для этого процесса — интерфейс обратной петли.
При подключении к Интернету у вашей машины также появится публичный IP.
Если же вы используете домашний компьютер, то он будет скрыт за оборудованием,
таким как кабельный модем или роутер. Вы можете запускать интернет-протоколы
даже между процессами на одной машине.
Большая часть Интернета, с которой мы будем взаимодействовать, — Всемир-
ная паутина, серверы баз данных и т. д. — основана на протоколе TCP, функцио-
нирующем поверх протокола IP, сокращенно — TCP/IP. Сначала рассмотрим
самые простые интернет-сервисы. Затем перейдем к общим шаблонам для работы
с сетями.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǹȖȒȍȚȣ
Если вы хотите узнать, как все работает, то этот подраздел для вас.
На самом низком уровне сетевого программирования используется сокет, по-
заимствованный из языка программирования C и операционной системы Unix.
Кодирование на уровне сокетов может быть утомительным. Вам будет гораздо
интереснее работать с чем-то наподобие ZeroMQ, однако не помешает узнать, что
лежит под этим уровнем. Например, сообщения о сокетах часто появляются при
возникновении ошибок в работе с сетями.
Напишем небольшой пример, где клиент и сервер будут обмениваться данными.
Клиент отправляет серверу строку, размещенную в датаграмме UDP, а сервер воз-
вращает пакет данных, содержащий строку. Серверу нужно слушать определенный
адрес и порт — они похожи на почтовое отделение и почтовый ящик. Клиент должен
знать эти два значения, чтобы доставить сообщение и получить ответ.
В следующем коде клиента и сервера элемент ƒ††”‡•• — это кортеж вида
(адрес, порт). Данный элемент является строкой, которая может быть именем или
IP-адресом. Когда ваши программы просто беседуют друг с другом на одной машине,
вы можете использовать имя ɐŽ‘ ƒŽŠ‘•–ɐ или эквивалентный адрес ɐɨɩɮŜɥŜɥŜɨɐ.
Для начала отправим небольшой фрагмент данных из одного процесса в другой
и вернем немного данных отправителю. Первая программа — клиент, а вторая —
сервер. В каждой из них мы выведем на экран время и откроем сокет. Сервер будет
слушать подключения к своему сокету, а клиент — писать данные в свой сокет,
который передаст сообщение на сервер.
В примере 17.1 показана первая программа, —†’ɏ•‡”˜‡”Ŝ’›.

ǷȘȐȔȍȘXGSBVHUYHUS\
ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
‹’‘”–•‘ ‡–

•‡”˜‡”ɏƒ††”‡••ʰſɐŽ‘ ƒŽŠ‘•–ɐřɭɮɯɰƀ
ƒšɏ•‹œ‡ʰɫɥɰɭ

’”‹–ſɐ–ƒ”–‹‰–Ї•‡”˜‡”ƒ–ɐř†ƒ–‡–‹‡Ŝ‘™ſƀƀ
’”‹–ſɐƒ‹–‹‰ˆ‘”ƒ Ž‹‡––‘ ƒŽŽŜɐƀ
•‡”˜‡”ʰ•‘ ‡–Ŝ•‘ ‡–ſ•‘ ‡–Ŝ ɏ ř•‘ ‡–Ŝɏ ƀ
•‡”˜‡”Ŝ„‹†ſ•‡”˜‡”ɏƒ††”‡••ƀ

†ƒ–ƒř Ž‹‡–ʰ•‡”˜‡”Ŝ”‡ ˜ˆ”‘ſƒšɏ•‹œ‡ƀ

’”‹–ſɐ–ɐř†ƒ–‡–‹‡Ŝ‘™ſƀř Ž‹‡–řɐ•ƒ‹†ɐř†ƒ–ƒƀ
•‡”˜‡”Ŝ•‡†–‘ſ„ɐ”‡›‘—–ƒŽ‹‰–‘‡ţɐř Ž‹‡–ƀ
•‡”˜‡”Ŝ Ž‘•‡ſƀ

Сервер должен установить сетевое соединение с помощью двух методов, импор-


тированных из пакета •‘ ‡–. Первый метод, •‘ ‡–Ŝ•‘ ‡–, создает сокет, а второй,
„‹†, привязывается к нему (слушает любые данные, приходящие на этот IP-адрес
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

и порт). Параметр  ɏ  означает, что мы создаем интернет-сокет (IP). (Существу-


ет и другой тип для Unix domain sockets, но он будет работать только на локальной
машине.) Параметр ɏ  означает, что мы будем отправлять и получать дата-
граммы — другими словами, станем использовать UDP.
Теперь сервер просто ждет прихода датаграммы (”‡ ˜ˆ”‘). Когда она появ-
ляется, сервер просыпается и получает данные и информацию о клиенте. Пере-
менная Ž‹‡– содержит комбинацию адреса и порта, необходимую для полу-
чения доступа к клиенту. Сервер завершает работу, отправляя ответ и закрывая
соединение.
Взглянем на файл —†’ɏ Ž‹‡–Ŝ’› (пример 17.2).

ǷȘȐȔȍȘXGSBFOLHQWS\
‹’‘”–•‘ ‡–
ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡

•‡”˜‡”ɏƒ††”‡••ʰſɐŽ‘ ƒŽŠ‘•–ɐřɭɮɯɰƀ
ƒšɏ•‹œ‡ʰɫɥɰɭ

’”‹–ſɐ–ƒ”–‹‰–Ї Ž‹‡–ƒ–ɐř†ƒ–‡–‹‡Ŝ‘™ſƀƀ
Ž‹‡–ʰ•‘ ‡–Ŝ•‘ ‡–ſ•‘ ‡–Ŝ ɏ ř•‘ ‡–Ŝɏ ƀ
Ž‹‡–Ŝ•‡†–‘ſ„ɐ ‡›Šɐř•‡”˜‡”ɏƒ††”‡••ƀ
†ƒ–ƒř•‡”˜‡”ʰ Ž‹‡–Ŝ”‡ ˜ˆ”‘ſƒšɏ•‹œ‡ƀ
’”‹–ſɐ–ɐř†ƒ–‡–‹‡Ŝ‘™ſƀř•‡”˜‡”řɐ•ƒ‹†ɐř†ƒ–ƒƀ
Ž‹‡–Ŝ Ž‘•‡ſƀ

Клиент содержит те же методы, что и сервер (за исключением „‹†ſƀ). Клиент


отправляет данные, а затем получает их, в то время как сервер сначала получает.
Запустим сервер в отдельном окне. Он выведет приветственное сообщение и бу-
дет спокойно ждать до тех пор, пока клиент не отправит ему данные:
ɛpython udp_server.py
–ƒ”–‹‰–Ї•‡”˜‡”ƒ–ɩɥɨɫŞɥɩŞɥɬɩɨśɨɮśɫɨŜɰɫɬɭɫɰ
ƒ‹–‹‰ˆ‘”ƒ Ž‹‡––‘ ƒŽŽŜ

Далее запустим клиент в отдельном окне. Он выведет приветственное сообще-


ние, отправит данные (слово Hey в байтовом формате), покажет ответ сервера и за-
вершит работу:
ɛpython udp_client.py
–ƒ”–‹‰–Ї Ž‹‡–ƒ–ɩɥɨɫŞɥɩŞɥɬɩɨśɩɫśɬɭŜɬɥɰɭɯɩ
–ɩɥɨɫŞɥɩŞɥɬɩɨśɩɫśɬɭŜɬɨɯɭɮɥſɐɨɩɮŜɥŜɥŜɨɐřɭɮɯɰƀ•ƒ‹†„ɐ”‡›‘—–ƒŽ‹‰–‘‡ţɐ

Наконец, сервер выведет что-то наподобие этого и завершит работу:


–ɩɥɨɫŞɥɩŞɥɬɩɨśɩɫśɬɭŜɬɨɯɫɮɪſɐɨɩɮŜɥŜɥŜɨɐřɬɭɩɭɮƀ•ƒ‹†„ɐ ‡›Šɐ

Клиенту нужно было знать адрес и номер порта сервера, однако он не указал свой
номер порта, поэтому тот был автоматически присвоен системой — в данном случае
он был равен ɬɭɩɭɮ.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǷȖȗȘȖȚȖȒȖȓț8'3ȌȈȕȕȣȍȖȚȗȘȈȊȓȧȦȚșȧȕȍȉȖȓȤȠȐȔȐȜȘȈȋȔȍȕȚȈȔȐȅȚȖȚȗȘȖȚȖȒȖȓ
ȕȍȋȈȘȈȕȚȐȘțȍȚȌȖșȚȈȊȒȐǭșȓȐȊȣȖȚȗȘȈȊȐȚȍȕȍșȒȖȓȤȒȖșȖȖȉȡȍȕȐȑșȗȖȔȖȡȤȦ8'3
ȚȖȖȕȐȔȖȋțȚȗȘȐȑȚȐȊȕȍȗȘȈȊȐȓȤȕȖȔȗȖȘȧȌȒȍȐȓȐȊȖȖȉȡȍȕȍȗȖȧȊȐȚȤșȧȅȚȖȚȗȘȖ
ȚȖȒȖȓȉȣșȚȘȓȍȋȖȒȕȍșȖȏȌȈȍȚșȖȍȌȐȕȍȕȐȑȖȌȕȈȒȖȕȍȕȈȌȍȎȍȕǶȕȗȖȓȍȏȍȕȊȚȖȔ
șȓțȟȈȍȒȖȋȌȈȕțȎȕȖȖȚȗȘȈȊȐȚȤȗȈȒȍȚȣȉȣșȚȘȖȐȕȍșȚȘȈȠȕȣȐȝȗȖȚȍȘȐȒȖȚȖȘȣȍ
ȗȘȖȐșȝȖȌȧȚȊȘȍȔȧȖȚȊȘȍȔȍȕȐ²ȕȈȗȘȐȔȍȘȗȘȐȐșȗȖȓȤȏȖȊȈȕȐȐȚȍȝȕȖȓȖȋȐȐ9R,3
YRLFHRYHU,3 

Вышесказанное приводит нас к протоколу TCP (Transmission Control Protocol —


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

ǷȍȘȊȣȍȌȊȍȊȍȘșȐȐȊȍȉȗȘȖȚȖȒȖȓȈ+773ȉȣȓȐȖșȕȖȊȈȕȣȕȈ7&3ȕȖ+773ȖșȕȖȊȈȕȕȈ
ȗȘȖȚȖȒȖȓȍ48,& KWWSVRUHLOO\<-\P ȒȖȚȖȘȣȑȐșȗȖȓȤȏțȍȚ8'3ǷȖȥȚȖȔțȗȘȐȊȣȉȖȘȍ
ȔȍȎȌț8'3Ȑ7&3șȓȍȌțȍȚțȟȐȚȣȊȈȚȤȔȕȖȎȍșȚȊȖȜȈȒȚȖȘȖȊ

Обменяемся пакетами между клиентом и сервером с помощью TCP.


Файл – ’ɏ Ž‹‡–Ŝ’› действует так же, как и предыдущий клиент, работающий
с UDP, отправляя только одну строку на сервер. Однако существуют небольшие
различия в вызовах сокетов, показанные в примере 17.3.

ǷȘȐȔȍȘWFSBFOLHQWS\
‹’‘”–•‘ ‡–
ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡

ƒ††”‡••ʰſɐŽ‘ ƒŽŠ‘•–ɐřɭɮɯɰƀ
ƒšɏ•‹œ‡ʰɨɥɥɥ

’”‹–ſɐ–ƒ”–‹‰–Ї Ž‹‡–ƒ–ɐř†ƒ–‡–‹‡Ŝ‘™ſƀƀ
Ž‹‡–ʰ•‘ ‡–Ŝ•‘ ‡–ſ•‘ ‡–Ŝ ɏ ř•‘ ‡–Ŝɏƀ
Ž‹‡–Ŝ ‘‡ –ſƒ††”‡••ƀ
Ž‹‡–Ŝ•‡†ƒŽŽſ„ɐ ‡›Šɐƀ
†ƒ–ƒʰ Ž‹‡–Ŝ”‡ ˜ſƒšɏ•‹œ‡ƀ
’”‹–ſɐ–ɐř†ƒ–‡–‹‡Ŝ‘™ſƀřɐ•‘‡‘‡”‡’Ž‹‡†ɐř†ƒ–ƒƀ
Ž‹‡–Ŝ Ž‘•‡ſƀ

Мы заменили параметр ɏ  на ɏ, чтобы получить потоковый


протокол, TCP. Мы также добавили вызов ‘‡ –ſƀ с целью установить поток.
Нам не нужно было делать это для UDP, поскольку каждая датаграмма после от-
правки предоставлялась сама себе.
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

Как показано в примере 17.4, файл – ’ɏ•‡”˜‡”Ŝ’› также отличается от своего


собрата, работающего с UDP.

ǷȘȐȔȍȘWFSBVHUYHUS\
ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
‹’‘”–•‘ ‡–

ƒ††”‡••ʰſɐŽ‘ ƒŽŠ‘•–ɐřɭɮɯɰƀ
ƒšɏ•‹œ‡ʰɨɥɥɥ

’”‹–ſɐ–ƒ”–‹‰–Ї•‡”˜‡”ƒ–ɐř†ƒ–‡–‹‡Ŝ‘™ſƀƀ
’”‹–ſɐƒ‹–‹‰ˆ‘”ƒ Ž‹‡––‘ ƒŽŽŜɐƀ
•‡”˜‡”ʰ•‘ ‡–Ŝ•‘ ‡–ſ•‘ ‡–Ŝ ɏ ř•‘ ‡–Ŝɏƀ
•‡”˜‡”Ŝ„‹†ſƒ††”‡••ƀ
•‡”˜‡”ŜŽ‹•–‡ſɬƀ

Ž‹‡–řƒ††”ʰ•‡”˜‡”Ŝƒ ‡’–ſƀ
†ƒ–ƒʰ Ž‹‡–Ŝ”‡ ˜ſƒšɏ•‹œ‡ƀ

’”‹–ſɐ–ɐř†ƒ–‡–‹‡Ŝ‘™ſƀř Ž‹‡–řɐ•ƒ‹†ɐř†ƒ–ƒƀ
Ž‹‡–Ŝ•‡†ƒŽŽſ„ɐ”‡›‘—–ƒŽ‹‰–‘‡ţɐƀ
Ž‹‡–Ŝ Ž‘•‡ſƀ
•‡”˜‡”Ŝ Ž‘•‡ſƀ

С помощью вызова •‡”˜‡”ŜŽ‹•–‡ſɬƀ сервер конфигурируется так, чтобы поста-


вить в очередь пять клиентских соединений, прежде чем отказывать в следующем.
Вызов Ž‹‡–Ŝ”‡ ˜ſɨɥɥɥƀ устанавливает максимальную длину входящего со-
общения равной 1000 байт.
Как и раньше, запустим сервер, а затем клиент и понаблюдаем. Сначала запустим
сервер:
ɛpython tcp_server.py
–ƒ”–‹‰–Ї•‡”˜‡”ƒ–ɩɥɨɫŞɥɩŞɥɭɩɩśɫɬśɨɪŜɪɥɭɰɮɨ
ƒ‹–‹‰ˆ‘”ƒ Ž‹‡––‘ ƒŽŽŜ
–ɩɥɨɫŞɥɩŞɥɭɩɩśɫɬśɨɭŜɥɫɯɯɭɬʳ•‘ ‡–Ŝ•‘ ‡–‘„Œ‡ –řˆ†ʰɭřˆƒ‹Ž›ʰɩř–›’‡ʰɨř
’”‘–‘ʰɥʴ•ƒ‹†„ɐ ‡›Šɐ

Теперь запустим клиент. Он отправит сообщение серверу, получит ответ и за-


вершит работу:
ɛpython tcp_client.py
–ƒ”–‹‰–Ї Ž‹‡–ƒ–ɩɥɨɫŞɥɩŞɥɭɩɩśɫɬśɨɭŜɥɪɯɭɫɩ
–ɩɥɨɫŞɥɩŞɥɭɩɩśɫɬśɨɭŜɥɫɰɥɮɯ•‘‡‘‡”‡’Ž‹‡†„ɐ”‡›‘—–ƒŽ‹‰–‘‡ţɐ

Сервер получит сообщение, выведет его на экран, ответит и завершит работу:


–ɩɥɨɫŞɥɩŞɥɭɩɩśɫɬśɨɭŜɥɫɯɯɭɬʳ•‘ ‡–Ŝ•‘ ‡–‘„Œ‡ –řˆ†ʰɭřˆƒ‹Ž›ʰɩř–›’‡ʰɨř
’”‘–‘ʰɥʴ•ƒ‹†„ɐ ‡›Šɐ

Обратите внимание: чтобы ответить, сервер TCP вызвал метод Ž‹‡–Ŝ•‡†ƒŽŽſƀ,


а в предыдущем примере — Ž‹‡–Ŝ•‡†–‘ſƀ. TCP поддерживает клиент-серверное
соединение с помощью нескольких вызовов сокетов и запоминает IP-адрес клиента.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Это не выглядит ужасно, но если вы попробуете написать что-то более сложное,


то увидите, насколько низкоуровневыми являются сокеты. Рассмотрим несколько
сложностей, с которыми вам придется столкнуться.
‰UDP отправляет сообщения, но их размер ограничен и нет гарантии, что они
достигнут места назначения.
‰TCP вместо сообщений отправляет потоки байтов. Вы не знаете, сколько байтов
отправит или получит система с каждым вызовом.
‰Для обмена сообщениями с помощью TCP вам нужна дополнительная инфор-
мация, чтобы собрать полное сообщение из сегментов: фиксированный размер
сообщения (в байтах), или размер всего сообщения, или какой-либо разделитель.
‰Поскольку сообщения являются байтами, а не текстовыми строками Unicode,
вам придется использовать тип bytes. Более подробную информацию об этом
типе см. в главе 12.
Если после всего этого вас все еще восхищает программирование сокетов, то вам
стоит посетить ресурс Python socket programming HOWTO (KWWSELWO\VRFNHWKRZWR),
чтобы получить более подробную информацию.

VFDS\
Иногда вам нужно погрузиться в поток данных, путешествующих по сети. Воз-
можно, вы хотите отладить веб-API или отследить некую проблему безопасности.
Библиотека • ƒ’› и программа предоставляют предметно-ориентированный язык
для создания и анализа пакетов в Python. Работать с ней гораздо проще, чем писать
и отлаживать программы, написанные на языке С.
Стандартная команда для установки выглядит так: pip install • ƒ’›. Докумен-
тация (KWWSVVFDS\UHDGWKHGRFVLR) этой библиотеки довольно обширна. Если вы ис-
пользуете такие инструменты, как – ’†—’ или ™‹”‡•Šƒ”, для исследования проблем,
связанных с протоколом TCP, то вам следует обратить внимание на • ƒ’›. Наконец,
не следует путать библиотеки • ƒ’› и • ”ƒ’›; последняя рассмотрена в разделе «По-
иск и выборка данных» главы 18.

1HWFDW
Еще один инструмент для проверки сетей и портов — Netcat (KWWSVRUHLOO\.+),
название которого зачастую сокращают до  . Рассмотрим пример соединения HTTP
с сайтом Google, где запросим базовую информацию о главной странице:
ɛ$ nc [Link] 80
HEAD / HTTP/1.1

ŵɨŜɨɩɥɥ
ƒ–‡śƒ–řɩɮ —Žɩɥɨɰɩɨśɥɫśɥɩ 
ŜŜŜ

В следующей главе, в подразделе «Тестируем с помощью telnet» раздела «Веб-


клиенты», вы увидите пример, в котором делается то же самое.
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

ǷȈȚȚȍȘȕȣȌȓȧȘȈȉȖȚȣșșȍȚȧȔȐ
Сетевые приложения можно создать на основе некоторых простых паттернов.
‰Самым распространенным является «Запрос — ответ», также известный как
«Клиент — сервер». Работает синхронно: клиент ожидает ответа сервера. Вы ви-
дели множество примеров его использования в этой книге. Ваш браузер — это
также клиент, делающий HTTP-запрос веб-серверу, который возвращает ответ.
‰Еще один распространенный паттерн — «Разветвление на выходе»: вы отправля-
ете данные любому доступному работнику из пула процессов. Примером служит
веб-сервер, расположенный за балансировщиком нагрузки.
‰Противоположностью этого паттерна является «Разветвление на входе»: вы
принимаете данные из одного или нескольких источников. В качестве примера
можно привести регистратор, который принимает текстовые сообщения от не-
скольких процессов и записывает их в единый файл журнала.
‰Еще один паттерн похож на радио- или телепередачи, он называется «Публика-
ция — подписка» или pub — sub. В рамках этого паттерна публикатор рассылает
данные. В простой системе их получат все подписчики. Однако зачастую они
могут указать, что заинтересованы только в определенных типах данных (подоб-
ные типы часто называются темами), и публикатор будет отправлять лишь эту
информацию. Поэтому, в отличие от паттерна «Разветвление на входе», заданный
фрагмент данных может получить более чем один подписчик. Если на тему никто
не подписался, то данные будут проигнорированы.
Рассмотрим некоторые примеры использования паттерна «Запрос — ответ», а за-
тем и паттерна «Публикация — подписка».

ǷȈȚȚȍȘȕ©ǯȈȗȘȖș²ȖȚȊȍȚª
Этот паттерн самый распространенный. Вы запрашиваете данные о DNS, сети или
электронной почте у соответствующих серверов, и они либо возвращают ответ, либо
сообщают о проблеме.
Я только что показал, как выполнять простые запросы с помощью протоколов
UDP и TCP, но создать приложение для работы с сетями на уровне сокетов довольно
сложно. Посмотрим, сможет ли нам помочь ZeroMQ.

=HUR04
ZeroMQ — библиотека, а не сервер. Иногда называемые сокетами на стероидах, со-
кеты ZeroMQ делают то, чего вы вроде бы ожидаете от обычных сокетов:
‰происходит обмен сообщениями целиком;
‰выполняются повторные соединения при обрыве;
‰выполняется буферизация данных для их сохранения в том случае, когда отпра-
вители и получатели не синхронизированы.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Онлайн-руководство (KWWS]JXLGH]HURPTRUJ) написано хорошим языком, в нем


представлено лучшее из виденных мной описаний сетевых паттернов. Питер Хинт-
дженс создал печатную версию (ZeroMQ: Messaging for Many Applications, O’Reilly),
внутри которой хороший код, а на обложке — большая рыба (хорошо, что не наобо-
рот). Все примеры в этом печатном руководстве написаны на языке С, но онлайн-
версия позволяет выбирать один из нескольких языков для каждого примера. Можно
даже выбрать примеры для Python (KWWSELWO\]HURPTS\). В этой главе я покажу
базовые приемы работы с ZeroMQ в Python.
ZeroMQ похож на конструктор Lego, и все мы знаем, что даже из небольшого
количества деталей можно построить удивительное множество вещей. В этом слу-
чае вы будете создавать сети из сокетов нескольких типов и паттернов. Основные
«детальки Lego», представленные в следующем списке, являются типами сокетов
ZeroMQ, которые из-за превратностей судьбы выглядят как паттерны работы в сети,
рассмотренные нами ранее:
‰REQ (синхронный запрос);
‰REP (синхронный ответ);
‰DEALER (асинхронный запрос);
‰ROUTER (асинхронный ответ);
‰PUB (публикация);
‰SUB (подписка);
‰PUSH (разветвление на выходе);
‰PULL (разветвление на входе).
Чтобы попробовать поработать с ними самостоятельно, вам нужно установить
библиотеку ZeroMQ, введя следующую команду:
ɛpip install pyzmq

Простейший паттерн — это одна пара «Запрос — ответ». Он является синхронным:


один сокет создает запрос, а затем другой сокет отвечает на него. Сначала рассмо-
трим код ответа (сервера) œ“ɏ•‡”˜‡”Ŝ’›, показанный в примере 17.5.

ǷȘȐȔȍȘ]PTBVHUYHUS\
‹’‘”–œ“

Š‘•–ʰɐɨɩɮŜɥŜɥŜɨɐ
’‘”–ʰɭɮɯɰ
‘–‡š–ʰœ“Ŝ‘–‡š–ſƀ
•‡”˜‡”ʰ ‘–‡š–Ŝ•‘ ‡–ſœ“Ŝƀ
•‡”˜‡”Ŝ„‹†ſɑ– ’śŵŵʩ•śʩ•ɑʩſŠ‘•–ř’‘”–ƀƀ
™Š‹Ž‡”—‡ś
ɤȢȚȜȘȔșȠȥȟșȘȧȲȭșȗȢțȔȣȤȢȥȔȞȟȜșȡȦȔ
”‡“—‡•–ɏ„›–‡•ʰ•‡”˜‡”Ŝ”‡ ˜ſƀ
”‡“—‡•–ɏ•–”ʰ”‡“—‡•–ɏ„›–‡•Ŝ†‡ ‘†‡ſɐ—–ˆŞɯɐƀ
’”‹–ſɑŠƒ–˜‘‹ ‡‹›Їƒ†•ƒ›•śʩ•ɑʩ”‡“—‡•–ɏ•–”ƀ
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

”‡’Ž›ɏ•–”ʰɑ–‘’•ƒ›‹‰śʩ•ɑʩ”‡“—‡•–ɏ•–”
”‡’Ž›ɏ„›–‡•ʰ„›–‡•ſ”‡’Ž›ɏ•–”řɐ—–ˆŞɯɐƀ
•‡”˜‡”Ŝ•‡†ſ”‡’Ž›ɏ„›–‡•ƀ

Мы создаем объект типа ‘–‡š– — это объект ZeroMQ, который сопровождает


состояние. Далее создаем сокет ZeroMQ, имеющий тип  (получено от REPly —
ответ). Вызываем метод „‹†ſƀ, чтобы заставить его слушать определенный IP-адрес
и порт. Обратите внимание: они указаны в строке, ɐ– ’śŵŵŽ‘ ƒŽŠ‘•–śɭɮɯɰɐ, а не
в кортеже, как это было в случае с простыми сокетами.
Код в данном примере продолжает получать запросы от отправителя и посылать
ответы. Эти сообщения могут быть очень длинными — ZeroMQ обработает детали.
В примере 17.6 показан код клиента, œ“ɏ Ž‹‡–Ŝ’›. Он имеет тип  (получено
от REQuest — запрос), в нем вызывается метод ‘‡ –ſƀ, а не „‹†ſƀ:

ǷȘȐȔȍȘ]PTBFOLHQWS\
‹’‘”–œ“

Š‘•–ʰɐɨɩɮŜɥŜɥŜɨɐ
’‘”–ʰɭɮɯɰ
‘–‡š–ʰœ“Ŝ‘–‡š–ſƀ
Ž‹‡–ʰ ‘–‡š–Ŝ•‘ ‡–ſœ“Ŝƀ
Ž‹‡–Ŝ ‘‡ –ſɑ– ’śŵŵʩ•śʩ•ɑʩſŠ‘•–ř’‘”–ƀƀ
ˆ‘”—‹”ƒ‰‡ſɨřɭƀś
”‡“—‡•–ɏ•–”ʰɑ‡••ƒ‰‡ɤʩ•ɑʩ—
”‡“—‡•–ɏ„›–‡•ʰ”‡“—‡•–ɏ•–”Ŝ‡ ‘†‡ſɐ—–ˆŞɯɐƀ
 Ž‹‡–Ŝ•‡†ſ”‡“—‡•–ɏ„›–‡•ƀ
”‡’Ž›ɏ„›–‡•ʰ Ž‹‡–Ŝ”‡ ˜ſƀ
”‡’Ž›ɏ•–”ʰ”‡’Ž›ɏ„›–‡•Ŝ†‡ ‘†‡ſɐ—–ˆŞɯɐƀ
’”‹–ſɑ‡–ʩ•ř”‡ ‡‹˜‡†ʩ•ɑʩſ”‡“—‡•–ɏ•–”ř”‡’Ž›ɏ•–”ƀƀ

Пришло время их запустить. Одно интересное отличие от примера с простыми


сокетами заключается в том, что вы можете запускать клиент и сервер в любом по-
рядке. Начнем с запуска сервера в одном окне в фоновом режиме:
ɛpython zmq_server.py &

Запустите клиент в том же окне:


ɛpython zmq_client.py

Вы увидите чередующиеся строки от сервера и клиента:


Šƒ–˜‘‹ ‡‹›Їƒ†•ƒ›•ɐ‡••ƒ‰‡ɤɨɐ
‡–ɐ‡••ƒ‰‡ɤɨɐř”‡ ‡‹˜‡†ɐ–‘’•ƒ›‹‰‡••ƒ‰‡ɤɨɐ
Šƒ–˜‘‹ ‡‹›Їƒ†•ƒ›•ɐ‡••ƒ‰‡ɤɩɐ
‡–ɐ‡••ƒ‰‡ɤɩɐř”‡ ‡‹˜‡†ɐ–‘’•ƒ›‹‰‡••ƒ‰‡ɤɩɐ
Šƒ–˜‘‹ ‡‹›Їƒ†•ƒ›•ɐ‡••ƒ‰‡ɤɪɐ
‡–ɐ‡••ƒ‰‡ɤɪɐř”‡ ‡‹˜‡†ɐ–‘’•ƒ›‹‰‡••ƒ‰‡ɤɪɐ
Šƒ–˜‘‹ ‡‹›Їƒ†•ƒ›•ɐ‡••ƒ‰‡ɤɫɐ
‡–ɐ‡••ƒ‰‡ɤɫɐř”‡ ‡‹˜‡†ɐ–‘’•ƒ›‹‰‡••ƒ‰‡ɤɫɐ
Šƒ–˜‘‹ ‡‹›Їƒ†•ƒ›•ɐ‡••ƒ‰‡ɤɬɐ
‡–ɐ‡••ƒ‰‡ɤɬɐř”‡ ‡‹˜‡†ɐ–‘’•ƒ›‹‰‡••ƒ‰‡ɤɬɐ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Наш клиент завершает работу после отправки пятого сообщения, но мы не дава-


ли такого указания серверу, поэтому он будет ожидать новых сообщений. При по-
вторном запуске клиент выведет те же пять строк, сервер тоже выведет их. Если вы
не завершите процесс œ“ɏ•‡”˜‡”Ŝ’› и попробуете запустить еще один, то Python
пожалуется на то, что адрес уже используется:
ɛpython zmq_server.py

ƃɩƄɪɬɭ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑœ“ɏ•‡”˜‡”Ŝ’›ɑřŽ‹‡ɮř‹ʳ‘†—އʴ
•‡”˜‡”Ŝ„‹†ſɑ– ’śŵŵʩ•śʩ•ɑʩſŠ‘•–ř’‘”–ƀƀ
 ‹Ž‡ɑ•‘ ‡–Ŝ’›šɑřŽ‹‡ɫɫɫř‹œ“Ŝ„ƒ ‡†Ŝ ›–Š‘Ŝ•‘ ‡–Ŝ‘ ‡–Ŝ„‹†
ſœ“ŵ„ƒ ‡†ŵ ›–Š‘ŵ•‘ ‡–Ŝ śɫɥɮɭƀ
 ‹Ž‡ɑ Ї ” Ŝ’š†ɑřŽ‹‡ɩɨř‹œ“Ŝ„ƒ ‡†Ŝ ›–Š‘Ŝ Ї ” Ŝɏ Ї ɏ”
ſœ“ŵ„ƒ ‡†ŵ ›–Š‘ŵ•‘ ‡–Ŝ śɭɥɪɩƀ
œ“Ŝ‡””‘”Ŝ””‘”ś††”‡••ƒŽ”‡ƒ†›‹—•‡

Сообщения нужно отправлять как байтовые строки, поэтому в нашем примере


мы закодировали строки в формате UTF-8. Вы можете отправить любое количество
сообщений, если будете преобразовывать их в тип bytes. Мы использовали простые
текстовые строки как источник сообщений, поэтому методов ‡ ‘†‡ſƀ и †‡ ‘†‡ſƀ
будет достаточно для трансформации их в байтовые строки и обратно. Если ваши
сообщения имеют другие типы данных, то можете использовать библиотеку, такую
как MessagePack (KWWSPVJSDFNRUJ).
Даже этот простой паттерн REQ — REP позволяет реализовать некоторые ша-
блоны коммуникации, поскольку любое количество клиентов REQ может исполь-
зовать метод ‘‡ –ſƀ, чтобы соединиться с единственным сервером . Сервер
обрабатывает запросы синхронно по одному за раз, но не сбрасывает другие запро-
сы, ожидающие его внимания. ZeroMQ буферизует сообщения до определенного
лимита; как раз из-за этого в его имени есть буква Q. Здесь она расшифровывается
как Queue — «очередь», M — Message («сообщение»), а Zero («ноль») означает, что
ему не нужны посредники.
Несмотря на то что ZeroMQ не предоставляет никаких центральных посредников
(промежуточных участников), вы можете создать их в любой момент. Например,
используйте сокеты DEALER и ROUTER, чтобы асинхронно подключиться к не-
скольким источникам и/или конечным точкам.
Несколько сокетов REQ подключаются к одному сокету ROUTER, который
передает каждый запрос сокету DEALER, а тот, в свою очередь, связывается с под-
ключенным к нему сокетом REP (рис. 17.1). Процесс похож на то, как несколько бра-
узеров связываются с прокси-сервером, расположенным перед фермой веб-серверов.
Это позволяет при необходимости добавить несколько клиентов и серверов.
Сокеты REQ соединяются только с сокетом ROUTER, сокет DEALER соединя-
ется с несколькими сокетами REP, лежащими позади него. ZeroMQ заботится о де-
талях, гарантируя, что нагрузка, создаваемая запросами, сбалансирована и ответы
будут возвращаться по правильному адресу.
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

ǸȐșǰșȗȖȓȤȏȖȊȈȕȐȍȗȖșȘȍȌȕȐȒȈȌȓȧșȖȍȌȐȕȍȕȐȧ
șȕȍșȒȖȓȤȒȐȔȐȒȓȐȍȕȚȈȔȐȐșȍȘȊȍȘȈȔȐ

Еще один сетевой паттерн называется «Вентилятор», в его рамках используются


сокеты PUSH — для перепоручения асинхронных задач, и сокеты PULL — для сбора
результатов.
Последняя значимая особенность ZeroMQ — возможность масштабироваться,
просто изменив тип соединения с сокетом при его создании:
‰– ’ выполняет соединение между процессами на одной или нескольких ма-
шинах;
‰‹’ выполняет соединение между процессами на одной машине;
‰‹’”‘ выполняет соединение между потоками одного процесса.
Последнее соединение, ‹’”‘ , — способ передать данные между потоками, избе-
жав блокировок; является альтернативой примеру работы с потоками, показанному
в подразделе «Потоки» на с. 311.
После использования ZeroMQ вы, возможно, больше не захотите возвращаться
к написанию чистого кода для сокетов.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǬȘțȋȐȍȐȕșȚȘțȔȍȕȚȣȖȉȔȍȕȈșȖȖȉȡȍȕȐȧȔȐ
ZeroMQ определенно не единственная библиотека, отвечающая за передачу сообще-
ний, которая поддерживается Python. Передача сообщений — это одна из самых
популярных идей в работе с сетями, и Python старается соответствовать другим
языкам программирования:
‰проект Apache, чей веб-сервер вы увидите в подразделе «Apache» на с. 411, также
поддерживает проект ActiveMQ (KWWSVDFWLYHPTDSDFKHRUJ), который включает
несколько интерфейсов Python, использующих простой текстовый протокол
STOMP (KWWSVRUHLOO\DKB0);
‰популярна также библиотека RabbitMQ (KWWSZZZUDEELWPTFRP), вы можете
прочесть онлайн-руководство для нее (KWWSELWO\UDEELWPTWXW);
‰NATS (KWWSZZZQDWVLR) — это быстрая система обмена сообщениями, написан-
ная на Go.

ǷȈȚȚȍȘȕ©ǷțȉȓȐȒȈȞȐȧ²ȗȖȌȗȐșȒȈª
Данный паттерн не является очередью — это широковещательная система. Один (или
более) процесс публикует сообщения. Каждый процесс-подписчик указывает, со-
общения какого типа он хочет получать. Копия каждого сообщения отправляется
каждому подписчику, указавшему данный тип. Поэтому то или иное сообщение мо-
жет быть обработано однажды, более чем однажды или ни разу. Каждый публикатор
просто выполняет рассылку и не знает, кто — если таковые есть — его слушает.

5HGLV
Вы уже видели Redis в главе 16, он использовался как сервер структур данных.
Однако он также содержит систему публикации — подписки. Публикатор создает
сообщения, имеющие тему и значение, а подписчики указывают, какие темы хотят
получать.
В примере 17.7 показан публикато𠔇†‹•ɏ’—„Ŝ’›.

ǷȘȐȔȍȘUHGLVBSXES\
‹’‘”–”‡†‹•
‹’‘”–”ƒ†‘

‘ʰ”‡†‹•Ŝ‡†‹•ſƀ
ƒ–•ʰƃɐ•‹ƒ‡•‡ɐřɐ’‡”•‹ƒɐřɐƒ‹‡ ‘‘ɐřɐ‘”™‡‰‹ƒˆ‘”‡•–ɐƄ
Šƒ–•ʰƃɐ•–‘˜‡’‹’‡ɐřɐ„‘™Ž‡”ɐřɐ–ƒŞ‘Ş•Šƒ–‡”ɐřɐˆ‡†‘”ƒɐƄ
ˆ‘”•‰‹”ƒ‰‡ſɨɥƀś
 ƒ–ʰ”ƒ†‘Ŝ Š‘‹ ‡ſ ƒ–•ƀ
Šƒ–ʰ”ƒ†‘Ŝ Š‘‹ ‡ſŠƒ–•ƀ
’”‹–ſɐ—„Ž‹•Šśʩ•™‡ƒ”•ƒʩ•ɐʩſ ƒ–řŠƒ–ƀƀ
 ‘Ŝ’—„Ž‹•Šſ ƒ–řŠƒ–ƀ
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

Каждая тема представляет собой породу кота, а сопутствующее значение — вид


шляпы.
В примере 17.8 показан подписчик ”‡†‹•ɏ•—„Ŝ’›.

ǷȘȐȔȍȘUHGLVBVXES\
‹’‘”–”‡†‹•
‘ʰ”‡†‹•Ŝ‡†‹•ſƀ

–‘’‹ •ʰƃɐƒ‹‡ ‘‘ɐřɐ’‡”•‹ƒɐƄ


•—„ʰ ‘Ŝ’—„•—„ſƀ
•—„Ŝ•—„• ”‹„‡ſ–‘’‹ •ƀ
ˆ‘”•‰‹•—„ŜŽ‹•–‡ſƀś
‹ˆ•‰ƃɐ–›’‡ɐƄʰʰɐ‡••ƒ‰‡ɐś
 ƒ–ʰ•‰ƃɐ Šƒ‡ŽɐƄ
Šƒ–ʰ•‰ƃɐ†ƒ–ƒɐƄ
’”‹–ſɐ—„• ”‹„‡śʩ•™‡ƒ”•ƒʩ•ɐʩſ ƒ–řŠƒ–ƀƀ

Подписчик показывает, что он хочет принимать сообщения о котах породы ɐƒ‹‡


‘‘ɐ и ɐ’‡”•‹ƒɐ и никаких других. Метод Ž‹•–‡ſƀ возвращает словарь. Если он
имеет тип ɐ‡••ƒ‰‡ɐ, то это значит, что он был отправлен публикатору и совпадает
с нашими критериями. Ключ ɐ Šƒ‡Žɐ — тема (порода кота), а ключ ɐ†ƒ–ƒɐ содер-
жит сообщение (шляпа).
Если вы сначала запустите публикатор, который никто не станет слушать, то
он будет похож на мима, упавшего в лесу (издаст ли он звук?), поэтому сначала за-
пустим подписчик:
ɛpython redis_sub.py

Далее запустим публикатор. Он отправит десять сообщений, а затем завершит


работу:
ɛpython redis_pub.py
—„Ž‹•Šśƒ‹‡ ‘‘™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„Ž‹•Šś‘”™‡‰‹ƒˆ‘”‡•–™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„Ž‹•Šś‘”™‡‰‹ƒˆ‘”‡•–™‡ƒ”•ƒ–ƒŞ‘Ş•Šƒ–‡”
—„Ž‹•Šśƒ‹‡ ‘‘™‡ƒ”•ƒ„‘™Ž‡”
—„Ž‹•Šś•‹ƒ‡•‡™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„Ž‹•Šś‘”™‡‰‹ƒˆ‘”‡•–™‡ƒ”•ƒ–ƒŞ‘Ş•Šƒ–‡”
—„Ž‹•Šśƒ‹‡ ‘‘™‡ƒ”•ƒ„‘™Ž‡”
—„Ž‹•Šś’‡”•‹ƒ™‡ƒ”•ƒ„‘™Ž‡”
—„Ž‹•Šś‘”™‡‰‹ƒˆ‘”‡•–™‡ƒ”•ƒ„‘™Ž‡”
—„Ž‹•Šśƒ‹‡ ‘‘™‡ƒ”•ƒ•–‘˜‡’‹’‡

Подписчик интересуют только две породы котов:


ɛpython redis_sub.py
—„• ”‹„‡śƒ‹‡ ‘‘™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„• ”‹„‡śƒ‹‡ ‘‘™‡ƒ”•ƒ„‘™Ž‡”
—„• ”‹„‡śƒ‹‡ ‘‘™‡ƒ”•ƒ„‘™Ž‡”
—„• ”‹„‡ś’‡”•‹ƒ™‡ƒ”•ƒ„‘™Ž‡”
—„• ”‹„‡śƒ‹‡ ‘‘™‡ƒ”•ƒ•–‘˜‡’‹’‡
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Мы не отдали подписчику указание завершить работу, поэтому он все еще ждет


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

=HUR04
У ZeroMQ нет центрального сервера, поэтому каждый публикатор пишет всем под-
писчикам. Перепишем наш пример для ZeroMQ. Публикатор œ“ɏ’—„Ŝ’› выглядит
так, как показано в примере 17.9.

ǷȘȐȔȍȘ]PTBSXES\
‹’‘”–œ“
‹’‘”–”ƒ†‘
‹’‘”––‹‡
Š‘•–ʰɐƋɐ
’‘”–ʰɭɮɯɰ
–šʰœ“Ŝ‘–‡š–ſƀ
’—„ʰ –šŜ•‘ ‡–ſœ“Ŝƀ
’—„Ŝ„‹†ſɐ– ’śŵŵʩ•śʩ•ɐʩſŠ‘•–ř’‘”–ƀƀ
ƒ–•ʰƃɐ•‹ƒ‡•‡ɐřɐ’‡”•‹ƒɐřɐƒ‹‡ ‘‘ɐřɐ‘”™‡‰‹ƒˆ‘”‡•–ɐƄ
Šƒ–•ʰƃɐ•–‘˜‡’‹’‡ɐřɐ„‘™Ž‡”ɐřɐ–ƒŞ‘Ş•Šƒ–‡”ɐřɐˆ‡†‘”ƒɐƄ
–‹‡Ŝ•އ‡’ſɨƀ
ˆ‘”•‰‹”ƒ‰‡ſɨɥƀś
 ƒ–ʰ”ƒ†‘Ŝ Š‘‹ ‡ſ ƒ–•ƀ
 ƒ–ɏ„›–‡•ʰ ƒ–Ŝ‡ ‘†‡ſɐ—–ˆŞɯɐƀ
Šƒ–ʰ”ƒ†‘Ŝ Š‘‹ ‡ſŠƒ–•ƀ
Šƒ–ɏ„›–‡•ʰŠƒ–Ŝ‡ ‘†‡ſɐ—–ˆŞɯɐƀ
’”‹–ſɐ—„Ž‹•Šśʩ•™‡ƒ”•ƒʩ•ɐʩſ ƒ–řŠƒ–ƀƀ
’—„Ŝ•‡†ɏ—Ž–‹’ƒ”–ſƃ ƒ–ɏ„›–‡•řŠƒ–ɏ„›–‡•Ƅƀ

Обратите внимание на то, как в этом коде используется кодировка UTF-8 для
темы и строки значения.
Файл подписчика называется œ“ɏ•—„Ŝ’› (пример 17.10).

ǷȘȐȔȍȘ]PTBVXES\
‹’‘”–œ“
Š‘•–ʰɐɨɩɮŜɥŜɥŜɨɐ
’‘”–ʰɭɮɯɰ
–šʰœ“Ŝ‘–‡š–ſƀ
•—„ʰ –šŜ•‘ ‡–ſœ“Ŝƀ
•—„Ŝ ‘‡ –ſɐ– ’śŵŵʩ•śʩ•ɐʩſŠ‘•–ř’‘”–ƀƀ
–‘’‹ •ʰƃɐƒ‹‡ ‘‘ɐřɐ’‡”•‹ƒɐƄ
ˆ‘”–‘’‹ ‹–‘’‹ •ś
•—„Ŝ•‡–•‘ ‘’–ſœ“Ŝ ř–‘’‹ Ŝ‡ ‘†‡ſɐ—–ˆŞɯɐƀƀ
™Š‹Ž‡”—‡ś
 ƒ–ɏ„›–‡•řŠƒ–ɏ„›–‡•ʰ•—„Ŝ”‡ ˜ɏ—Ž–‹’ƒ”–ſƀ
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

 ƒ–ʰ ƒ–ɏ„›–‡•Ŝ†‡ ‘†‡ſɐ—–ˆŞɯɐƀ


Šƒ–ʰŠƒ–ɏ„›–‡•Ŝ†‡ ‘†‡ſɐ—–ˆŞɯɐƀ
’”‹–ſɐ—„• ”‹„‡śʩ•™‡ƒ”•ƒʩ•ɐʩſ ƒ–řŠƒ–ƀƀ

В этом коде мы подписываемся на два разных байтовых значения: две строки из


–‘’‹ •, закодированные с помощью UTF-8.

ȅȚȖȔȖȎȍȚȗȖȒȈȏȈȚȤșȧȕȍȔȕȖȋȖȏȈȗțȚȈȕȕȣȔȕȖȍșȓȐȊȣȝȖȚȐȚȍȗȖȌȗȐșȣȊȈȚȤșȧȕȈ
ȊșȍȚȍȔȣȚȖȕțȎȕȖȗȖȌȗȐșȈȚȤșȧȕȈȗțșȚțȦșȚȘȖȒțȉȈȑȚȖȊ  ǵȍșȌȍȓȈȊȥȚȖȋȖȊȣ
ȕȍȗȖȓțȟȐȚȍȕȐȟȍȋȖ

Обратите внимание: в публикаторе мы вызываем метод •‡†ɏ—Ž–‹’ƒ”–ſƀ, а в под-


писчике — ”‡ ˜ɏ—Ž–‹’ƒ”–ſƀ. Это позволяет отправлять многокомпонентные со-
общения и использовать первую часть как тему. Мы также можем отправить тему
и сообщение как простую строку или строку байтов, но подход, где коты и шляпы
разделены, кажется более чистым.
Запустите подписчик:
ɛpython zmq_sub.py

Запустите публикатор. Он немедленно отправит десять сообщений, а затем за-


вершит работу:
ɛpython zmq_pub.py
—„Ž‹•Šś‘”™‡‰‹ƒˆ‘”‡•–™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„Ž‹•Šś•‹ƒ‡•‡™‡ƒ”•ƒ„‘™Ž‡”
—„Ž‹•Šś’‡”•‹ƒ™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„Ž‹•Šś‘”™‡‰‹ƒˆ‘”‡•–™‡ƒ”•ƒˆ‡†‘”ƒ
—„Ž‹•Šśƒ‹‡ ‘‘™‡ƒ”•ƒ–ƒŞ‘Ş•Šƒ–‡”
—„Ž‹•Šśƒ‹‡ ‘‘™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„Ž‹•Šś’‡”•‹ƒ™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„Ž‹•Šś‘”™‡‰‹ƒˆ‘”‡•–™‡ƒ”•ƒˆ‡†‘”ƒ
—„Ž‹•Šś‘”™‡‰‹ƒˆ‘”‡•–™‡ƒ”•ƒ„‘™Ž‡”
—„Ž‹•Šśƒ‹‡ ‘‘™‡ƒ”•ƒ„‘™Ž‡”

Подписчик выведет на экран все, что запросил и получил:


—„• ”‹„‡ś’‡”•‹ƒ™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„• ”‹„‡śƒ‹‡ ‘‘™‡ƒ”•ƒ–ƒŞ‘Ş•Šƒ–‡”
—„• ”‹„‡śƒ‹‡ ‘‘™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„• ”‹„‡ś’‡”•‹ƒ™‡ƒ”•ƒ•–‘˜‡’‹’‡
—„• ”‹„‡śƒ‹‡ ‘‘™‡ƒ”•ƒ„‘™Ž‡”

ǬȘțȋȐȍȐȕșȚȘțȔȍȕȚȣ©ǷțȉȓȐȒȈȞȐȐ²ȗȖȌȗȐșȒȐª
Вам могут пригодиться следующие ссылки Python.
‰RabbitMQ — широко известный посредник сообщений, Python API для него на-
зывается ’‹ƒ. Обратитесь к тематической документации (KWWSSLNDUHDGWKHGRFVRUJ)
и руководству по «Публикации — подписке» (KWWSELWO\SXEVXEWXW).
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰Перейдите в окно поиска PyPi (KWWSVS\SLS\WKRQRUJ) и введите pubsub, чтобы


найти пакеты для Python, такие как pypubsub (KWWSSXEVXEVRXUFHIRUJHQHW).
‰Протокол PubSubHubbub (KWWSVFRGHJRRJOHFRPSSXEVXEKXEEXE) позволяет под-
писчикам зарегистрировать функции обратного вызова для публикаторов.
‰NATS (KWWSVQDWVLR) — это быстрая система обмена сообщениями с открытым
исходным кодом, которая поддерживает паттерны «Публикация — подписка»,
«Запрос — ответ» и очереди.

ǰȕȚȍȘȕȍȚșȍȘȊȐșȣ
Python имеет широкий набор инструментов для работы с сетями. В следующих
подразделах мы рассмотрим способы автоматизации наиболее популярных ин-
тернет-сервисов. В сети доступна полная официальная документация (KWWSELWO\
S\LQWHUQHW).

ǬȖȔȍȕȕȈȧșȐșȚȍȔȈȐȔȍȕ
Компьютеры имеют числовые IP-адреса, например [Link], однако имена
мы запоминаем лучше, чем числа. Доменная система имен (Domain Name System,
DNS) — критически важный интернет-сервис, который преобразует IP-адреса
в имена и обратно с помощью распределенной базы данных. Когда вы используете
браузер и внезапно видите сообщение наподобие looking up host, вы, возможно,
потеряли соединение с Интернетом, и первым предположением должен стать
сбой DNS.
Некоторые функции DNS можно найти в низкоуровневом модуле •‘ ‡–. Функ-
ция ‰‡–Š‘•–„—ƒ‡ſƀ возвращает IP-адрес доменного имени, а ее расширенная версия
geth‘•–„›ƒ‡ɏ‡šſƀ возвращает имя, список альтернативных имен и список адресов:
ʴʴʴ‹’‘”–•‘ ‡–
ʴʴʴ•‘ ‡–Ŝ‰‡–Š‘•–„›ƒ‡ſɐ™™™Ŝ ”ƒ’’›–ƒš‹†‡”›Ŝ ‘ɐƀ
ɐɭɭŜɭŜɫɫŜɫɐ
ʴʴʴ•‘ ‡–Ŝ‰‡–Š‘•–„›ƒ‡ɏ‡šſɐ™™™Ŝ ”ƒ’’›–ƒš‹†‡”›Ŝ ‘ɐƀ
ſɐ ”ƒ’’›–ƒš‹†‡”›Ŝ ‘ɐřƃɐ™™™Ŝ ”ƒ’’›–ƒš‹†‡”›Ŝ ‘ɐƄřƃɐɭɭŜɭŜɫɫŜɫɐƄƀ

Метод ‰‡–ƒ††”‹ˆ‘ſƀ ищет IP-адрес, но также возвращает достаточное количе-


ство информации, чтобы создать сокет, который с ним соединится:
ʴʴʴ•‘ ‡–Ŝ‰‡–ƒ††”‹ˆ‘ſɐ™™™Ŝ ”ƒ’’›–ƒš‹†‡”›Ŝ ‘ɐřɯɥƀ
ƃſɩřɩřɨɮřɐɐřſɐɭɭŜɭŜɫɫŜɫɐřɯɥƀƀř
ſɩřɨřɭřɐɐřſɐɭɭŜɭŜɫɫŜɫɐřɯɥƀƀƄ

Предыдущий вызов вернул два кортежа: первый — для UDP, а второй — для TCP
(6 в строке ɩ, ɨ, 6 — это значение для TCP).
Вы можете запросить информацию лишь для TCP или только для UDP:
ʴʴʴ•‘ ‡–Ŝ‰‡–ƒ††”‹ˆ‘ſɐ™™™Ŝ ”ƒ’’›–ƒš‹†‡”›Ŝ ‘ɐřɯɥř•‘ ‡–Ŝ ɏ ř
•‘ ‡–Ŝɏƀ
ƃſɩřɨřɭřɐɐřſɐɭɭŜɭŜɫɫŜɫɐřɯɥƀƀƄ
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

Некоторые номера портов для TCP и UDP (KWWSELWO\WFSXGSSRUWV) зарезервиро-


ваны определенными сервисами IANA и связаны с именами сервисов. Например,
HTTP имеет имя http, ему присвоен номер порта TCP 80.
Эти функции преобразуют имена сервисов в номера портов и наоборот:
ʴʴʴ‹’‘”–•‘ ‡–
ʴʴʴ•‘ ‡–Ŝ‰‡–•‡”˜„›ƒ‡ſɐŠ––’ɐƀ
ɯɥ
ʴʴʴ•‘ ‡–Ŝ‰‡–•‡”˜„›’‘”–ſɯɥƀ
ɐŠ––’ɐ

ǴȖȌțȓȐ3\WKRQȌȓȧȘȈȉȖȚȣ
șȥȓȍȒȚȘȖȕȕȖȑȗȖȟȚȖȑ
Стандартная библиотека Python содержит следующие модули для работы с элек-
тронной почтой:
‰•–’Ž‹„ (KWWSVRUHLOO\BN)9) — для отправки сообщений по электронной почте
с помощью простого протокола передачи почты (Simple Mail Transfer Protocol,
SMTP);
‰‡ƒ‹Ž (KWWSVRUHLOO\:9*E() — для создания и анализа сообщений электронной
почты;
‰poplib (KWWSVRUHLOO\[L-7) — для чтения электронной почты с помощью протокола
почтового отделения, версия 3 (Post Office Protocol 3, POP3);
‰‹ƒ’Ž‹„ (KWWSVRUHLOO\ZHQJR) — для чтения электронной почты с помощью про-
токола доступа к электронной почте (Internet Message Access Protocol, IMAP).
Если вы хотите написать собственный SMTP-сервер на Python, то попробуйте
•–’† (KWWSVRUHLOO\-N/V') или его новую асинхронную версию — ƒ‹‘•–’† (KWWSV
DLRVPWSGUHDGWKHGRFVLR).

ǬȘțȋȐȍȗȘȖȚȖȒȖȓȣ
Используя стандартный модуль ftplib (KWWSELWO\S\IWSOLE), вы можете перемещать
байты с помощью протокола передачи файлов (File Transfer Protocol, FTP). Несмо-
тря на свой возраст, он все еще хорошо работает.
Вы видели, как эти модули применяются повсеместно в разных местах данной кни-
ги. Взгляните также на документацию, касающуюся поддержки интернет-протоколов
в стандартной библиотеке (KWWSELWO\S\LQWHUQHW).

ǪȍȉșȍȘȊȐșȣȐ$3,
Поставщики информации всегда имеют сайт, однако он предназначен для челове-
ческих глаз, а не для машин. Если данные опубликованы только на нем, то любой,
кто хочет получить к ним доступ, должен писать краулер (это показано в разделе
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

«Поиск и выборка данных» на с. 424) и переписывать их после каждого изменения


формата. Обычно данная процедура утомительна. В противоположность ей если
сайт предлагает API для своих данных, то эти данные становятся доступными для
клиентских программ. API меняются реже, чем макеты веб-страниц, поэтому и из-
менения в клиентах распространены меньше. Быстрый чистый конвейер также
позволяет упростить создание гибридных приложений — комбинаций, которые
не предвиделись, но могут быть полезны и даже прибыльны.
Простейший API — веб-интерфейс, который предоставляет данные в структури-
рованном формате, таком как JSON или XML (однако не в текстовом и не в формате
HTML). API может быть минимальным или полнофункциональным RESTful API
(данное понятие рассматривается в разделе «REST API» на с. 424), это позволит
найти еще один выход для байтов, работающих без устали.
В самом начале книги вы видели веб-API — этот интерфейс запрашивал старую
копию сайта из Internet Archive.
API особенно полезны для получения данных с популярных сайтов социаль-
ных медиа, таких как Twitter, Facebook и LinkedIn. Все эти сайты предоставляют
бесплатные API, но требуют от вас регистрации и получения ключа (долго ге-
нерируемой текстовой строки, ее часто называют токеном), который будет ис-
пользоваться при соединении. Ключ помогает сайту определить, кто получает
доступ к данным. Он также может служить для ограничения трафика запросов
к серверам.
У следующих брендов имеются интересные сервисы API:
‰New York Times (KWWSGHYHORSHUQ\WLPHVFRP);
‰Twitter (KWWSVS\WKRQWZLWWHUUHDGWKHGRFVLR);
‰Facebook (KWWSVGHYHORSHUVIDFHERRNFRPWRROV);
‰Weather Underground (KWWSZZZZXQGHUJURXQGFRPZHDWKHUDSL);
‰Marvel Comics (KWWSGHYHORSHUPDUYHOFRP).
Примеры API для карт вы можете увидеть в главе 21, примеры других API —
в главе 22.

ǹȍȘȐȈȓȐȏȈȞȐȧȌȈȕȕȣȝ
Как вы видели в главе 16, такие форматы данных, как XML, JSON и YAML, пред-
ставляют собой способы хранения структурированных текстовых данных. Сетевым
приложениям необходимо обмениваться данными с другими программами. Преоб-
разование между данными в памяти и последовательностями байтов (в частности,
перед их отправкой другому клиенту) называется сериализацией или маршаллин-
гом. JSON — это популярный формат сериализации, особенно часто используемый
в RESTful-системах, но с его помощью нельзя выразить все типы данных, использу-
емые в Python. Кроме того, как текстовый формат он выглядит более многословным
в отличие от ряда бинарных методов сериализации. Рассмотрим несколько подходов,
с которыми вы можете столкнуться.
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

ǹȍȘȐȈȓȐȏȈȞȐȧșȗȖȔȖȡȤȦSLFNOH
Python предоставляет модуль ’‹ Ž‡, позволяющий сохранить и восстановить любой
объект в специальном бинарном формате.
Помните, как JSON сошел с ума, когда встретил объект †ƒ–‡–‹‡? Для ’‹ Ž‡
это не проблема:
ʴʴʴ‹’‘”–’‹ Ž‡
ʴʴʴ‹’‘”–†ƒ–‡–‹‡
ʴʴʴ‘™ɨʰ†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡Ŝ—– ‘™ſƀ
ʴʴʴ’‹ Ž‡†ʰ’‹ Ž‡Ŝ†—’•ſ‘™ɨƀ
ʴʴʴ‘™ɩʰ’‹ Ž‡ŜŽ‘ƒ†•ſ’‹ Ž‡†ƀ
ʴʴʴ‘™ɨ
†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ſɩɥɨɫřɭřɩɩřɩɪřɩɫřɨɰřɨɰɬɮɩɩƀ
ʴʴʴ‘™ɩ
†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ſɩɥɨɫřɭřɩɩřɩɪřɩɫřɨɰřɨɰɬɮɩɩƀ

Модуль ’‹ Ž‡ работает и с вашими классами и объектами. Мы определим не-


большой класс, который называется ‹› и возвращает слово ɐ–‹›ɐ, когда исполь-
зуется как строка:
ʴʴʴ‹’‘”–’‹ Ž‡
ʴʴʴ Žƒ••‹›ſƀś
ŜŜŜ†‡ˆɏɏ•–”ɏɏſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ–‹›ɐ
ŜŜŜ
ʴʴʴ‘„Œɨʰ‹›ſƀ
ʴʴʴ‘„Œɨ
ʳɏɏƒ‹ɏɏŜ‹›‘„Œ‡ –ƒ–ɥšɨɥɥɮɭ‡†ɨɥʴ
ʴʴʴ•–”ſ‘„Œɨƀ
ɐ–‹›ɐ
ʴʴʴ’‹ Ž‡†ʰ’‹ Ž‡Ŝ†—’•ſ‘„Œɨƀ
ʴʴʴ’‹ Ž‡†
„ɐɎšɯɥɎšɥɪ ɏɏƒ‹ɏɏɎ‹›Ɏ“ɎšɥɥƀɎšɯɨ“ɎšɥɨŜɐ
ʴʴʴ‘„Œɩʰ’‹ Ž‡ŜŽ‘ƒ†•ſ’‹ Ž‡†ƀ
ʴʴʴ‘„Œɩ
ʳɏɏƒ‹ɏɏŜ‹›‘„Œ‡ –ƒ–ɥšɨɥɥɮɭ‡ɬɬɥʴ
ʴʴʴ•–”ſ‘„Œɩƀ
ɐ–‹›ɐ

Строка ’‹ Ž‡† — это обработанная ’‹ Ž‡ бинарная строка, созданная из объ-


екта ‘„Œɨ. Мы преобразовали ее в объект ‘„Œɩ с целью сделать копию объекта ‘„Œɨ.
Используйте функцию †—’ſƀ, чтобы ’‹ Ž‡ сохранил данные в файл, и функцию
Ž‘ƒ†ſƀ, чтобы ’‹ Ž‡ загрузил данные из файла.
Модуль —Ž–‹’”‘ ‡••‹‰ использует ’‹ Ž‡ для обмена данными между процессами.
Если модуль ’‹ Ž‡ не может сериализовать ваш формат данных, то с ним, воз-
можно, справится более новый сторонний пакет †‹ŽŽ (KWWSVS\SLRUJSURMHFWGLOO).

ǷȖșȒȖȓȤȒț ȔȖȌțȓȤ SLFNOH ȔȖȎȍȚ șȖȏȌȈȊȈȚȤ ȖȉȢȍȒȚȣ 3\WKRQ Ȓ ȕȍȔț ȗȘȐȔȍȕȐȔȣ


ȗȘȍȌțȗȘȍȎȌȍȕȐȧ Ȗ ȉȍȏȖȗȈșȕȖșȚȐ ȘȈșșȔȖȚȘȍȕȕȣȍ ȘȈȕȍȍ ǵȍ ȏȈȋȘțȎȈȑȚȍ Ȋ SLFNOH
ȌȈȕȕȣȍȒȖȚȖȘȣȔȕȍȌȖȊȍȘȧȍȚȍ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǬȘțȋȐȍȜȖȘȔȈȚȣșȍȘȐȈȓȐȏȈȞȐȐ
Есть и другие бинарные форматы обмена данными, они обычно компактнее и бы-
стрее, чем XML или JSON:

‰MsgPack (KWWSPVJSDFNRUJ);
‰Protocol Buffers (KWWSVFRGHJRRJOHFRPSSURWREXI);
‰Avro (KWWSDYURDSDFKHRUJGRFVFXUUHQW);
‰Thrift (KWWSWKULIWDSDFKHRUJ);
‰Lima (KWWSVOLPDUHDGWKHGRFVLR);
‰Serialize (KWWSVS\SLRUJSURMHFW6HULDOL]H) — это фронтенд Python для других форма-
тов, включающих JSON, YAML, pickle и MsgPack;
‰Бенчмарк (KWWSVRUHLOO\6(6+) различных пакетов сериализации для Python.

Поскольку они бинарные, ни один из них не может быть изменен человеком,


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

‰типы данных;
‰диапазоны значений;
‰обязательные и необязательные данные.

Ниже представлены некоторые из этих пакетов:


‰Marshmallow (KWWSVPDUVKPDOORZUHDGWKHGRFVLRHQ);
‰Pydantic (KWWSVS\GDQWLFGRFVKHOSPDQXDOLR) — использует подсказки для типов,
поэтому требует версии Python не ниже 3.6;
‰TypeSystem (KWWSVZZZHQFRGHLRW\SHV\VWHP).

Эти пакеты зачастую используются вместе с веб-серверами для гарантии того,


что байты, которые попали к ним по протоколу HTTP, отправятся в правильные
структуры данных для дальнейшей обработки.

ǻȌȈȓȍȕȕȣȍȊȣȏȖȊȣȗȘȖȞȍȌțȘ
Удаленные вызовы процедур (Remote Procedure Call, RPC) выглядят как обычные
функции, но выполняются на удаленных машинах по всей сети. Вместо того чтобы
вызывать RESTful API и передавать туда аргументы, закодированные в URL или
теле запросов, вы можете вызвать функцию RPC на собственной машине. При этом
в RPC-клиенте произойдет следующее.
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

1. Он преобразует аргументы вашей функции в байты.


2. Он отправляет закодированные байты удаленной машине.
И вот что происходит на удаленной машине.
1. Она получает закодированные байты запроса.
2. После получения байтов RPC-клиент декодирует их в оригинальные структуры
данных.
3. Затем клиент находит и вызывает локальную функцию с помощью раскодиро-
ванных данных.
4. Далее он кодирует результат работы функции.
5. Наконец, отправляет закодированные байты вызывающей стороне.
Затем машина, запустившая процесс, декодирует полученные байты в возвра-
щенные значения.
RPC — это популярный прием, и люди реализовали его множеством способов.
На стороне сервера вы запускаете серверную программу, создаете механизм для
ее связывания с помощью какого-либо способа транспортировки байтов и метода
кодирования/декодирования, определяете функции сервиса и подаете сигнал «RPC
готов к работе». Клиенты соединяются с сервером и вызывают одну из его функций
с помощью RPC.

;0/53&
Стандартная библиотека содержит только одну реализацию RPC, которая исполь-
зует в качестве формата обмена данными XML, — šŽ”’ . Вы определяете и реги-
стрируете функции на сервере, а клиент вызывает их так, будто они были импорти-
рованы. Сначала рассмотрим файл šŽ”’ ɏ•‡”˜‡”Ŝ’› (пример 17.11).

ǷȘȐȔȍȘ[POUSFBVHUYHUS\
ˆ”‘šŽ”’ Ŝ•‡”˜‡”‹’‘”–‹’އ‡”˜‡”

†‡ˆ†‘—„އſ—ƀś
”‡–—”—Ƌɩ

•‡”˜‡”ʰ‹’އ‡”˜‡”ſſɑŽ‘ ƒŽŠ‘•–ɑřɭɮɯɰƀƀ
•‡”˜‡”Ŝ”‡‰‹•–‡”ɏˆ— –‹‘ſ†‘—„އřɑ†‘—„އɑƀ
•‡”˜‡”Ŝ•‡”˜‡ɏˆ‘”‡˜‡”ſƀ

Функция, которую мы предоставляем на сервере, называется †‘—„އſƀ. В каче-


стве аргумента она ожидает число, а возвращает его же, умноженное на два. Сервер
начинает работу на определенных адресе и порте. Нам нужно зарегистрировать
функцию, чтобы сделать ее доступной клиентам с помощью RPC. Наконец, можно
запустить ее.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Теперь, как вы догадались, рассмотрим пример 17.12, в нем показывается файл


šŽ”’ ɏ Ž‹‡–Ŝ’›.

ǷȘȐȔȍȘ[POUSFBFOLHQWS\
‹’‘”–šŽ”’ Ŝ Ž‹‡–

’”‘š›ʰšŽ”’ Ŝ Ž‹‡–Ŝ‡”˜‡””‘š›ſɑŠ––’śŵŵŽ‘ ƒŽŠ‘•–śɭɮɯɰŵɑƀ


—ʰɮ
”‡•—Ž–ʰ’”‘š›Ŝ†‘—„އſ—ƀ
’”‹–ſɑ‘—„އʩ•‹•ʩ•ɑʩſ—ř”‡•—Ž–ƀƀ

Клиент соединяется с сервером с помощью функции ‡”˜‡””‘š›ſƀ. Далее он


вызывает функцию ’”‘š›Ŝ†‘—„އſƀ. Откуда она появилась? Она была создана ди-
намически с помощью сервера. Механизм RPC волшебным образом прикрепляет
имя функции к вызову удаленного сервера.
Попробуйте сами — запустите сервер и клиент:
ɛpython xmlrpc_server.py

Далее запустите клиент:


ɛpython xmlrpc_client.py
‘—„އɮ‹•ɨɫ

После этого сервер выведет на экран следующее:


ɨɩɮŜɥŜɥŜɨŞŞƃɨɪŵ ‡„ŵɩɥɨɫɩɥśɨɭśɩɪƄɑŵ ŵɨŜɨɑɩɥɥŞ

Популярные методы передачи данных — HTTP и ZeroMQ.

-62153&
JSON-RPC (версии 1.0 (KWWSVRUHLOO\2NO.D) и 2.0 (KWWSVRUHLOO\&6U)) аналогичны
XML-RPC, но в них используется JSON. Существует множество библиотек для
работы с JSON-RPC, самая простая из них состоит из двух частей: клиента (KWWSV
RUHLOO\QS[I) и сервера (KWWSVRUHLOO\3BX'U).
Они устанавливаются с помощью команд pip install Œ•‘”’ •‡”˜‡” и pip
install Œ•‘”’ Ž‹‡–.
Эти библиотеки предоставляют множество альтернативных способов напи-
сать клиент (KWWSVRUHLOO\IG) и сервер (KWWSVRUHLOO\6,1HJ). В примерах 17.13
и 17.14 я применяю встроенный в данную библиотеку сервер, который использует
порт 5000 и является простейшим.
Сначала рассмотрим сервер.

ǷȘȐȔȍȘMVRQUSFBVHUYHUS\
ˆ”‘Œ•‘”’ •‡”˜‡”‹’‘”–‡–Š‘†ř•‡”˜‡

ɒ‡–Š‘†
†‡ˆ†‘—„އſ—ƀś
”‡–—”—Ƌɩ
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

‹ˆɏɏƒ‡ɏɏʰʰɑɏɏƒ‹ɏɏɑś
•‡”˜‡ſƀ

Затем рассмотрим клиент.

ǷȘȐȔȍȘMVRQUSFBFOLHQWS\
ˆ”‘Œ•‘”’ Ž‹‡–‹’‘”–”‡“—‡•–

—ʰɮ
”‡•’‘•‡ʰ”‡“—‡•–ſɑŠ––’śŵŵŽ‘ ƒŽŠ‘•–śɬɥɥɥɑřɑ†‘—„އɑř—ʰ—ƀ
’”‹–ſɑ‘—„އɑř—řɑ‹•ɑř”‡•’‘•‡Ŝ†ƒ–ƒŜ”‡•—Ž–ƀ

Как и в случае с большинством примеров архитектуры «Клиент — сервер», рас-


смотренных в данной главе, сначала запустите сервер (сделайте это в отдельном
окне терминала или добавьте после его имени символ ĺ, чтобы запустить его в фо-
новом режиме), а затем запустите клиент:
ɛpython jsonrpc_server.py &
ƃɨƄɨɥɭɩɨ
ɛpython jsonrpc_client.py
ɨɩɮŜɥŜɥŜɨŞŞƃɩɪŵ —ŵɩɥɨɰɨɬśɪɰśɩɫƄɑŵ ŵɨŜɨɑɩɥɥŞ
‘—„އɮ‹•ɨɫ

Если вы запустили сервер в фоновом режиме, то убейте процесс после того, как
закончите работу.

0HVVDJH3DFN53&
Библиотека кодирования MessagePack имеет собственную реализацию RPC (KWWS
ELWO\PVJSDFNUSF). Она устанавливается следующим образом:
ɛpip install msgpack-rpc-python

Эта команда также установит –‘”ƒ†‘, веб-сервер, основанный на событиях, ко-


торый данная библиотека использует в качестве транспорта. Как обычно, сначала
рассмотрим сервер (•‰’ƒ ɏ•‡”˜‡”Ŝ’›, пример 17.15).

ǷȘȐȔȍȘPVJSDFNBVHUYHUS\
ˆ”‘•‰’ƒ ”’ ‹’‘”–‡”˜‡”ř††”‡••

Žƒ••‡”˜‹ ‡•ſƀś
†‡ˆ†‘—„އſ•‡Žˆř—ƀś
”‡–—”—Ƌɩ

•‡”˜‡”ʰ‡”˜‡”ſ‡”˜‹ ‡•ſƀƀ
•‡”˜‡”ŜŽ‹•–‡ſ††”‡••ſɑŽ‘ ƒŽŠ‘•–ɑřɭɮɯɰƀƀ
•‡”˜‡”Ŝ•–ƒ”–ſƀ

Класс ‡”˜‹ ‡• предоставляет свои методы как сервисы RPC. Теперь запустим
клиент, •‰’ƒ ɏ Ž‹‡–Ŝ’› (пример 17.16).
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǷȘȐȔȍȘPVJSDFNBFOLHQWS\
ˆ”‘•‰’ƒ ”’ ‹’‘”–Ž‹‡–ř††”‡••

Ž‹‡–ʰŽ‹‡–ſ††”‡••ſɑŽ‘ ƒŽŠ‘•–ɑřɭɮɯɰƀƀ
—ʰɯ
”‡•—Ž–ʰ Ž‹‡–Ŝ ƒŽŽſɐ†‘—„އɐř—ƀ
’”‹–ſɑ‘—„އʩ•‹•ʩ•ɑʩſ—ř”‡•—Ž–ƀƀ

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


пустим сервер и клиент в отдельных окнах терминала1, а затем пронаблюдаем
результат:
ɛpython msgpack_server.py

ɛpython msgpack_client.py
‘—„އɯ‹•ɨɭ

=HURUSF
Пакет zerorpc (KWWSZZZ]HURUSFLR) написан разработчиками Docker (когда они еще
назывались dotCloud). Он использует ZeroMQ и MsgPack для соединения клиентов
и серверов и магическим образом предоставляет функции как конечные точки RPC.
Введите команду pip install œ‡”‘”’ , чтобы установить его. В примерах 17.17
и 17.18 показаны клиент и сервер, работающие по принципу «запрос — ответ».

ǷȘȐȔȍȘ]HURUSFBVHUYHUS\
‹’‘”–œ‡”‘”’

Žƒ••ſƀś
†‡ˆ†‘—„އſ•‡Žˆř—ƀś
”‡–—”ɩƋ—

•‡”˜‡”ʰœ‡”‘”’ Ŝ‡”˜‡”ſſƀƀ
•‡”˜‡”Ŝ„‹†ſɑ– ’śŵŵɥŜɥŜɥŜɥśɫɩɫɩɑƀ
•‡”˜‡”Ŝ”—ſƀ

ǷȘȐȔȍȘ]HURUSFBFOLHQWS\
‹’‘”–œ‡”‘”’

Ž‹‡–ʰœ‡”‘”’ ŜŽ‹‡–ſƀ
Ž‹‡–Ŝ ‘‡ –ſɑ– ’śŵŵɨɩɮŜɥŜɥŜɨśɫɩɫɩɑƀ
—ʰɮ
”‡•—Ž–ʰ Ž‹‡–Ŝ†‘—„އſ—ƀ
’”‹–ſɑ‘—„އɑř—řɑ‹•ɑř”‡•—Ž–ƀ

Обратите внимание: клиент вызывает метод Ž‹‡–Ŝ†‘—„އſƀ даже несмотря на


то, что его определение отсутствует:

1
Или поместим его в фоновый режим с помощью символа &.
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

ɛpython zerorpc_server &


ƃɨƄɬɬɨɮɩ
ɛpython zerorpc_client.py
‘—„އɮ‹•ɨɫ

На сайте KWWSVJLWKXEFRPUSF]HURUSFS\WKRQ вы сможете найти еще больше при-


меров.

J53&
Компания Google создала gRPC (KWWSVJUSFLR) как портативный и быстрый способ
определять и соединять сервисы. Этот пакет кодирует данные как буферы прото-
колов (KWWSVRUHLOO\8,1OF).
Установите те части, которые касаются Python:
ɛpip install grpcio
ɛpip install grpcio-tools

Документация к клиенту Python (KWWSVJUSFLRGRFVTXLFNVWDUWS\WKRQ) очень по-


дробная, так что здесь я приведу лишь краткий обзор его возможностей. Кроме того,
вам может понравиться это отдельное руководство (KWWSVRUHLOO\DZQ[2).
Чтобы использовать gRPC, нужно создать файл с расширением Ŝ’”‘–‘ для опре-
деления сервиса и его методов ”’ .
Метод ”’ похож на определение функции (в нем описываются его аргументы
и возвращаемые типы) и может указывать на один из следующих паттернов работы
с сетью:
‰запрос — ответ (синхронно или асинхронно);
‰запрос — потоковый ответ;
‰потоковый запрос — ответ (синхронно или асинхронно);
‰потоковый запрос — потоковый ответ.
Отдельные запросы могут быть блокирующими или асинхронными. По потоко-
вым запросам можно итерировать.
Далее вам нужно запустить программу ‰”’ ɏ–‘‘Ž•Ŝ’”‘–‘ , чтобы создать код для
клиента и сервера. gRPC позволяет выполнить сериализацию и сетевое соединение;
вы добавляете свой код, характерный только для вашего приложения, в заглушки
клиента и сервера.
gRPC — высокоуровневая альтернатива REST API. Этот пакет больше подходит
для межсервисного взаимодействия, а REST — для публичных API.

7ZLUS
Twirp (KWWSVRUHLOO\EXI[) похож на gRPC, однако его создатели заявляют, что он
проще. Вы определяете файл с расширением Ŝ’”‘–‘, как и в случае с gRPC, и twirp
может сгенерировать код Python, который обрабатывает клиентскую и серверную
части.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǰȕșȚȘțȔȍȕȚȣțȌȈȓȍȕȕȖȋȖțȗȘȈȊȓȍȕȐȧ
‰ƒŽ– (KWWSZZZVDOWVWDFNFRP) написан на Python. Он создавался как способ реа-
лизовать удаленное выполнение программ, но позже вырос в полноценную плат-
форму управления системами. Основанный на ZeroMQ вместо SSH, он может
работать с тысячами серверов.
‰Альтернативными продуктами являются —’’‡– (KWWSSXSSHWODEVFRP) и Їˆ
(KWWSZZZJHWFKHIFRPFKHI), тесно связанные с Ruby.
‰Пакет •‹„އ (KWWSZZZDQVLEOHFRPKRPH), который, как и ƒŽ–, написан с по-
мощью Python, вполне сопоставим с ними. Вы можете скачать и применять его
бесплатно, но поддержка и отдельные пакеты с надстройками требуют коммерче-
ской лицензии. По умолчанию он использует SSH и не требует установки особого
программного обеспечения на тех компьютерах, которыми будет управлять.
Пакеты ƒŽ– и •‹„އ функционально являются супермножествами пакета
ƒ„”‹ , поскольку обрабатывают исходную конфигурацию, развертывание и уда-
ленное выполнение.

ǸȈȉȖȚȈȍȔșȉȖȓȤȠȐȔȐȖȉȢȍȔȈȔȐȌȈȕȕȣȝ
По мере роста Google и других интернет-компаний обнаружилось, что традиционные
вычислительные решения не масштабировались. Программное обеспечение, кото-
рое работало на отдельных или даже на нескольких машинах, не могло справиться
с тысячами.
Из-за объемов дискового пространства для баз данных и файлов поиск требовал
множества механических движений дисковой головки. (Подумайте о виниловой
пластинке и времени, необходимом для перемещения иголки с одной дорожки на
другую вручную. А также подумайте о скрипящем звуке, который она издаст, если
вы надавите слишком сильно, не говоря уже о звуках, которые издаст хозяин пла-
стинки.) Но передавать потоком последовательные фрагменты диска вы можете
быстрее.
Разработчики обнаружили, что гораздо быстрее было распространять и анали-
зировать данные на нескольких объединенных в сеть машинах, чем на отдельных.
Они могли использовать алгоритмы, которые звучали просто, однако на деле в целом
лучше работали с объемными распределенными данными. Один из таких алгоритмов
называется MapReduce, он может распределить вычисления между несколькими
компьютерами и затем собрать результат. Это похоже на работу с очередями.

+DGRRS
После того как компания Google опубликовала (KWWSVRUHLOO\FODG) полученные ре-
зультаты, компания Yahoo! вслед за ней создала пакет с открытым исходным кодом,
написанный на Java, который называется Hadoop (в честь игрушечного плюшевого
слона, принадлежавшего сыну главного разработчика).
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

Здесь вступают в действие слова «большие данные». Зачастую они просто озна-
чают следующее: «данных слишком много, чтобы они поместились на мою маши-
ну» — данные, объем которых превышает дисковое пространство, память, время
работы процессора или все перечисленное. Для некоторых организаций решением
вопроса больших данных является Hadoop. Этот пакет копирует данные среди ма-
шин, пропускает их через программы масштабирования и сжатия и сохраняет на
диск результаты после каждого шага.
Этот процесс может быть медленным. Более быстрый метод — отправка потоком
с помощью Hadoop, который работает как каналы Unix, посылая данные между про-
граммами и не требуя записи на диск после выполнения каждого шага. Вы можете
писать программы, использующие отправку потоком с помощью Hadoop, на любом
языке, включая Python.
Множество модулей Python были написаны для Hadoop, некоторые из них рассма-
триваются в статье блога A Guide to Python Frameworks for Hadoop (KWWSELWO\S\KDGRRS).
Компания Spotify, известная передачей потоковой музыки, открыла исходный код
своего компонента для отправки потоком с помощью Hadoop — написанного на
Python Luigi (KWWSVJLWKXEFRPVSRWLI\OXLJL).

6SDUN
Конкурент по имени Spark (KWWSELWO\DERXWVSDUN) был разработан для того, чтобы
превысить скорость работы Hadoop в 10–100 раз. Он может читать и обрабатывать
любой источник данных и формат Hadoop. Spark включает в себя API для Python
и других языков. Вы можете найти документацию по установке онлайн (KWWSELWO\
GOVSDUN).

'LVFR
Еще одна альтернатива Hadoop — Disco (KWWSGLVFRSURMHFWRUJ), который использует
Python для обработки MapReduce и язык программирования Erlang для коммуника-
ции. К сожалению, вы не можете установить его с помощью pip — см. документацию
(KWWSELWO\JHWGLVFR).

'DVN
Dask (KWWSVGDVNRUJ) похож на Spark, однако написан на Python и широко исполь-
зуется в научных пакетах, таких как NumPy, Pandas и scikit-learn. Он может рас-
пространять задачи в кластерах, содержащих тысячи машин.
Для получения Dask и всех вспомогательных модулей выполните следующую
команду:
ɛpip install dask[complete]

Обратитесь к главе 22, чтобы увидеть связанные с нашей темой примеры парал-
лельного программирования, в которых объемные структурированные вычисления
распространены между несколькими машинами.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǸȈȉȖȚȈȍȔȊȖȉȓȈȒȈȝ
Я действительно совсем не знаю облаков.

Джони Митчелл

Не так давно вам приходилось покупать собственные серверы, размещать их на


стойках в дата-центрах и устанавливать на них множество программ: операцион-
ные системы, драйверы устройств, файловые системы, базы данных, веб-серверы,
серверы электронной почты, балансировщики нагрузки, мониторы и т. д. Эффект
новизны пропал, когда вы начали пытаться поддерживать работоспособность
нескольких систем. Кроме того, вам приходилось постоянно волноваться о без-
опасности.
Многие хостинговые службы предлагали позаботиться о ваших серверах за не-
кую плату, но вам все равно приходилось брать в аренду физические устройства
и постоянно платить за пиковую нагрузку.
С увеличением количества компьютеров ошибки все более распространены.
Вам нужно масштабировать сервисы горизонтально и хранить избыточные данные.
Вы не можете предполагать, что сеть будет работать как одна машина. Согласно
Питеру Дойчу, восемь ошибок восприятия распределенных вычислений заключа-
ются в следующем.
‰Сеть надежна.
‰Латентность равна нулю.
‰Полоса пропускания бесконечна.
‰Сеть безопасна.
‰Топология не меняется.
‰Существует всего один администратор.
‰Стоимость транспортировки равна нулю.
‰Сеть гомогенна.
Вы можете попробовать создать сложную распределенную систему, но для этого
потребуется много работы и другой набор инструментов. Серверы можно сравнить
с домашними животными: вы даете им имена, знаете их характер и лечите по мере
необходимости. Но по мере роста их количества они становятся больше похожими
на скот: выглядят одинаково, имеют номера, и их просто заменяют, если возникает
какая-либо проблема.
Вместо того чтобы создавать систему, вы можете арендовать сервер в облаке.
В рамках этой модели обслуживание серверов — забота кого-то другого, а вы мо-
жете сконцентрироваться на своем сервисе, блоге или чем-то другом, что хотели бы
показать миру. Используя онлайн-панель инструментов и API, вы можете выбрать
серверы с любой необходимой вам конфигурацией быстро и легко — они эластич-
ны. Вы можете отслеживать их статус и получать предупреждения, если какой-то
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

показатель превысил лимит. Облака в данный момент довольно популярная тема,


и корпоративные расходы на облачные компоненты резко возросли.
Самые крупные поставщики облачных сервисов:
‰Amazon (AWS);
‰Google;
‰Microsoft Azure.

$PD]RQ:HE6HUYLFHV
По мере роста компании Amazon от сотен до тысяч и миллионов серверов раз-
работчики столкнулись со всеми проблемами распределенных систем. Однажды
в 2002 году (или около того) СЕО компании Джефф Безос объявил работникам
Amazon, что с этого момента все данные и функционал должны быть доступны
только через интерфейсы сетевых сервисов — не через файлы, базы данных или ло-
кальные вызовы функций. Программистам пришлось разрабатывать эти интерфейсы
так, как если бы их код стал общедоступным. Письмо заканчивалось мотивирующей
фразой: «Тот, кто этого не сделает, будет уволен».
Неудивительно, что разработчики взялись за дело и с течением времени создали
очень крупную архитектуру, ориентированную на сервисы. Они позаимствовали или
придумали сами множество решений, включая Amazon Web Services (AWS) (KWWS
DZVDPD]RQFRP), которое сейчас доминирует на рынке. Официальной библиотекой
Python для работы с AWS является „‘–‘ɪ:
‰документация (KWWSVRUHLOO\\%D]);
‰страницы SDK (KWWSVDZVDPD]RQFRPVGNIRUS\WKRQ).
Установите ее следующим образом:
ɛpip install boto3

Вы можете использовать „‘–‘ɪ как альтернативу веб-страницам для управления


AWS.

*RRJOH
Google часто использует Python для внутренних нужд и нанимает именитых разра-
ботчиков Python (у них какое-то время работал сам Гвидо ван Россум). На главной
странице Google (KWWSVFORXGJRRJOHFRP) и странице, посвященной Python (KWWSV
FORXGJRRJOHFRPS\WKRQ), вы можете найти подробную информацию о его сервисах.

0LFURVRIW$]XUH
Microsoft наряду с Amazon и Google предлагает облачный сервис под названием
Azure (KWWSVD]XUHPLFURVRIWFRP). В статье Python on Azure (KWWSVRUHLOO\<R1]) можно
узнать, как разрабатывать и размещать приложения Python в этом сервисе.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

2SHQ6WDFN
OpenStack (KWWSVZZZRSHQVWDFNRUJ) — это бесплатное решение с открытым ис-
ходным кодом, содержащее сервисы Python и Rest API. Многие из них аналогичны
сервисам, предлагаемым коммерческими облаками.

'RFNHU
Простой стандартизированный контейнер отправки ПО произвел революцию
в международной торговле. Всего несколько лет назад Docker применил название
«контейнер» и аналогию к методу виртуализации с помощью малоизвестных осо-
бенностей Linux. Контейнеры гораздо легче, чем виртуальные машины, и немного
тяжелее, чем virtualenvs в Python. Они позволяют упаковать приложение отдель-
но от других программ на одной и той же машине, общим для них будет только
ядро ОС.
Чтобы установить клиентскую библиотеку Docker (KWWSVS\SLRUJSURMHFWGRFNHU),
выполните следующую команду:
ɛpip install docker

.XEHUQHWHV
Технология контейнеризации распространилась по всему вычислительному миру.
В конечном счете возникла потребность в способе управления большим количе-
ством контейнеров и автоматизации операций, выполняемых вручную в крупных
распределенных системах:
‰обход отказов;
‰балансировка нагрузки;
‰масштабирование.
Похоже, что лидером на рынке управления контейнерами становится Kubernetes
(KWWSVNXEHUQHWHVLR).
Чтобы установить его клиентскую библиотеку (KWWSVJLWKXEFRPNXEHUQHWHVFOLHQW
S\WKRQ), выполните следующую команду:
ɛpip install kubernetes

ǿȐȚȈȑȚȍȌȈȓȍȍ
Как говорят на телевидении, наш следующий гость не нуждается в представле-
нии. Узнаем, почему Python является одним из лучших языков для работы в Ин-
тернете.
ǫȓȈȊȈǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ  

ǻȗȘȈȎȕȍȕȐȧ
17.1. Используйте объект класса •‘ ‡–, чтобы реализовать сервис, сообщающий
текущее время. Когда клиент отправляет на сервер строку ɐ–‹‡ɐ, верните
текущие дату и время как строку ISO.
17.2. Задействуйте сокеты ZeroMQ REQ и REP, чтобы сделать то же самое.
17.3. Попробуйте сделать то же самое с помощью XMLRPC.
17.4. Возможно, вы видели эпизод телесериала I Love Lucy, в котором Люси и Этель
работают на шоколадной фабрике. Парочка стала отставать, когда линия кон-
вейера, направлявшая к ним на обработку конфеты, еще более ускорилась.
Напишите симуляцию, которая отправляет разные типы конфет в список
Redis, и клиент Lucy, делающий блокирующие выталкивания из списка.
Ей нужно 0,5 секунды, чтобы обработать одну конфету. Выведите на экран
время и тип каждой конфеты, которую получит Lucy, а также количество не-
обработанных конфет.
17.5. Используйте ZeroMQ, чтобы публиковать стихотворение из упражнения 12.4
(пример 12.1) по одному слову за раз. Напишите потребитель ZeroMQ, кото-
рый будет выводить на экран каждое слово, начинающееся с гласной. Напи-
шите другой потребитель, который станет выводить все слова, состоящие из
пяти букв. Знаки препинания игнорируйте.
ƋƓƈƊƈ
ǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț

О, какой сложный узор мы ткем…

Вальтер Скотт. Мармион

На французско-швейцарской границе располагается CERN — Институт исследова-


ния физики частиц, где частенько сталкивают атомы друг с другом.
При этом процессе генерируется множество данных. В 1989 году английский
ученый Тим Бернерс-Ли впервые внес предложение помочь распространять инфор-
мацию внутри CERN, а также среди всего исследовательского сообщества. Он назвал
его World Wide Web (Всемирная паутина) и довольно быстро выделил три основные
идеи, которые должны были лечь в основу ее дизайна:
‰HTTP (Hypertext Transfer Protocol — протокол передачи гипертекста) — про-
токол для веб-клиентов и серверов для обмена запросами и ответами;
‰HTML (Hypertext Markup Language — гипертекстовый язык разметки) — формат
для представления результатов;
‰URL (Uniform Resource Locator — единообразный локатор ресурса) — способ
уникально обозначить сервер и ресурс на этом сервере.
В самом простом варианте использования веб-клиент (я думаю, что Бернерс-Ли
был первым, кто употребил слово «браузер») соединяется с веб-сервером с помощью
протокола HTTP, запрашивает URL и получает HTML.
Все это было создано на базе сети Интернет, который в то время был неком-
мерческим, им пользовались лишь несколько университетов и исследовательских
организаций.
Бернерс-Ли написал первый браузер и сервер на компьютере NeXT1. Извест-
ность Всемирной паутины значительно возросла в 1993-м, когда группа студентов
Иллинойсского университета выпустила браузер Mosaic (для Windows, Macintosh
и Unix) и сервер NCSA httpd. Загрузив тем летом Mosaic и начав создавать сайты,
я даже не догадывался, что Всемирная паутина и Интернет станут частью повсед-

1
Компания, основанная Стивом Джобсом после его ухода из Apple.
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

невной жизни. В то время Интернет1 все еще был некоммерческим официально,


в мире существовало всего 500 известных веб-серверов (KWWSKRPHZHEFHUQFK
DERXWELUWKZHE). К концу 1994 года их количество увеличилось до 10 000. Интернет
был открыт для коммерческого использования, и авторы браузера Mosaic основа-
ли компанию Netscape, чтобы писать коммерческие веб-приложения. Компания
Netscape стала достоянием общественности как часть возникшего в то время
раннего интернет-безумия, и взрывной рост Всемирной паутины не остановился
до сих пор.
Практически каждый язык программирования был использован для написания
веб-клиентов и веб-серверов. Динамические языки Perl, PHP и Ruby стали особенно
популярными. В этой главе я покажу вам, почему Python особенно хорош для работы
в Интернете на любом из таких уровней, как:
‰клиенты для удаленного доступа;
‰серверы, предоставляющие данные для сайтов и веб-API;
‰веб-API и сервисы, позволяющие обмениваться данными другими способами,
отличающимися от просматриваемых веб-страниц.
Выполняя упражнения в конце главы, мы создадим настоящий интерактивный
сайт.

ǪȍȉȒȓȐȍȕȚȣ
Низкоуровневая система проводящих путей Интернета называется Transmission
Control Protocol/Internet Protocol (протокол управления передачей/интернет-
протокол) или просто TCP/IP (в одноименном разделе главы 17 на с. 368 данный
протокол рассматривается более подробно). Он перемещает байты между компьюте-
рами, но не обращает внимания на то, что они значат. Это работа высокоуровневых
протоколов — определений синтаксиса для некоторых целей. HTTP — стандартный
протокол для обмена данными в Сети.
Всемирная паутина — это клиент-серверная система. Клиент делает запрос сер-
веру: он открывает соединение TCP/IP, отправляет URL и другую информацию
с помощью HTTP и получает ответ.
Формат ответа также определяется протоколом HTTP. Он включает в себя статус
запроса и (в том случае, если запрос выполнен успешно) данные и формат ответа.
Самый известный веб-клиент — это браузер. Он может создавать HTTP-запросы
несколькими способами. Вы можете инициировать запрос вручную, написав URL
в адресной строке или нажав ссылку на веб-странице. Очень часто для отображения
сайта используются возвращаемые данные: HTML-документы, файлы JavaScript,

1
Развеем старый миф. Сенатор (а впоследствии вице-президент) Эл Гор выступал в под-
держку двухпартийного законодательства и сотрудничества, включая финансирование
группы, создавшей Mosaic, что позволило значительно развить Интернет на раннем этапе.
Он никогда не утверждал, что «изобрел Интернет»; эту фразу ему приписали его полити-
ческие конкуренты, когда он баллотировался в президенты в 2000-м.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

файлы CSS и изображения, но данные могут быть любого типа, в том числе и не
предназначенные для отображения.
Важный аспект HTTP — этот протокол не имеет состояния. Каждое создаваемое
вами соединение HTTP не зависит от других. Это упрощает базовые операции, но
усложняет другие. Рассмотрим несколько примеров таких усложнений.
‰Кэширование. Удаленный контент, который не меняется, должен быть сохранен
веб-клиентом и использован для того, чтобы не загружать его с сервера снова.
‰Сессии. Интернет-магазин должен запоминать содержимое вашей корзины.
‰Аутентификация. Сайты, которые требуют ваши имя пользователя и пароль,
должны запоминать их, пока вы авторизованы.
Решения для описанных усложнений включают в себя cookie, в которых сервер
отправляет клиенту довольно специфическую информацию, позволяющую их рас-
познать, когда клиент отправляет эти файлы назад.

ǺȍșȚȐȘțȍȔșȗȖȔȖȡȤȦWHOQHW
HTTP — протокол, основанный на тексте, поэтому вы можете вручную вводить его
код во время тестирования. Древняя программа telnet позволяет подключиться
к любому серверу и порту и вводить команды для любого сервиса, запущенного
на нем. Создавать безопасные (зашифрованные) соединения с другими машинами
следует с помощью ssh.
Запросим у любимого многими тестового сайта Google базовую информацию
о его главной странице. Введем следующее:
ɛtelnet [Link] 80

Если на порте 80 (на нем работает незашифрованный http; зашифрованный про-


токол https использует порт 443) по адресу ‰‘‘‰Ž‡Ŝ ‘ существует веб-сервер (я ду-
маю, это беспроигрышный вариант), то telnet выведет на экран подтверждающую
информацию, а затем отобразит пустую строку, которая является приглашением
ввести что-то еще:
”›‹‰ɮɫŜɨɩɬŜɩɩɬŜɨɮɮŜŜŜ
‘‡ –‡†–‘™™™Ŝ‰‘‘‰Ž‡Ŝ ‘Ŝ
• ƒ’‡ Šƒ”ƒ –‡”‹•ɐɋƄɐŜ

Теперь введем настоящую команду HTTP для telnet, которую он отправит на


веб-сервер Google. Самая распространенная команда HTTP (ее использует ваш
браузер каждый раз, когда вы вводите URL в адресной строке) — это . Она по-
зволяет получить содержимое заданного ресурса, такого как HTML-файл, и возвра-
щает его клиенту. Для первой проверки мы используем команду HTTP , просто
получающую некую базовую информацию о ресурсе:
HEAD / HTTP/1.1

Добавьте дополнительный символ возврата каретки, чтобы удаленный сер-


вер понял: вы закончили вводить команду и хотите получить ответ. Конструкция
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

 ŵ отправляет запрос HTTP  глагол (команда) с целью получить информа-
цию о главной странице (ŵ). Вы получите ответ наподобие следующего (я обрезал
некоторые длинные строки с помощью многоточий, чтобы они не вываливались за
пределы страницы):
ŵɨŜɨɩɥɥ
ƒ–‡ś‘řɨɥ —ɩɥɨɰɨɭśɨɩśɨɪ 
š’‹”‡•śŞɨ
ƒ ЇŞ‘–”‘Žś’”‹˜ƒ–‡řƒšŞƒ‰‡ʰɥ
‘–‡–Ş›’‡ś–‡š–ŵŠ–ŽŚ Šƒ”•‡–ʰ ŞɯɯɬɰŞɨ
ɪśʰɑŠ‹•‹•‘–ƒɪ’‘Ž‹ ›Š‡‡‰Ŝ ‘ŵ’ɪ’Їޒˆ‘”‘”‡‹ˆ‘Ŝɑ
‡”˜‡”ś‰™•
ŞŞ”‘–‡ –‹‘śɥ
Ş ”ƒ‡Ş’–‹‘•ś 
‡–Ş‘‘‹‡śɨɏ ʰŜŜŜڇ𒋔‡•ʰŜŜŜ Ś’ƒ–Šʰŵچ‘ƒ‹ʰŜ‰‘‘‰Ž‡Ŝ ‘
‡–Ş‘‘‹‡ś ʰŜŜŜڇ𒋔‡•ʰŜŜŜ Ś’ƒ–Šʰŵچ‘ƒ‹ʰŜ‰‘‘‰Ž‡Ŝ ‘Ś ––’Ž›
”ƒ•ˆ‡”ސ ‘†‹‰ś Š—‡†
 ‡’–ރ‰‡•ś‘‡
ƒ”›ś ‡’–ސ ‘†‹‰

Так выглядят заголовки ответов HTTP и их значения. Некоторые из них, такие


как ƒ–‡ или ‘–‡–Ş›’‡, обязательны. Другие, например ‡–Ş‘‘‹‡, использу-
ются для отслеживания вашей активности в течение нескольких посещений (мы
поговорим об управлении состоянием чуть позже). Делая запрос HTTP , вы
получаете в ответ только заголовки. Если вы задействовали команды HTTP 
или HTTP , то также получите данные от главной страницы (смесь HTML,
CSS, JavaScript и всего прочего, что Google решит разместить на своей главной
странице).
Я не хочу, чтобы вы зависли в telnet. Закрыть его можно, введя следующее:
q

ǺȍșȚȐȘțȍȔșȗȖȔȖȡȤȦFXUO
Использовать telnet довольно просто, но это делается исключительно вручную.
Программа —”Ž (KWWSVFXUOKD[[VH), возможно, самый популярный веб-клиент, ра-
ботающий в командной строке. Его документация включает в себя книгу Everything
Curl (KWWSVFXUOKD[[VHERRNKWPO), доступную в форматах HTML, PDF и ebook. В этой
таблице (KWWSVRUHLOO\G/5E) сравниваются —”Ž и похожие инструменты. На стра-
нице скачивания (KWWSVFXUOKD[[VHGRZQORDGKWPO) перечислены все основные, а также
многие узкоспециализированные платформы.
Простейший вариант использования —”Ž — неявный запрос  (здесь его вывод
будет обрезан):
ɛcurl [Link]
ʳІ‘ –›’‡Š–Žʴ
ʳŠ–Žʴ
ʳЇƒ†ʴ
ʳ–‹–އʴšƒ’Ž‡‘ƒ‹ʳŵ–‹–އʴ
ŜŜŜ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Здесь используется :


ɛcurl --head [Link]
ŵɨŜɨɩɥɥ
‘–‡–ސ ‘†‹‰ś‰œ‹’
 ‡’–ރ‰‡•ś„›–‡•
ƒ ЇŞ‘–”‘ŽśƒšŞƒ‰‡ʰɭɥɫɯɥɥ
‘–‡–Ş›’‡ś–‡š–ŵŠ–ŽŚ Šƒ”•‡–ʰ Şɯ
ƒ–‡ś—řɥɬƒ›ɩɥɨɰɨɭśɨɫśɪɥ 
–ƒ‰śɑɨɬɫɨɥɩɬɭɭɪɑ
š’‹”‡•ś—řɨɩƒ›ɩɥɨɰɨɭśɨɫśɪɥ 
ƒ•–Ş‘†‹ˆ‹‡†ś ”‹řɥɰ—‰ɩɥɨɪɩɪśɬɫśɪɬ 
‡”˜‡”śſƒ‰„ŵɬɩɨƀ
ރ Їś 
‘–‡–އ‰–Šśɭɥɭ

Если вы передаете аргументы, то можете включить их в командную строку или


в файл данных. В этих примерах я использую следующее:
‰URL любого сайта;
‰файл †ƒ–ƒŜ–š– — текстовый файл данных со следующим содержимым: ƒʰɨĺ„ʰɩ;
‰файл †ƒ–ƒŜŒ•‘ — файл данных JSON с таким содержимым: Ƈɑƒɑś ɨř ɑ„ɑś ɩƈ;
‰ƒʰɨĺ„ʰɩ в качестве двух аргументов.
Использование аргументов по умолчанию (закодированных в форме):
ɛcurl -X POST -d "a=1&b=2" url
ɛcurl -X POST -d "@[Link]" url

Для аргументов, закодированных в JSON:


ɛcurl -X POST -d "{'a':1,'b':2}" -H "Content-Type: application/json" url
ɛcurl -X POST -d "@[Link]" url

ǺȍșȚȐȘțȍȔșȐșȗȖȓȤȏȖȊȈȕȐȍȔKWWSLH
Альтернативой —”Ž в духе Python является httpie (KWWSVKWWSLHRUJ).
ɛpip install httpie

Чтобы выполнить запрос , сделаем шаги, аналогичные шагам для —”Ž, по-
казанным выше (ވ — это синоним для ŞŞˆ‘”):
ɛhttp -f POST url a=1 b=2
ɛhttp POST -f url < [Link]

Кодировкой по умолчанию является JSON:


ɛhttp POST url a=1 b=2
ɛhttp POST url < [Link]

Программа httpie также обрабатывает заголовки HTTP, cookies, загрузки фай-


лов, аутентификацию, перенаправление, переадресацию, SSL и т. д. Как обычно, вы
можете обратиться к документации (KWWSVKWWSLHRUJGRF).
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

ǺȍșȚȐȘțȍȔșȗȖȔȖȡȤȦKWWSELQ
Вы можете тестировать свои веб-запросы для сайта httpbin (KWWSVKWWSELQRUJ)
или же загрузить и запустить сайт в локальном образе Docker:
ɛdocker run -p 80:80 kennethreitz/httpbin

ǹȚȈȕȌȈȘȚȕȣȍȊȍȉȉȐȉȓȐȖȚȍȒȐ3\WKRQ
В Python 2 модули веб-клиентов и веб-серверов были слегка разбросаны. Одна из
целей Python 3 заключается в том, чтобы разместить эти модули в двух пакетах (как
вы помните из главы 11, пакет — всего лишь каталог для хранения файлов модулей):
‰http управляет всеми деталями клиент-серверного взаимодействия HTTP:
y Ž‹‡– выполняет всю работу на стороне клиента;
y server помогает написать веб-сервер Python;
y ‘‘‹‡• и ‘‘‹‡Œƒ” управляют cookies, которые сохраняют данные между
посещениями;
‰urllib работает на базе http:
y request обрабатывает клиентские запросы;
y response обрабатывает ответы сервера;
y parse разбивает URL на части.

ǭșȓȐ Ȋȣ ȝȖȚȐȚȍ ȕȈȗȐșȈȚȤ ȒȖȌ ȒȖȚȖȘȣȑ șȖȊȔȍșȚȐȔ ș3\WKRQ  Ȑ 3\WKRQ  ȚȖ ȊȈȔ
șȓȍȌțȍȚȗȖȔȕȐȚȤȖȚȖȔȟȚȖȉȐȉȓȐȖȚȍȒȈXUOOLEȏȕȈȟȐȚȍȓȤȕȖ KWWSVRUHLOO\ZZB5 
ȐȏȔȍȕȐȓȈșȤȗȘȐȗȍȘȍȝȖȌȍȕȈ3\WKRQǿțȚȤȕȐȎȍȊȗȖȌȘȈȏȌȍȓȍ©ǯȈȗȘȍȌȍȓȈȔȐșȚȈȕ
ȌȈȘȚȕȖȑȉȐȉȓȐȖȚȍȒȐUHTXHVWVªȕȈșȗȘȍȌșȚȈȊȓȍȕȈȉȖȓȍȍțȌȖȉȕȈȧȈȓȤȚȍȘȕȈȚȐȊȈ

Воспользуемся стандартной библиотекой с целью получить что-либо с сайта.


URL в следующем примере возвращает информацию с тестового сайта:
ʴʴʴ‹’‘”–—”ŽŽ‹„Ŝ”‡“—‡•–ƒ•—”
ʴʴʴ
ʴʴʴ—”ŽʰɐŠ––’śŵŵ™™™Ŝ‡šƒ’އŜ ‘ŵɐ
ʴʴʴ ‘ʰ—”Ŝ—”Ž‘’‡ſ—”Žƀ

Этот небольшой фрагмент кода открыл соединение TCP/IP с удаленным веб-


сервером ™™™Ŝ‡šƒ’އŜ ‘ , создал запрос HTTP и получил HTTP-ответ. Ответ
содержит не только данные о странице (цитату). Из официальной документации
(KWWSELWO\KWWSUHVSRQVHGRFV) мы можем узнать, что ‘ является объектом класса
‡•’‘•‡, содержащим несколько методов и атрибутов. Одна из наиболее важ-
ных частей ответа — код статуса HTTP:
ʴʴʴ’”‹–ſ ‘Ŝ•–ƒ–—•ƀ
ɩɥɥ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Значение ɩɥɥ означает, что все прошло гладко. Существуют десятки кодов ста-
туса HTTP, объединенных в пять диапазонов в соответствии с их первой цифрой
(сотни):
‰1xx (информация) — сервер получил запрос, но имеет некую дополнительную
информацию для клиента;
‰2xx (успех) — сработало, каждый код успеха, кроме 200, сообщает дополнитель-
ные детали;
‰3xx (перенаправление) — ресурс был перемещен, поэтому ответ возвращает кли-
енту новый URL;
‰4xx (ошибка клиента) — некие проблемы на стороне клиента, например знамени-
тая ошибка 404 (ресурс не найден). Код 418 (I’m a teapot) был первоапрельской
шуткой;
‰5xx (ошибка сервера) — код 500 — общая ошибка. Вы можете встретить ошиб-
ку 502 (ошибочный шлюз), если произошел разрыв связи между веб-сервером
и машинным интерфейсом.
Чтобы получить содержимое веб-страницы, используйте метод ”‡ƒ†ſƀ перемен-
ной ‘. Вы получите значение типа bytes. Получим данные и выведем на экран
первые 50 байт:
ʴʴʴ†ƒ–ƒʰ ‘Ŝ”‡ƒ†ſƀ
ʴʴʴ’”‹–ſ†ƒ–ƒƃśɬɥƄƀ

„ɐʳІ‘ –›’‡Š–ŽʴɎʳŠ–ŽʴɎʳЇƒ†ʴɎʳ–‹–އʴšƒ’Ž‡ɐ

Мы можем преобразовать эти байты в строку и вывести 50 первых символов:


ʴʴʴ•–”ɏ†ƒ–ƒʰ†ƒ–ƒŜ†‡ ‘†‡ſɐ—–ˆɯɐƀ
ʴʴʴ’”‹–ſ•–”ɏ†ƒ–ƒƃśɬɥƄƀ
ʳІ‘ –›’‡Š–Žʴ
ʳŠ–Žʴ
ʳЇƒ†ʴ
ʳ–‹–އʴšƒ’Ž‡
ʴʴʴ

Остальная часть решения включает в себя дополнительный код HTML и CSS.


Из любопытства взглянем, какие еще заголовки HTTP были отправлены нам:
ʴʴʴˆ‘”‡›ř˜ƒŽ—‡‹ ‘Ŝ‰‡–Їƒ†‡”•ſƀś
ŜŜŜ’”‹–ſ‡›ř˜ƒŽ—‡ƀ
ŜŜŜ

ƒ ЇŞ‘–”‘ŽƒšŞƒ‰‡ʰɭɥɫɯɥɥ
‘–‡–Ş›’‡–‡š–ŵŠ–ŽŚ Šƒ”•‡–ʰ Şɯ
ƒ–‡—řɥɬƒ›ɩɥɨɰɥɪśɥɰśɩɭ 
–ƒ‰ɑɨɬɫɨɥɩɬɭɭɪʫ‹†‡–ɑ
š’‹”‡•—řɨɩƒ›ɩɥɨɰɥɪśɥɰśɩɭ 
ƒ•–Ş‘†‹ˆ‹‡† ”‹řɥɰ—‰ɩɥɨɪɩɪśɬɫśɪɬ 
‡”˜‡”ſƒ‰„ŵɬɩɰɭƀ
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

ƒ”› ‡’–ސ ‘†‹‰


ރ Ї 
‘–‡–އ‰–Šɨɩɮɥ
‘‡ –‹‘ Ž‘•‡

Помните пример работы с telnet, который я показывал ранее? Теперь наша би-
блиотека Python может разбирать заголовки этих HTTP-запросов и размещать их
в словарь. ƒ–‡ и ‡”˜‡” кажутся довольно очевидными, некоторые другие — нет.
Полезно знать, что HTTP имеет набор стандартных заголовков, таких как ‘–‡–Ş
›’‡, и множество опциональных.

ǯȈȗȘȍȌȍȓȈȔȐșȚȈȕȌȈȘȚȕȖȑȉȐȉȓȐȖȚȍȒȐUHTXHVWV
В начале главы 1 вы увидели программу, которая получает доступ к Wayback
Machine API с помощью стандартных библиотек —”ŽŽ‹„Ŝ”‡“—‡•– и Œ•‘. За ним
следовал другой пример, использовавший стороннюю библиотеку requests. Он был
короче и проще для понимания.
Я считаю, что для большинства задач, связанных с разработкой веб-клиентов,
проще использовать библиотеку requests. Вы можете просмотреть ее документацию
по адресу KWWSVRUHLOO\])F\ (она довольно хорошо написана), чтобы получить более
подробную информацию. Я покажу основные принципы работы с этой библиотекой
в данном подразделе и буду задействовать ее на протяжении всей книги для решения
задач, связанных с веб-клиентами.
Для начала нужно установить библиотеку requests:
ɛpip install requests

Переделаем предыдущий вызов сервиса с ‡šƒ’އŜ ‘ с помощью библиотеки


requests:
ʴʴʴ‹’‘”–”‡“—‡•–•
ʴʴʴ”‡•’ʰ”‡“—‡•–•Ŝ‰‡–ſɐŠ––’śŵŵ‡šƒ’އŜ ‘ɐƀ
ʴʴʴ”‡•’
ʳ‡•’‘•‡ƃɩɥɥƄʴ
ʴʴʴ”‡•’Ŝ•–ƒ–—•ɏ ‘†‡
ɩɥɥ
ʴʴʴ”‡•’Ŝ–‡š–ƃśɬɥƄ
ɐʳІ‘ –›’‡Š–ŽʴɎʳŠ–ŽʴɎʳЇƒ†ʴɎʳ–‹–އʴšƒ’Ž‡ɐ

Для демонстрации запроса JSON создадим сокращенную версию программы,


которую вы увидите в конце данной главы. Вы предоставляете строку, и програм-
ма воспользуется поисковым API Internet Archive, чтобы пройтись по названиям
миллиардов мультимедиа, сохраненным в этом архиве. Обратите внимание: в вызов
”‡“—‡•–•Ŝ‰‡–ſƀ, показанный в примере 18.1, вам нужно передать только словарь ’ƒ”ƒ•
и библиотека requests обработает управляющие символы и создаст запрос.

ǷȘȐȔȍȘLDS\
‹’‘”–Œ•‘
‹’‘”–•›•
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‹’‘”–”‡“—‡•–•

†‡ˆ•‡ƒ” Šſ–‹–އƀś
—”ŽʰɑŠ––’śŵŵƒ” Š‹˜‡Ŝ‘”‰ŵƒ†˜ƒ ‡†•‡ƒ” ŠŜ’Š’ɑ
’ƒ”ƒ•ʰƇɑ“ɑśˆɑ–‹–އśſƇ–‹–އƈƀɑř
ɑ‘—–’—–ɑśɑŒ•‘ɑř
ɑˆ‹‡Ž†•ɑśɑ‹†‡–‹ˆ‹‡”ř–‹–އɑř
ɑ”‘™•ɑśɬɥř
ɑ’ƒ‰‡ɑśɨřƈ
”‡•’ʰ”‡“—‡•–•Ŝ‰‡–ſ—”Žř’ƒ”ƒ•ʰ’ƒ”ƒ•ƀ
”‡–—””‡•’ŜŒ•‘ſƀ

‹ˆɏɏƒ‡ɏɏʰʰɑɏɏƒ‹ɏɏɑś
–‹–އʰ•›•Ŝƒ”‰˜ƃɨƄ
†ƒ–ƒʰ•‡ƒ” Šſ–‹–އƀ
†‘ •ʰ†ƒ–ƒƃɑ”‡•’‘•‡ɑƄƃɑ†‘ •ɑƄ
’”‹–ſˆɑ ‘—†Ƈއſ†‘ •ƀƈ‹–‡•ř•Š‘™‹‰ˆ‹”•–ɨɥɑƀ
’”‹–ſɑ‹†‡–‹ˆ‹‡”Ɏ––‹–އɑƀ
ˆ‘””‘™‹†‘ •ƃśɨɥƄś
’”‹–ſ”‘™ƃɑ‹†‡–‹ˆ‹‡”ɑƄř”‘™ƃɑ–‹–އɑƄř•‡’ʰɑɎ–ɑƀ

Сколько у них элементов, связанных с вендиго?


ɛpython [Link] wendigo
‘—†ɩɫ‹–‡•ř•Š‘™‹‰ˆ‹”•–ɨɥ
‹†‡–‹ˆ‹‡”–‹–އ
†ɏ™‡†‹‰‘ɏ’‡›Ş•’ƒ””‘™‡†‹‰‘
‡†‹‰‘ɨ‡†‹‰‘ɨ
™‡†‹‰‘ɏƒ‰ɏŽ‹„”‹˜‘šЇ‡†‹‰‘
–Ї™‡†‹‰‘ɨɥɯɰɮ‰—–Ї‡†‹‰‘
‹•„ɏɰɮɯɥɯɫɪɰɫɫɮɰɩ‡†‹‰‘‘—–ƒ‹Ś‡ƒ–Š ƒ’
Œƒ‡†‘Şɥɭɥɬɥɯ‡†‹‰‘Ş—†‹‘‡ƒ•Š
ˆƒ˜ŞŽƒ†›ɏ™‡†‹‰‘Žƒ†›ɏ™‡†‹‰‘ ƒ˜‘”‹–‡•
ɥɨɨ„ ‡ƒ”Ї‡†‹‰‘ɥɨɨ„ ‡ƒ”Ї‡†‹‰‘
Šƒ”‡†Šƒ–•ɨɨɩ’‹•‘†‡ɨɨɩŞЇ‡†‹‰‘
Œƒ‡†‘Şɥɮɭɰɭɫ‡†‹‰‘Ş‘ƒ‡‘‡Œƒ‡ʴ

Первую колонку (идентификатор) можно использовать для того, чтобы про-


смотреть элемент на сайте DUFKLYHRUJ. Вы узнаете, как это делается, в конце главы.

ǪȍȉșȍȘȊȍȘȣ
Веб-разработчики обнаружили, что Python хорошо подходит для написания веб-
серверов и программ, работающих на серверной стороне. Это привело к появлению
такого множества фреймворков, написанных на данном языке, что теперь уже стано-
вится трудно исследовать их все и сделать выбор, не говоря уже о принятии решения
о том, какие из них обсудить в книге.
Веб-фреймворк предоставляет функции, позволяющие построить сайты, поэтому
может решать большее количество задач, чем простой веб-сервер (HTTP). Вы встре-
титесь с функциями маршрутизации (URL к функции сервера), шаблонами (HTML
с динамическими включениями), отладкой и др.
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

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

ǷȘȖșȚȍȑȠȐȑȊȍȉșȍȘȊȍȘ3\WKRQ
Вы можете запустить простейший веб-сервер, просто введя одну строку кода Python:
ɛpython -m [Link]

С помощью этой строки вы реализуете примитивный Python HTTP-сервер.


Если не возникло никаких проблем, то вы увидите исходное сообщение о статусе:
‡”˜‹‰ ‘ɥŜɥŜɥŜɥ’‘”–ɯɥɥɥŜŜŜ

Запись ɥŜɥŜɥŜɥ означает любой адрес TCP, поэтому веб-клиенты могут получать
к нему доступ независимо от того, какой адрес имеет сервер. В главе 11 вы можете
прочитать о некоторых низкоуровневых деталях TCP и других системах соединения
в сеть.
Теперь вы можете запрашивать файлы, чьи пути относительны к вашему текуще-
му каталогу, и они будут вам возвращены. Если вы введете в своем браузере строку
Š––’śŵŵŽ‘ ƒŽŠ‘•–śɯɥɥɥ, то должны увидеть список каталогов и сервер выведет на
экран строки обращения к журналам, например такие:
ɨɩɮŜɥŜɥŜɨŞŞƃɩɥŵ ‡„ŵɩɥɨɪɩɩśɥɩśɪɮƄɑ ŵ ŵɨŜɨɑɩɥɥŞ

Элементы Ž‘ ƒŽŠ‘•– и ɨɩɮŜɥŜɥŜɨ являются для TCP синонимами вашего локаль-


ного компьютера, поэтому сработают независимо от того, подключены ли вы к Ин-
тернету. Вы можете интерпретировать эти строки следующим образом:
‰ɨɩɮŜɥŜɥŜɨ — IP-адрес клиента;
‰первый символ Ş — имя удаленного пользователя, если он присутствует;
‰второй символ Ş — имя авторизующегося пользователя, если требуется;
‰ƃɩɥŵ ‡„ŵɩɥɨɪ ɩɩśɥɩśɪɮƄ — дата и время доступа;
‰ɑ ŵ ŵɨŜɨɑ — команда, отправленная веб-серверу:
y метод HTTP ( );
y запрошенный ресурс (ŵ, верхний уровень);
y версия HTTP ( ŵɨŜɨ);
‰последнее число (ɩɥɥ) — код статуса HTTP, возвращенный веб-сервером.
Щелкните на любом файле. Если ваш браузер может распознать его формат
(HTML, PNG, GIF, JPEG и т. д.), то должен отобразить его, и сервер занесет этот за-
прос в журнал. Например, если в вашем текущем каталоге имеется файл ‘”‡‹ŽŽ›Ŝ’‰,
запрос Š––’śŵŵŽ‘ ƒŽŠ‘•–śɯɥɥɥŵ‘”‡‹ŽŽ›Ŝ’‰ должен вернуть изображение встрево-
женной зверушки, показанное на рис. 20.2, а в журнале должна появиться похожая
запись:
ɨɩɮŜɥŜɥŜɨŞŞƃɩɥŵ ‡„ŵɩɥɨɪɩɩśɥɪśɫɯƄɑ ŵ‘”‡‹ŽŽ›Ŝ’‰ ŵɨŜɨɑɩɥɥŞ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

При наличии в этом каталоге других файлов их названия должны появиться


в списке. Можете щелкнуть на одном из файлов, чтобы загрузить его. Если ваш брау-
зер сконфигурирован так, чтобы отображать формат данного файла, то вы увидите
результат на экране. В противном случае браузер спросит, хотите ли вы загрузить
и сохранить файл.
По умолчанию используется порт 8000, но вы можете указать любой другой:
ɛpython -m [Link] 9999

Вы должны увидеть следующее:


‡”˜‹‰ ‘ɥŜɥŜɥŜɥ’‘”–ɰɰɰɰŜŜŜ

Этот сервер, написанный только на Python, лучше всего подходит для быстрых
тестов. Вы можете выключить его, убив его процесс нажатием &WUO+&.
Вы не должны использовать этот простой сервер для загруженного производ-
ственного сайта. Традиционные веб-серверы, такие как Apache и NGINX, гораздо бы-
стрее работают со статическими файлами. Кроме того, этот простой сервер не может
взаимодействовать с динамическим содержимым, в отличие от более продвинутых
серверов, принимающих дополнительные параметры.

:HE6HUYHU*DWHZD\,QWHUIDFH :6*,
Довольно быстро необходимость в простых файлах исчезает, и нам уже нужен сер-
вер, который может запускать программы динамически. В первые годы существова-
ния Всемирной паутины общий интерфейс шлюза (Common Gateway Interface, CGI)
был разработан для того, чтобы веб-серверы могли запускать внешние программы
и возвращать результаты. CGI также обрабатывал получение входных аргументов
от клиента, передавая их через сервер сторонним программам. Однако программы
запускались заново при каждом обращении клиента. Масштабировать такие систе-
мы было трудно, поскольку даже у небольших программ время загрузки довольно
велико.
Чтобы избежать задержки запуска, люди начали встраивать интерпретатор
языка в веб-сервер. Apache запускал код на PHP внутри своего модуля ‘†ɏ’Š’,
Perl — внутри модуля ‘†ɏ’‡”Ž и Python — внутри модуля ‘†ɏ’›–Š‘. Далее код
этих динамических языков мог быть выполнен внутри долгоиграющего процесса
Apache, а не во внешних программах.
Альтернативный метод заключается в том, чтобы запускать динамический язык
внутри отдельной долгоиграющей программы и заставить ее обмениваться данными
с веб-сервером. Примерами таких программ являются FastCGI и SCGI.
Веб-разработка на Python совершила рывок с появлением Web Server Gateway
Interface (WSGI) — универсального API между веб-приложениями и веб-серверами.
Все веб-фреймворки и веб-серверы Python, показанные далее, используют WSGI.
Обычно вам не нужно знать, как функционирует данный интерфейс (для этого
многого и не потребуется), но знание основных принципов его функционирования
может действительно помочь разработке. Такое соединение называется синхрон-
ным — за одним шагом следует другой.
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

$6*,
Я уже несколько раз упоминал, что в Python начали появляться возможности асин-
хронного программирования, такие как ƒ•› , await и ƒ•› ‹‘. ASGI (Asynchronous
Server Gateway Interface) — аналог WSGI, который использует все эти возможности.
В приложении В вы познакомитесь с этой темой более подробно, а также увидите
примеры новых веб-фреймворков, применяющих ASGI.

DSDFKH
Лучшим WSGI-модулем ƒ’ƒ Ї (KWWSKWWSGDSDFKHRUJ) является ‘†ɏ™•‰‹ (KWWSV
FRGHJRRJOHFRPSPRGZVJL). Он может запускать код, написанный на Python, вну-
три процесса Apache или в отдельном процессе, который обменивается данными
с Apache. Если вы используете Linux или OS X, в вашей системе ƒ’ƒ Ї уже уста-
новлен. Для Windows вам придется устанавливать его самостоятельно (KWWSELWO\
DSDFKHKWWS).
Наконец, установите предпочитаемый веб-фреймворк Python, основанный на
WSGI. Попробуем использовать в наших примерах фреймворк bottle. Практически
вся работа включает в себя конфигурирование Apache, что может оказаться довольно
затруднительным.
Создайте тестовый файл и сохраните его как ŵ˜ƒ”ŵ™™™ŵ–‡•–ŵŠ‘‡Ŝ™•‰‹ (при-
мер 18.2).

ǷȘȐȔȍȘKRPHZVJL
‹’‘”–„‘––އ

ƒ’’Ž‹ ƒ–‹‘ʰ„‘––އŜ†‡ˆƒ—Ž–ɏƒ’’ſƀ

ɒ„‘––އŜ”‘—–‡ſɐŵɐƀ
†‡ˆŠ‘‡ſƀś
”‡–—”ɑƒ’ƒ Їƒ†™•‰‹ř•‹––‹‰‹ƒ–”‡‡ɑ

На сей раз не вызывайте функцию ”—ſƀ, поскольку это запустит встроенный


веб-сервер Python. Нам нужно присвоить некое значение переменной ƒ’’Ž‹ ƒ–‹‘,
поскольку именно его будет проверять ‘†ɏ™•‰‹ при объединении веб-сервера и кода
Python.
Если ƒ’ƒ Ї и его модуль ‘†ɏ™•‰‹ работают корректно, то нужно лишь соеди-
нить их с нашим сценарием Python. Надо добавить в файл одну строку, которая
определяет сайт по умолчанию для этого сервера ƒ’ƒ Ї, но поиск данного файла
сам по себе является задачей. Он может называться ŵ‡– ŵƒ’ƒ ЇɩŵŠ––’†Ŝ ‘ˆ, или
ŵ‡– ŵƒ’ƒ Їɩŵ•‹–‡•ރ˜ƒ‹Žƒ„އŵ†‡ˆƒ—Ž–, или даже быть латинским названием чьей-то
ручной саламандры.
Предположим, вы понимаете работу ƒ’ƒ Ї и нашли нужный файл. Добавьте эту
строку в раздел ʳ‹”–—ƒŽ ‘•–ʴ, который управляет стандартным сайтом:
  ”‹’–Ž‹ƒ•ŵŵ˜ƒ”ŵ™™™ŵ–‡•–ŵŠ‘‡Ŝ™•‰‹
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Этот раздел должен выглядеть так:


ʳ‹”–—ƒŽ ‘•–Ƌśɯɥʴ
‘ —‡–‘‘–ŵ˜ƒ”ŵ™™™

  ”‹’–Ž‹ƒ•ŵŵ˜ƒ”ŵ™™™ŵ–‡•–ŵŠ‘‡Ŝ™•‰‹

ʳ‹”‡ –‘”›ŵ˜ƒ”ŵ™™™ŵ–‡•–ʴ
”†‡”ƒŽŽ‘™ř†‡›
ŽŽ‘™ˆ”‘ƒŽŽ
ʳŵ‹”‡ –‘”›ʴ
ʳŵ‹”–—ƒŽ ‘•–ʴ

Запустите ƒ’ƒ Ї или, если он работал, перезапустите, с целью указать ему, что
следует использовать новую конфигурацию. Перейдя в браузере по адресу KWWS
ORFDOKRVW, вы должны увидеть эту строку:
ƒ’ƒ Їƒ†™•‰‹ř•‹––‹‰‹ƒ–”‡‡

Это запустит ‘†ɏ™•‰‹ во встроенном режиме как часть самого ƒ’ƒ Ї.
Вы также можете запустить его в режиме демона — как один или несколько про-
цессов, отдельных от ƒ’ƒ Ї. Для этого добавьте две новые строки директив в ваш
файл конфигурации ƒ’ƒ Ї:
 ƒ‡‘”‘ ‡••†‘ƒ‹Şƒ‡—•‡”ʰ—•‡”ސƒ‡‰”‘—’ʰ‰”‘—’ސƒ‡–Š”‡ƒ†•ʰɩɬ
 ”‘ ‡•• ”‘—’†‘ƒ‹Şƒ‡

В предыдущем примере переменные user-name и group-name представляют со-


бой имена пользователя и группы в операционной системе, а переменная domain-
name — имя вашего интернет-домена. Минимальная конфигурация ƒ’ƒ Ї может
выглядеть так:
ʳ‹”–—ƒŽ ‘•–Ƌśɯɥʴ
‘ —‡–‘‘–ŵ˜ƒ”ŵ™™™

  ”‹’–Ž‹ƒ•ŵŵ˜ƒ”ŵ™™™ŵ–‡•–ŵŠ‘‡Ŝ™•‰‹

 ƒ‡‘”‘ ‡••›†‘ƒ‹Ŝ ‘—•‡”ʰ›—•‡”‰”‘—’ʰ›‰”‘—’–Š”‡ƒ†•ʰɩɬ


 ”‘ ‡•• ”‘—’›†‘ƒ‹Ŝ ‘

ʳ‹”‡ –‘”›ŵ˜ƒ”ŵ™™™ŵ–‡•–ʴ
”†‡”ƒŽŽ‘™ř†‡›
ŽŽ‘™ˆ”‘ƒŽŽ
ʳŵ‹”‡ –‘”›ʴ
ʳŵ‹”–—ƒŽ ‘•–ʴ

1*,1;
Веб-сервер NGINX (KWWSQJLQ[RUJ) не имеет встроенного модуля Python. Вместо
этого он обменивается данными с помощью отдельного сервера WSGI, такого как
uWSGI или gUnicorn. Вместе они представляют собой очень быструю и удобную
в конфигурации платформу для веб-разработки на Python.
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

Вы можете установить ‰‹š с его официального сайта KWWSZLNLQJLQ[RUJ,QVWDOO.


Небольшая страница документации (KWWSVRUHLOO\)73D) предоставляет инструкции,
позволяющие объединить Flask, NGINX и uWSGI.

ǬȘțȋȐȍȊȍȉșȍȘȊȍȘȣ3\WKRQ
Ниже перечислены некоторые независимые WSGI-серверы, написанные на Python,
которые работают как ƒ’ƒ Ї или ‰‹š и используют несколько процессов и/или
потоков (см. раздел «Конкурентность» главы 15 на с. 308) для обработки одновре-
менных запросов:
‰uwsgi (KWWSSURMHFWVXQELWLWXZVJL);
‰ Ї””›’› (KWWSZZZFKHUU\S\RUJ);
‰pylons (KWWSZZZS\ORQVSURMHFWRUJ).
А это серверы, основанные на событиях, которые пользуются одним процессом,
но избегают блокирования любым одиночным запросом:
‰–‘”ƒ†‘ (KWWSZZZWRUQDGRZHERUJ);
‰gevent (KWWSJHYHQWRUJ);
‰‰—‹ ‘” (KWWSJXQLFRUQRUJ).
О событиях я подробнее рассказывал в разделе «Конкурентность» на с. 308.

ǼȘȍȑȔȊȖȘȒȐȌȓȧȘȈȉȖȚȣȊȍȉșȍȘȊȍȘȈȔȐ
Веб-серверы обрабатывают детали работы HTTP и WSGI, но вам нужно использо-
вать веб-фреймворки, чтобы написать код на Python, который будет поддерживать
сайт. Так что мы немного поговорим о фреймворках, а затем вернемся к альтерна-
тивным способам обслуживания сайтов, использующих их.
Написать сайт на Python можно с помощью множества веб-фреймворков (не-
которые даже могут сказать, что их слишком много). Веб-фреймворк обрабаты-
вает как минимум запросы клиента и ответы сервера. Большинство крупных веб-
фреймворков могут решать такие задачи, как:
‰обработка протокола HTTP;
‰аутентификация (authn, или «кто ты?»);
‰авторизация (authz, или «что ты можешь сделать?»);
‰создание сессии;
‰получение параметров;
‰валидация параметров (обязательные/опциональные, тип, диапазон);
‰обработка глаголов HTTP;
‰маршрутизация (функции/классы);
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰выдача статических файлов (HTML, JS, CSS, изображения);


‰выдача динамических данных (базы данных, сервисы);
‰возврат значений и статусов HTTP.
Опциональные возможности:
‰создание шаблонов для бэкенда;
‰соединение с базами данных, ORM;
‰ограничение скорости;
‰асинхронные задачи.
В следующих подразделах мы напишем пример, использующий два фреймворка
(Bottle и Flask). Они являются синхронными. Далее поговорим об альтернативах,
в частности о сайтах, работающих с базами данных. Вы можете найти подходящий
фреймворк Python для любого сайта, который только представите.

%RWWOH
Bottle состоит из одного файла Python, поэтому его довольно легко опробовать
и развернуть. Bottle не является частью стандартной библиотеки Python, поэтому
установите его с помощью следующей команды:
ɛpip install bottle

Рассмотрим код, который запустит тестовый веб-сервер и вернет текстовую стро-


ку, когда ваш браузер обратится по URL KWWSORFDOKRVW. Сохраните этот файл
как „‘––އɨŜ’› (пример 18.3).

ǷȘȐȔȍȘERWWOHS\
ˆ”‘„‘––އ‹’‘”–”‘—–‡ř”—

ɒ”‘—–‡ſɐŵɐƀ
†‡ˆŠ‘‡ſƀś
”‡–—”ɑ –‹•ɐ–ˆƒ ›ř„—–‹–ɐ•›Š‘‡’ƒ‰‡ɑ

”—ſŠ‘•–ʰɐŽ‘ ƒŽŠ‘•–ɐř’‘”–ʰɰɰɰɰƀ

Bottle использует декоратор route, чтобы связать URL со следующей функцией;


в этом примере ŵ (главная страница) обрабатывается функцией Š‘‡ſƀ. Запустите
данный сценарий сервера с помощью следующей команды:
ɛpython [Link]

Обратившись по адресу KWWSORFDOKRVW, вы должны увидеть следующее:


–‹•ɐ–ˆƒ ›ř„—–‹–ɐ•›Š‘‡’ƒ‰‡

Функция ”—ſƀ запускает встроенный тестовый веб-сервер bottle. Вам не нужно


использовать его в программах, написанных с помощью bottle, но это может ока-
заться полезным на первых порах разработки и тестирования.
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

Теперь вместо создания текста главной страницы в коде создадим отдельный


HTML-файл, который называется ‹†‡šŜŠ–Ž и содержит такую строку:
›ʳ„ʴ‡™ʳŵ„ʴƒ†ʳ‹ʴ‹’”‘˜‡†ʳŵ‹ʴŠ‘‡’ƒ‰‡ŠŠŠ

Дайте bottle задание возвращать содержимое этого файла, когда запрашивается


главная страница. Сохраните данный сценарий как „‘––އɩŜ’› (пример 18.4).

ǷȘȐȔȍȘERWWOHS\
ˆ”‘„‘––އ‹’‘”–”‘—–‡ř”—ř•–ƒ–‹ ɏˆ‹Ž‡

ɒ”‘—–‡ſɐŵɐƀ
†‡ˆƒ‹ſƀś
”‡–—”•–ƒ–‹ ɏˆ‹Ž‡ſɐ‹†‡šŜŠ–Žɐř”‘‘–ʰɐŜɐƀ

”—ſŠ‘•–ʰɐŽ‘ ƒŽŠ‘•–ɐř’‘”–ʰɰɰɰɰƀ

В вызове •–ƒ–‹ ɏˆ‹Ž‡ſƀ мы хотим получить файл ‹†‡šŜŠ–Ž из каталога, ука-


занного в root (в нашем случае в ɐŜɐ, текущем каталоге). Если код предыдущего
примера все еще выполняется, то остановите его. Теперь запустите новый сервер:
ɛpython [Link]

Каждый раз, когда вы обращаетесь к странице KWWSORFDOKRVW, вы должны


видеть следующее:
›newƒ†improvedŠ‘‡’ƒ‰‡ŠŠŠ

Добавим последний пример, который демонстрирует, как передавать аргументы


в URL и использовать их. Конечно же, этот файл будет называться „‘––އɪŜ’› (при-
мер 18.5).

ǷȘȐȔȍȘERWWOHS\
ˆ”‘„‘––އ‹’‘”–”‘—–‡ř”—ř•–ƒ–‹ ɏˆ‹Ž‡

ɒ”‘—–‡ſɐŵɐƀ
†‡ˆŠ‘‡ſƀś
”‡–—”•–ƒ–‹ ɏˆ‹Ž‡ſɐ‹†‡šŜŠ–Žɐř”‘‘–ʰɐŜɐƀ
ɒ”‘—–‡ſɐŵ‡ Š‘ŵʳ–Š‹‰ʴɐƀ
†‡ˆ‡ Š‘ſ–Š‹‰ƀś
”‡–—”ɑƒ›Š‡ŽŽ‘–‘›Ž‹––އˆ”‹‡†śʩ•Šɑʩ–Š‹‰

”—ſŠ‘•–ʰɐŽ‘ ƒŽŠ‘•–ɐř’‘”–ʰɰɰɰɰƀ

У нас появилась новая функция ‡ Š‘ſƀ, в которую мы хотим передавать стро-


ковый аргумент через URL. За это отвечает строка ɒ”‘—–‡ſɐŵ‡ Š‘ŵʳ–Š‹‰ʴɐƀ в пре-
дыдущем примере. Конструкция ʳ–Š‹‰ʴ в маршруте означает: все, что находится
в URL после ŵ‡ Š‘ŵ, присваивается строковому аргументу thing, который передается
функции ‡ Š‘. Чтобы увидеть развитие событий, остановите старый сервер, если он
все еще работает, и запустите его с новым кодом:
ɛpython [Link]
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Далее перейдите в браузере по ссылке KWWSORFDOKRVWHFKR0RWKUD. Вы должны


увидеть следующее:
ƒ›Š‡ŽŽ‘–‘›Ž‹––އˆ”‹‡†ś‘–Š”ƒŠ

Оставьте „‘––އɪŜ’› работать еще на пару минут, чтобы мы могли попробовать


что-либо еще. Вы проверяли работу этих примеров, вводя URL в браузер и глядя на
отображаемые страницы. Вы также можете использовать клиентские библиотеки,
такие как requests, чтобы они выполняли работу за вас. Сохраните этот код как
„‘––އɏ–‡•–Ŝ’› (пример 18.6).

ǷȘȐȔȍȘERWWOHBWHVWS\
‹’‘”–”‡“—‡•–•

”‡•’ʰ”‡“—‡•–•Ŝ‰‡–ſɐŠ––’śŵŵŽ‘ ƒŽŠ‘•–śɰɰɰɰŵ‡ Š‘ŵ‘–Š”ƒɐƀ


‹ˆ”‡•’Ŝ•–ƒ–—•ɏ ‘†‡ʰʰɩɥɥƒ†Ɏ
”‡•’Ŝ–‡š–ʰʰɐƒ›Š‡ŽŽ‘–‘›Ž‹––އˆ”‹‡†ś‘–Š”ƒŠɐś
’”‹–ſɐ –™‘”‡†ŠŠƒ–ƒŽ‘•–‡˜‡”Šƒ’’‡•Šɐƀ
‡Ž•‡ś
’”‹–ſɐ”‰Šř‰‘––Š‹•śɐř”‡•’Ŝ–‡š–ƀ

Отлично! Теперь запустите этот код:


ɛpython bottle_test.py

В терминале вы должны увидеть следующее:


–™‘”‡†ŠŠƒ–ƒŽ‘•–‡˜‡”Šƒ’’‡•Š

Перед вами небольшой пример юнит-теста. В главе 19 вы можете получить


более подробную информацию о том, почему тесты — это хорошо и как написать их
с помощью Python.
У фреймворка Bottle больше возможностей, чем я вам показал. В частности, при
вызове функции ”—ſƀ можно попробовать добавить следующие аргументы:
‰†‡„—‰ʰ”—‡ — создает страницу отладки, если вы получаете ошибку HTTP;
‰”‡Ž‘ƒ†‡”ʰ”—‡ — перезагружает страницу в браузере, если вы измените хотя бы
небольшой кусочек кода.
Все это хорошо задокументировано на сайте разработчика KWWSERWWOHS\RUJGRFVGHY.

)ODVN
Bottle — это хороший фреймворк для того, чтобы начать работу. Но если вам нужно
больше возможностей, то попробуйте Flask. Он был создан в 2010 году как перво-
апрельская шутка, но реакция энтузиастов вдохновила его автора, Армина Ронахера,
сделать его настоящим фреймворком. Он назвал результат Flask («склянка»), обыгры-
вая название Bottle — «бутылка».
Flask почти так же прост в использовании, как и Bottle, но поддерживает мно-
жество расширений, которые могут оказаться полезными в профессиональной
веб-разработке, например аутентификацию с помощью Facebook и интеграцию с ба-
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

зами данных. Это решение мне нравится больше других веб-фреймворков Python,
поскольку в нем сбалансированы простота применения и богатый набор функций.
Пакет ˆŽƒ• включает в себя библиотеку WSGI ™‡”œ‡—‰ и библиотеку шаблонов
Œ‹Œƒɩ. Вы можете установить его с помощью терминала:
ɛpip install flask

Переделаем наш последний пример с использованием фреймворка Flask. Однако


для начала нужно внести несколько изменений.
‰Во Flask каталог по умолчанию для статических файлов называется •–ƒ–‹ ,
и URL для таких файлов тоже начинается со ŵ•–ƒ–‹ . Мы изменяем папку на ɐŜɐ
(текущий каталог) и префикс URL на ɐ ɐ (пустой), чтобы позволить URL ŵ ото-
бражать файл ‹†‡šŜŠ–Ž.
‰В функции ”—ſƀ установка параметра †‡„—‰ʰ”—‡ активизирует также автома-
тическую перезагрузку, тогда как фреймворк bottle для отладки и перезагрузки
использует отдельные аргументы.
Сохраните этот код в файл ˆŽƒ•ɨŜ’› (пример 18.7).

ǷȘȐȔȍȘIODVNS\
ˆ”‘ˆŽƒ•‹’‘”– Žƒ•

ƒ’’ʰ Žƒ•ſɏɏƒ‡ɏɏř•–ƒ–‹ ɏˆ‘ކ‡”ʰɐŜɐř•–ƒ–‹ ɏ—”Žɏ’ƒ–Šʰɐɐƀ

ɒƒ’’Ŝ”‘—–‡ſɐŵɐƀ
†‡ˆŠ‘‡ſƀś
”‡–—”ƒ’’Ŝ•‡†ɏ•–ƒ–‹ ɏˆ‹Ž‡ſɐ‹†‡šŜŠ–Žɐƀ

ɒƒ’’Ŝ”‘—–‡ſɐŵ‡ Š‘ŵʳ–Š‹‰ʴɐƀ
†‡ˆ‡ Š‘ſ–Š‹‰ƀś
”‡–—”ɑƒ›Š‡ŽŽ‘–‘›Ž‹––އˆ”‹‡†śʩ•ɑʩ–Š‹‰
ƒ’’Ŝ”—ſ’‘”–ʰɰɰɰɰř†‡„—‰ʰ”—‡ƀ

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


ɛpython [Link]

Протестируйте главную страницу, введя в браузер следующий URL:


Š––’śŵŵŽ‘ ƒŽŠ‘•–śɰɰɰɰŵ

Вы должны увидеть следующее (как и в случае с bottle):


›newƒ†‹’”‘˜‡†Š‘‡’ƒ‰‡ŠŠŠ

Попробуйте обратиться к конечной точке ŵ‡ Š‘:


Š––’śŵŵŽ‘ ƒŽŠ‘•–śɰɰɰɰŵ‡ Š‘ŵ ‘†œ‹ŽŽƒ

Вы должны увидеть следующее:


ƒ›Š‡ŽŽ‘–‘›Ž‹––އˆ”‹‡†ś ‘†œ‹ŽŽƒ

Есть еще одно преимущество установки параметра †‡„—‰ равным ”—‡ при вызове
метода run. Если в серверном коде генерируется исключение, то Flask возвращает
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

особую отформатированную страницу, содержащую полезные сведения о том, что


и где пошло не так. Даже больше: вы можете вводить команды с целью увидеть зна-
чения переменных в программе сервера.

ǵȍ țșȚȈȕȈȊȓȐȊȈȑȚȍ ȗȈȘȈȔȍȚȘ GHEXJ  7UXH ȕȈ ȗȘȖȐȏȊȖȌșȚȊȍȕȕȣȝ ȊȍȉșȍȘȊȍȘȈȝ


ǺȈȒȐȔȖȉȘȈȏȖȔȗȖȚȍȕȞȐȈȓȤȕȣȍȏȓȖțȔȣȠȓȍȕȕȐȒȐȗȖȓțȟȈȚșȓȐȠȒȖȔȔȕȖȋȖȐȕȜȖȘ
ȔȈȞȐȐȖȊȈȠȍȔșȍȘȊȍȘȍ

До сих пор примеры с использованием Flask повторяли то, что мы делали с по-
мощью фреймворка Bottle. Что такого может делать Flask в отличие от Bottle? Flask
содержит Œ‹Œƒɩ — более широкую систему шаблонов. Рассмотрим небольшой при-
мер одновременного применения Œ‹Œƒɩ и Flask.
Создайте каталог –‡’Žƒ–‡• и файл ˆŽƒ•ɩŜŠ–Ž внутри него (пример 18.8).

ǷȘȐȔȍȘIODVNKWPO
ʳŠ–Žʴ
ʳЇƒ†ʴ
ʳ–‹–އʴ Žƒ•ɩšƒ’Ž‡ʳŵ–‹–އʴ
ʳŵЇƒ†ʴ
ʳ„‘†›ʴ
ƒ›Š‡ŽŽ‘–‘›Ž‹––އˆ”‹‡†śƇƇ–Š‹‰ƈƈ
ʳŵ„‘†›ʴ
ʳŵŠ–Žʴ

Далее мы напишем серверный код, который получает этот шаблон, заполняет


значение аргумента thing , передаваемого нами, и отрисовывает его как HTML
(я опущу функцию Š‘‡ſƀ для экономии места). Сохраните этот файл под именем
ˆŽƒ•ɩŜ’› (пример 18.9).

ǷȘȐȔȍȘIODVNS\
ˆ”‘ˆŽƒ•‹’‘”– Žƒ•ř”‡†‡”ɏ–‡’Žƒ–‡

ƒ’’ʰ Žƒ•ſɏɏƒ‡ɏɏƀ

ɒƒ’’Ŝ”‘—–‡ſɐŵ‡ Š‘ŵʳ–Š‹‰ʴɐƀ
†‡ˆ‡ Š‘ſ–Š‹‰ƀś
”‡–—””‡†‡”ɏ–‡’Žƒ–‡ſɐˆŽƒ•ɩŜŠ–Žɐř–Š‹‰ʰ–Š‹‰ƀ

ƒ’’Ŝ”—ſ’‘”–ʰɰɰɰɰř†‡„—‰ʰ”—‡ƀ

Аргумент thing ʰ thing утверждает, что для передачи переменной с именем thing
в шаблон эта переменная содержит значение строки thing.
Убедитесь, что файл ˆŽƒ•ɨŜ’› перестал работать, и запустите файл ˆŽƒ•ɩŜ’›:
ɛpython [Link]

Теперь введите этот URL:


Š––’śŵŵŽ‘ ƒŽŠ‘•–śɰɰɰɰŵ‡ Š‘ŵ ƒ‡”ƒ
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

Вы должны увидеть следующее:


ƒ›Š‡ŽŽ‘–‘›Ž‹––އˆ”‹‡†ś ƒ‡”ƒ

Модифицируем наш пример и сохраним его в каталоге –‡’Žƒ–‡• под именем


ˆŽƒ•ɪŜŠ–Ž:
ʳŠ–Žʴ
ʳЇƒ†ʴ
ʳ–‹–އʴ Žƒ•ɪšƒ’Ž‡ʳŵ–‹–އʴ
ʳŵЇƒ†ʴ
ʳ„‘†›ʴ
ƒ›Š‡ŽŽ‘–‘›Ž‹––އˆ”‹‡†śƇƇ–Š‹‰ƈƈŜ
Žƒ•ř‹–Œ—•–†‡•–”‘›‡†ƇƇ’Žƒ ‡ƈƈŠ
ʳŵ„‘†›ʴ
ʳŵŠ–Žʴ

Второй аргумент в URL, ‡ Š‘, вы можете передать множеством способов.


Передача аргумента как части пути URL. С помощью этого метода вы просто
расширяете URL (сохраните код, показанный в примере 18.10, как ˆŽƒ•ɪƒŜ’›):

ǷȘȐȔȍȘIODVNDS\
ˆ”‘ˆŽƒ•‹’‘”– Žƒ•ř”‡†‡”ɏ–‡’Žƒ–‡

ƒ’’ʰ Žƒ•ſɏɏƒ‡ɏɏƀ

ɒƒ’’Ŝ”‘—–‡ſɐŵ‡ Š‘ŵʳ–Š‹‰ʴŵʳ’Žƒ ‡ʴɐƀ


†‡ˆ‡ Š‘ſ–Š‹‰ř’Žƒ ‡ƀś
”‡–—””‡†‡”ɏ–‡’Žƒ–‡ſɐˆŽƒ•ɪŜŠ–Žɐř–Š‹‰ʰ–Š‹‰ř’Žƒ ‡ʰ’Žƒ ‡ƀ

ƒ’’Ŝ”—ſ’‘”–ʰɰɰɰɰř†‡„—‰ʰ”—‡ƀ

Как обычно, остановите предыдущий сценарий тестового сервера, если он еще


работает, и затем запустите новый:
ɛpython [Link]

URL должен выглядеть так:


Š––’śŵŵŽ‘ ƒŽŠ‘•–śɰɰɰɰŵ‡ Š‘ŵ‘†ƒŵ ‡‡•’‘”–

Вы должны увидеть следующее:


ƒ›Š‡ŽŽ‘–‘›Ž‹––އˆ”‹‡†ś‘†ƒŜŽƒ•ř‹–Œ—•–†‡•–”‘›‡† ‡‡•’‘”–Š

Или же вы можете передать аргументы как параметры команды , как это по-
казано в примере 18.11; сохраните файл как ˆŽƒ•ɪ„Ŝ’›.

ǷȘȐȔȍȘIODVNES\
ˆ”‘ˆŽƒ•‹’‘”– Žƒ•ř”‡†‡”ɏ–‡’Žƒ–‡ř”‡“—‡•–

ƒ’’ʰ Žƒ•ſɏɏƒ‡ɏɏƀ

ɒƒ’’Ŝ”‘—–‡ſɐŵ‡ Š‘ŵɐƀ
†‡ˆ‡ Š‘ſƀś
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

–Š‹‰ʰ”‡“—‡•–Ŝƒ”‰•Ŝ‰‡–ſɐ–Š‹‰ɐƀ
’Žƒ ‡ʰ”‡“—‡•–Ŝƒ”‰•Ŝ‰‡–ſɐ’Žƒ ‡ɐƀ
”‡–—””‡†‡”ɏ–‡’Žƒ–‡ſɐˆŽƒ•ɪŜŠ–Žɐř–Š‹‰ʰ–Š‹‰ř’Žƒ ‡ʰ’Žƒ ‡ƀ

ƒ’’Ŝ”—ſ’‘”–ʰɰɰɰɰř†‡„—‰ʰ”—‡ƀ

Запустите новый сценарий сервера:


ɛpython [Link]

В этот раз используйте такой URL:


Š––’śŵŵŽ‘ ƒŽŠ‘•–śɰɰɰɰŵ‡ Š‘ţ–Š‹‰ʰ ‘”‰‘ĺ’Žƒ ‡ʰ‹Ž‡”†‹‰

Вы должны увидеть следующее:


ƒ›Š‡ŽŽ‘–‘›Ž‹––އˆ”‹‡†ś ‘”‰‘ŜŽƒ•ř‹–Œ—•–†‡•–”‘›‡†‹Ž‡”†‹‰Š

Когда команда  используется в URL, любые аргументы должны передаваться


в формате ĺȞȟȲȫɮʰțȡȔȫɮĺȞȟȲȫɯʰțȡȔȫɯĺŜŜŜ
Вы также можете использовать оператор словаря **, чтобы передать несколько
аргументов в шаблон с помощью одного словаря (назовите файл ˆŽƒ•ɪ Ŝ’›), как
показано в примере 18.12.

ǷȘȐȔȍȘIODVNFS\
ˆ”‘ˆŽƒ•‹’‘”– Žƒ•ř”‡†‡”ɏ–‡’Žƒ–‡ř”‡“—‡•–

ƒ’’ʰ Žƒ•ſɏɏƒ‡ɏɏƀ

ɒƒ’’Ŝ”‘—–‡ſɐŵ‡ Š‘ŵɐƀ
†‡ˆ‡ Š‘ſƀś
™ƒ”‰•ʰƇƈ
™ƒ”‰•ƃɐ–Š‹‰ɐƄʰ”‡“—‡•–Ŝƒ”‰•Ŝ‰‡–ſɐ–Š‹‰ɐƀ
™ƒ”‰•ƃɐ’Žƒ ‡ɐƄʰ”‡“—‡•–Ŝƒ”‰•Ŝ‰‡–ſɐ’Žƒ ‡ɐƀ
”‡–—””‡†‡”ɏ–‡’Žƒ–‡ſɐˆŽƒ•ɪŜŠ–ŽɐřƋƋ™ƒ”‰•ƀ

ƒ’’Ŝ”—ſ’‘”–ʰɰɰɰɰř†‡„—‰ʰ”—‡ƀ

Элемент ƋƋ™ƒ”‰• действует как конструкция –Š‹‰ʰ–Š‹‰ř ’Žƒ ‡ʰ’Žƒ ‡. Исполь-


зуя этот словарь, можно сэкономить немного времени, если входных аргументов
много.
У языка шаблонов Œ‹Œƒɩ гораздо больше возможностей. Если вы работали на
PHP, то увидите много общего.

'MDQJR
Œƒ‰‘ (KWWSVZZZGMDQJRSURMHFWFRP) — очень популярный веб-фреймворк, написан-
ный на Python, особенно для крупных сайтов. Его стоит изучить по многим при-
чинам, среди которых регулярно появляющиеся требования опыта работы с Œƒ‰‘
в объявлениях о вакансиях. Он содержит код ORM (об ORM мы говорили в подраз-
деле SQLAlchemy на с. 348), позволяющий создавать автоматические веб-страницы
для типичных функций баз данных  (создание, замена, обновление, удаление),
которые я рассматривал в главе 16. Он также включает автоматические страницы
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

администрирования для этих веб-страниц, но они предназначены для внутреннего


использования среди программистов, а не размещения на публичных веб-страницах.
Вам не обязательно использовать ORM именно для Œƒ‰‘, если больше нравится
применять что-то другое, например SQLAlchemy или прямые запросы SQL.

ǬȘțȋȐȍȜȘȍȑȔȊȖȘȒȐ
Вы можете сравнить фреймворки с помощью онлайн-таблицы, размещенной по
адресу KWWSELWO\ZHEIUDPHV:
‰fastapi (KWWSVIDVWDSLWLDQJHORFRP) обрабатывает как синхронные (WSGI), так
и асинхронные (ASGI) вызовы, использует подсказки типов и генерирует тесто-
вые страницы. Очень хорошо задокументирован. Рекомендую;
‰™‡„ɩ’› (KWWSZZZZHES\FRP) работает примерно с тем же, с чем и †Œƒ‰‘, только
немного в другом стиле;
‰’›”ƒ‹† (KWWSVWU\S\UDPLGFRP) появился из более раннего проекта pylons, с точки
зрения функционала похож на †Œƒ‰‘;
‰turbogears (KWWSWXUERJHDUVRUJ) поддерживает ORM, множество баз данных и не-
сколько языков шаблонов;
‰™Š‡‡œ›Ŝ™‡„ (KWWSS\WKRQKRVWHGRUJZKHH]\ZHE) более молодой фреймворк, оптими-
зирован для повышения производительности. Недавние исследования показали,
что он работает быстрее других (KWWSELWO\ZKHH]\ZHE);
‰‘Ž–‡ (KWWSVPROWHQIUDPHZRUNFRP) также использует подсказки типов, но под-
держивает только WSGI;
‰apistar (KWWSVGRFVDSLVWDUFRP) похож на fastapi, но это скорее инструмент для
валидации API, чем веб-фреймворк;
‰ƒ•‘‹–‡ (KWWSVGRFVPDVRQLWHSURMHFWFRP) — аналог Ruby on Rails или Laravel, на-
писанный на Python.

ǼȘȍȑȔȊȖȘȒȐȌȓȧȘȈȉȖȚȣșȉȈȏȈȔȐȌȈȕȕȣȝ
Интернет и базы данных — это неразлучная парочка: где одно, там и другое. В реаль-
ных приложениях Python в какой-то момент вам может понадобиться предоставить
веб-интерфейс (сайт и/или API) реляционной базе данных.
Вы можете создать собственный интерфейс с помощью:
‰веб-фреймворка, такого как Bottle или Flask;
‰пакет для работы с БД, наподобие db-api или SQLAlchemy;
‰драйвер для базы данных вроде pymysql.
Вместо этого вы также можете использовать один из пакетов, объединяющих
Интернет и базы данных:
‰connexion (KWWSVFRQQH[LRQUHDGWKHGRFVLR);
‰datasette (KWWSVGDWDVHWWHUHDGWKHGRFVLR);
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰sandman2 (KWWSVJLWKXEFRPMHIINQXSSVDQGPDQ);
‰flask-restless (KWWSVIODVNUHVWOHVVUHDGWKHGRFVLR).
Или можете использовать фреймворк со встроенной поддержкой баз данных,
такой как Django.
Кроме того, ничто не заставляет вас выбирать именно реляционную базу данных.
Если схема ваших данных может значительно изменяться — столбцы явно разли-
чаются в разных строках, — то вам стоит выбрать базу данных, не имеющую схемы.
Это могут быть базы данных NoSQL, которые мы рассматривали в главе 16. Однажды
я работал над сайтом, который изначально хранил данные в базе данных NoSQL,
затем переключался на одну реляционную базу данных, затем на другую, потом на
другую базу данных NoSQL и, наконец, возвращался к одной из реляционных.

ǪȍȉșȍȘȊȐșȣȐȈȊȚȖȔȈȚȐȏȈȞȐȧ
Мы рассмотрели традиционные веб-клиенты и серверные приложения, потребля-
ющие и генерирующие HTML-страницы. Интернет оказался мощным способом
объединять приложения и данные во многих форматах, не только HTML.

ǴȖȌțȓȤZHEEURZVHU
Начнем с небольшого сюрприза. Запустите сессию Python в окне терминала и вве-
дите следующую строку:
ʴʴʴ‹’‘”–ƒ–‹‰”ƒ˜‹–›

Эта строка скрыто вызывает модуль стандартной библиотеки webbrowser и пере-


направляет ваш браузер по информативной ссылке Python1.
Вы можете использовать этот модуль непосредственно. Данная программа за-
гружает главную страницу сайта Python в ваш браузер:
ʴʴʴ‹’‘”–™‡„„”‘™•‡”
ʴʴʴ—”ŽʰɐŠ––’śŵŵ™™™Ŝ’›–Š‘Ŝ‘”‰ŵɐ
ʴʴʴ™‡„„”‘™•‡”Ŝ‘’‡ſ—”Žƀ
”—‡

Этот код откроет ее в новом окне:


ʴʴʴ™‡„„”‘™•‡”Ŝ‘’‡ɏ‡™ſ—”Žƀ
”—‡

А этот — на новой вкладке, если ваш браузер поддерживает вкладки:


ʴʴʴ™‡„„”‘™•‡”Ŝ‘’‡ɏ‡™ɏ–ƒ„ſɐŠ––’śŵŵ™™™Ŝ’›–Š‘Ŝ‘”‰ŵɐƀ
”—‡

Модуль webbrowser заставляет браузер делать всю работу.

1
Если вы по какой-то причине не видите ее, то посетите сайт xkcd ([Link]
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

ǴȖȌțȓȤZHEYLHZ
Вместо вызова браузера, как это делает модуль webbrowser, модуль webview ото-
бражает страницу в собственном окне, используя интерфейс, нативный для вашей
машины. Чтобы установить его в ОС Linux или macOS:
ɛpip install pywebview[qt]

В Windows:
ɛpip install pywebview[cef]

Обратитесь к инструкциям по установке (KWWSVRUHLOO\1L<'), если у вас возникли


проблемы.
Рассмотрим пример, в котором я передал модулю официальный сайт правитель-
ства США, показывающий текущее время:
ʴʴʴ‹’‘”–™‡„˜‹‡™
ʴʴʴ—”Žʰ‹’—–ſɑţɑƀ
ţŠ––’śŵŵ–‹‡Ŝ‰‘˜
ʴʴʴ™‡„˜‹‡™Ŝ ”‡ƒ–‡ɏ™‹†‘™ſˆɑ™‡„˜‹‡™†‹•’Žƒ›‘ˆƇ—”Žƈɑř—”Žƀ

На рис. 18.1 показан полученный мной результат.


Чтобы остановить программу, убейте окно отображения.

ǸȐșǶȒȕȖZHEYLHZ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

5(67$3,
Зачастую данные доступны только внутри веб-страниц. При желании получить
к ним доступ вам нужно получить доступ к странице через браузер и прочитать ее.
Если с момента вашего последнего визита авторы сайта внесли какие-нибудь из-
менения, то местоположение и стиль данных могли измениться.
Вместо того чтобы публиковать веб-страницы, вы можете предоставить до-
ступ к данным через веб-интерфейс программирования приложений (Application
Programming Interface, API). Клиенты получают доступ к вашему сервису, делая
запросы к URL, и получают ответы, содержащие статус и данные. Вместо HTML-
страниц данные имеют формат, который удобнее использовать в других програм-
мах, таких как JSON и XML (в главе 16 содержится более подробная информация
о форматах).
Понятие «передача состояния представления» (Representational State Transfer,
REST) было определено Роем Филдингом (Roy Fielding) в его докторской диссерта-
ции. Многие продукты имеют REST-интерфейс или интерфейс RESTful. На практике
это часто означает, что они имеют веб-интерфейс — определения URL, предназна-
ченные для доступа к веб-сервису.
Сервис RESTful использует глаголы HTTP определенными способами, описан-
ными далее:
‰  получает информацию о ресурсе, но не его данные;
‰  получает данные ресурса с сервера. Это стандартный метод, используемый
вашим браузером.  не должен применяться для создания, изменения или
удаления данных;
‰ создает новый ресурс;
‰ заменяет существующий ресурс, создавая его, если его нет;
‰ частично обновляет ресурс;
‰ — этот глагол говорит сам за себя: DELETE удаляет. Мы за правдивость
в рекламе!
Клиент RESTful также может запрашивать содержимое одного или нескольких
типов с помощью заголовков запроса HTTP. Например, сложный сервис с интер-
фейсом REST может принимать и возвращать данные в строках JSON.

ǷȖȐșȒȐȊȣȉȖȘȒȈȌȈȕȕȣȝ
Иногда вам нужно получить немного больше информации — рейтинг фильма, цену
акции или доступность продукта, — но требуемая информация доступна только на
HTML-страницах, при этом окружена рекламой и посторонним контентом.
Вы можете извлечь необходимую информацию вручную, сделав следующее.
1. Введите URL в браузер.
2. Подождите, пока загрузится удаленная страница.
3. Просмотрите отображенную страницу на предмет необходимой информации.
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

4. Запишите ее где-нибудь.
5. Повторите процесс для связанных URL.
Однако гораздо более приятно автоматизировать некоторые из этих шагов.
Программа, автоматически получающая данные из Сети, называется краулером или
веб-пауком1. После того как содержимое было получено с одного из удаленных веб-
серверов, скрапер анализирует ее, чтобы найти иголку в стоге сена.

6FUDS\
Если вам нужно мощное решение, объединяющее в себе возможности краулера
и скрапера, то стоит загрузить Scrapy (KWWSVFUDS\RUJ):
ɛpip install scrapy
Эта команда установит сам модуль и программу • ”ƒ’›, работающую в команд-
ной строке.
Scrapy — это фреймворк, а не модуль, в отличие от ‡ƒ—–‹ˆ—Ž‘—’. Он имеет боль-
ше возможностей, но зачастую его трудно настроить. Чтобы узнать больше о Scrapy,
прочтите Scrapy at a Glance (KWWSVRUHLOO\,<RH) и руководство (KWWSVRUHLOO\+B$:).

%HDXWLIXO6RXS
Если у вас уже есть HTML-данные с сайта и вы просто хотите извлечь оттуда дан-
ные, то вам подойдет ‡ƒ—–‹ˆ—Ž‘—’ (KWWSVRUHLOO\FP9). Анализировать HTML
труднее, чем кажется. Это происходит потому, что большая часть HTML-кода
на общедоступных веб-страницах технически некорректна: незакрытые теги, не-
правильная вложенность и прочие усложнения. Если вы пытаетесь написать свой
HTML-анализатор с помощью регулярных выражений, которые мы рассматривали
в разделе «Текстовые строки: регулярные выражения» на с. 253, то довольно скоро
столкнетесь с подобным беспорядком.
Чтобы установить ‡ƒ—–‹ˆ—Ž‘—’, введите следующую команду (не забудьте по-
ставить в конце ɫ, иначе pip попробует установить более старую версию и, возможно,
выдаст ошибку):
ɛpip install beautifulsoup4
Теперь воспользуемся им для того, чтобы получить все ссылки с веб-страницы.
HTML-элемент a — это ссылка, а href — ее атрибут, который представляет собой
место назначения ссылки. В примере 18.13 мы определим функцию ‰‡–ɏŽ‹•ſƀ,
которая делает грязную работу, и основную программу, получающую один или не-
сколько URL как аргументы командной строки.
ǷȘȐȔȍȘOLQNVS\
†‡ˆ‰‡–ɏŽ‹•ſ—”Žƀś
‹’‘”–”‡“—‡•–•
ˆ”‘„•ɫ‹’‘”–‡ƒ—–‹ˆ—Ž‘—’ƒ••‘—’
”‡•—Ž–ʰ”‡“—‡•–•Ŝ‰‡–ſ—”Žƀ

1
Неприятный термин, если вы арахнофоб.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

’ƒ‰‡ʰ”‡•—Ž–Ŝ–‡š–
†‘ ʰ•‘—’ſ’ƒ‰‡ƀ
Ž‹•ʰƃ‡Ž‡‡–Ŝ‰‡–ſɐŠ”‡ˆɐƀˆ‘”‡Ž‡‡–‹†‘ Ŝˆ‹†ɏƒŽŽſɐƒɐƀƄ
”‡–—”Ž‹•

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
‹’‘”–•›•
ˆ‘”—”Ž‹•›•Ŝƒ”‰˜ƃɨśƄś
’”‹–ſɐ‹•‹ɐř—”Žƀ
ˆ‘”—řŽ‹‹‡—‡”ƒ–‡ſ‰‡–ɏŽ‹•ſ—”Žƀř•–ƒ”–ʰɨƀś
’”‹–ſ—řŽ‹ƀ
’”‹–ſƀ
Я сохранил эту программу под именем Ž‹•Ŝ’›, а затем запустил с помощью
данной команды:
ɛpython [Link] [Link]
Взгляните на первые несколько отображенных строк:
‹•‹Š––’śŵŵ„‘‹‰„‘‹‰Ŝ‡–ŵ
ɨŠ––’śŵŵ„‘‹‰„‘‹‰Ŝ‡–ŵ•—‰‰‡•–ŜŠ–Ž
ɩŠ––’śŵŵ„‘‹‰„‘‹‰Ŝ‡–ŵ ƒ–‡‰‘”›ŵˆ‡ƒ–—”‡ŵ
ɪŠ––’śŵŵ„‘‹‰„‘‹‰Ŝ‡–ŵ ƒ–‡‰‘”›ŵ”‡˜‹‡™ŵ
ɫŠ––’śŵŵ„‘‹‰„‘‹‰Ŝ‡–ŵ ƒ–‡‰‘”›ŵ’‘† ƒ•–•
ɬŠ––’śŵŵ„‘‹‰„‘‹‰Ŝ‡–ŵ ƒ–‡‰‘”›ŵ˜‹†‡‘ŵ
ɭŠ––’śŵŵ„„•Ŝ„‘‹‰„‘‹‰Ŝ‡–ŵ
ɮŒƒ˜ƒ• ”‹’–ś˜‘‹†ſɥƀ
ɯŠ––’śŵŵ•Š‘’Ŝ„‘‹‰„‘‹‰Ŝ‡–ŵ
ɰŠ––’śŵŵ„‘‹‰„‘‹‰Ŝ‡–ŵƒ„‘—–
ɨɥŠ––’śŵŵ„‘‹‰„‘‹‰Ŝ‡–ŵ ‘–ƒ –

5HTXHVWV+70/
Кеннет Ритц, автор популярного пакета для работы с веб-клиентами requests, на-
писал новую библиотеку для скрапинга, которая называется Requests-HTML (KWWS
KWPOS\WKRQUHTXHVWVRUJ) (для Python 3.6 и более новых версий).
Она получает страницу и обрабатывает ее элементы, поэтому вы, например,
можете найти все ссылки, все содержимое или атрибуты любого элемента HTML.
Библиотека имеет простой дизайн, похожий на requests и другие пакеты этого
автора. В конечном счете она может быть проще в использовании, чем ‡ƒ—–‹ˆ—Ž‘—’
или Scrapy.

ǬȈȊȈȑȚȍȗȖșȔȖȚȘȐȔȜȐȓȤȔ
Напишем полноценную программу.
Она будет искать видео с помощью API архива Internet Archive1. Это один из
немногих API, которые позволяют получить анонимный доступ, и он будет суще-
ствовать и после того, как данная книга будет напечатана.

1
Если помните, я использовал еще один API для работы с архивами в основном примере
главы 1.
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

ǩȖȓȤȠȐȕșȚȊȖȊȍȉ$3,ȚȘȍȉțȦȚȖȚȊȈșȗȖȓțȟȐȚȤȒȓȦȟ$3,ȐȗȘȍȌȖșȚȈȊȓȧȚȤȍȋȖȊșȧȒȐȑ
ȘȈȏȒȖȋȌȈȊȣȝȖȚȐȚȍȗȖȓțȟȐȚȤȒȕȍȔțȌȖșȚțȗǷȖȟȍȔț"ȅȚȖ©ȚȘȈȋȍȌȐȧȖȉȡȐȕª²
ȉȍșȗȓȈȚȕȣȍȘȍșțȘșȣșȈȕȖȕȐȔȕȣȔȌȖșȚțȗȖȔȏȈȟȈșȚțȦȐșȗȖȓȤȏțȦȚșȧșȓȐȠȒȖȔȔȕȖȋȖ
ȐȕȍȗȘȈȊȐȓȤȕȖǪȖȚȗȖȟȍȔțțȕȈșȕȍȔȖȎȍȚȉȣȚȤȝȖȘȖȠȐȝșȍȘȊȐșȖȊ

Программа, показанная в примере 18.14, делает следующее:


‰приглашает вас ввести часть названия фильма или видео;
‰ищет элемент с таким названием в Internet Archive;
‰возвращает список идентификаторов, имен и описаний;
‰перечисляет их и просит вас выбрать один;
‰отображает это видео в вашем браузере;
Сохраните данный файл под именем ‹ƒ‘˜‹‡•Ŝ’›.
Функция •‡ƒ” Šſƀ использует библиотеку requests, чтобы получить доступ
к URL и результаты и преобразовать их в формат JSON. Другие функции обрабаты-
вают все остальное. Вы увидите использование включений списков, разбиения строк
и других возможностей, которые были представлены в предыдущих главах. (Номера
строк не являются частью исходного кода; они будут использованы в упражнениях,
чтобы найти нужные фрагменты кода.)

ǷȘȐȔȍȘLDPRYLHVS\
ɨɑɑɑǭȔȝȘșȠȖȜȘșȢȖ –‡”‡–” Š‹˜‡
ɩȣȢȨȤȔȗȠșȡȦȧȡȔțȖȔȡȜȳȜȢȦȢȕȤȔțȜȠșȗȢŜɑɑɑ
ɪ
ɫ‹’‘”–•›•
ɬ‹’‘”–™‡„„”‘™•‡”
ɭ‹’‘”–”‡“—‡•–•
ɮ
ɯ†‡ˆ•‡ƒ” Šſ–‹–އƀś
ɰɑɑɑǢȢțȖȤȔȭȔșȠȥȣȜȥȢȞȞȢȤȦșȚșȝřȥȢȥȦȢȳȭȜȩȜțȦȤșȩȱȟșȠșȡȦȢȖ
ɨɥſȜȘșȡȦȜȨȜȞȔȦȢȤřțȔȗȢȟȢȖȢȞřȢȣȜȥȔȡȜșƀřȞȢȦȢȤȯșȢȣȜȥȯȖȔȲȦȖȜȘșȢȤȢȟȜȞȜř
ɨɨȫȰȜțȔȗȢȟȢȖȞȜȫȔȥȦȜȫȡȢȥȢȢȦȖșȦȥȦȖȧȲȦțȡȔȫșȡȜȲȣșȤșȠșȡȡȢȝ–‹–އŜɑɑɑ
ɨɩ•‡ƒ” Šɏ—”ŽʰɑŠ––’•śŵŵƒ” Š‹˜‡Ŝ‘”‰ŵƒ†˜ƒ ‡†•‡ƒ” ŠŜ’Š’ɑ
ɨɪ’ƒ”ƒ•ʰƇ
ɨɫɑ“ɑśɑ–‹–އśſƇƈƀ‡†‹ƒ–›’‡śſ‘˜‹‡•ƀɑŜˆ‘”ƒ–ſ–‹–އƀř
ɨɬɑˆŽɑśɑ‹†‡–‹ˆ‹‡”ř–‹–އř†‡• ”‹’–‹‘ɑř
ɨɭɑ‘—–’—–ɑśɑŒ•‘ɑř
ɨɮɑ”‘™•ɑśɨɥř
ɨɯɑ’ƒ‰‡ɑśɨř
ɨɰƈ
ɩɥ”‡•’ʰ”‡“—‡•–•Ŝ‰‡–ſ•‡ƒ” Šɏ—”Žř’ƒ”ƒ•ʰ’ƒ”ƒ•ƀ
ɩɨ†ƒ–ƒʰ”‡•’ŜŒ•‘ſƀ
ɩɩ†‘ •ʰƃſ†‘ ƃɑ‹†‡–‹ˆ‹‡”ɑƄř†‘ ƃɑ–‹–އɑƄř†‘ ƃɑ†‡• ”‹’–‹‘ɑƄƀ
ɩɪˆ‘”†‘ ‹†ƒ–ƒƃɑ”‡•’‘•‡ɑƄƃɑ†‘ •ɑƄƄ
ɩɫ”‡–—”†‘ •
ɩɬ
ɩɭ†‡ˆ Š‘‘•‡ſ†‘ •ƀś
ɩɮɑɑɑǢȯȖșȘșȠȡȢȠșȤȥȦȤȢȞȜřțȔȗȢȟȢȖȢȞȜȫȔȥȦȜȫȡȢșȢȣȜȥȔȡȜșȘȟȳ
ɩɯȞȔȚȘȢȗȢȞȢȤȦșȚȔȜțȥȣȜȥȞȔś†‘ •ŜǯȢțȖȢȟȜȠȣȢȟȰțȢȖȔȦșȟȲȖȯȕȤȔȦȰ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ɩɰȡȢȠșȤȥȦȤȢȞȜŜǥȥȟȜȢȡȞȢȤȤșȞȦșȡřȖșȤȡșȠȣșȤȖȯȝȱȟșȠșȡȦȖȯȕȤȔȡȡȢȗȢ
ɪɥȞȢȤȦșȚȔſɑȜȘșȡȦȜȨȜȞȔȦȢȤɑƀŜǢȣȤȢȦȜȖȡȢȠȥȟȧȫȔșȖșȤȡșȠ‘‡Ŝɑɑɑ
ɪɨŽƒ•–ʰއſ†‘ •ƀŞɨ
ɪɩˆ‘”—ř†‘ ‹‡—‡”ƒ–‡ſ†‘ •ƀś
ɪɪ’”‹–ſˆɑƇ—ƈśſƇ†‘ ƃɨƄƈƀƇ†‘ ƃɩƄƃśɪɥƄƈŜŜŜɑƀ
ɪɫ‹†‡šʰ‹’—–ſˆɑŠ‹ Š™‘—ކ›‘—Ž‹‡–‘•‡‡ſɥ–‘ƇŽƒ•–ƈƀţɑƀ
ɪɬ–”›ś
ɪɭ”‡–—”†‘ •ƃ‹–ſ‹†‡šƀƄƃɥƄ
ɪɮ‡š ‡’–ś
ɪɯ”‡–—”‘‡
ɪɰ
ɫɥ†‡ˆ†‹•’Žƒ›ſ‹†‡–‹ˆ‹‡”ƀś
ɫɨɑɑɑǮȦȢȕȤȔțȜȠȖȜȘșȢȜțȔȤȩȜȖȔȖȕȤȔȧțșȤșȥȣȢȠȢȭȰȲȜȘșȡȦȜȨȜȞȔȦȢȤȔɑɑɑ
ɫɩ†‡–ƒ‹Ž•ɏ—”ŽʰɑŠ––’•śŵŵƒ” Š‹˜‡Ŝ‘”‰ŵ†‡–ƒ‹Ž•ŵƇƈɑŜˆ‘”ƒ–ſ‹†‡–‹ˆ‹‡”ƀ
ɫɪ’”‹–ſɑ‘ƒ†‹‰ɑř†‡–ƒ‹Ž•ɏ—”Žƀ
ɫɫ™‡„„”‘™•‡”Ŝ‘’‡ſ†‡–ƒ‹Ž•ɏ—”Žƀ
ɫɬ
ɫɭ†‡ˆƒ‹ſ–‹–އƀś
ɫɮɑɑɑǭȔȝȘșȠȖȥșȨȜȟȰȠȯřȫȰșȡȔțȖȔȡȜșȥȢȢȦȖșȦȥȦȖȧșȦțȡȔȫșȡȜȲȣșȤșȠșȡȡȢȝ
ɫɯś–‹–އŜdzțȡȔșȠȖȯȕȢȤȣȢȟȰțȢȖȔȦșȟȳȜȢȦȢȕȤȔțȜȠșȗȢȖȕȤȔȧțșȤșŜɑɑɑ
ɫɰ‹†‡–‹ˆ‹‡”•ʰ•‡ƒ” Šſ–‹–އƀ
ɬɥ‹ˆ‹†‡–‹ˆ‹‡”•ś
ɬɨ‹†‡–‹ˆ‹‡”ʰ Š‘‘•‡ſ‹†‡–‹ˆ‹‡”•ƀ
ɬɩ‹ˆ‹†‡–‹ˆ‹‡”ś
ɬɪ†‹•’Žƒ›ſ‹†‡–‹ˆ‹‡”ƀ
ɬɫ‡Ž•‡ś
ɬɬ’”‹–ſɑ‘–Š‹‰•‡Ž‡ –‡†ɑƀ
ɬɭ‡Ž•‡ś
ɬɮ’”‹–ſɑ‘–Š‹‰ˆ‘—†ˆ‘”ɑř–‹–އƀ
ɬɯ
ɬɰ‹ˆɏɏƒ‡ɏɏʰʰɑɏɏƒ‹ɏɏɑś
ɭɥƒ‹ſ•›•Ŝƒ”‰˜ƃɨƄƀ

Вот что я получил, запустив эту программу и выполнив поиск для буквосочета-
ния eegah1:
ɛpython [Link] eegah
ɥśſ‡‰ƒŠƀ ”‘ „śЋއ†”‹˜‹‰–Š”‘ŜŜŜ
ɨśſ‡‰ƒŠƀŠ‹•ˆ‹ŽŠƒ•ˆƒŽŽ‡‹–‘–ЇŜŜŜ
ɩśſ‡‰ƒŠƀ ƒ˜‡ƒ‹•†‹• ‘˜‡”‡†‘—–‹ŜŜŜ
ɪśſ‡‰ƒŠſɨɰɭɩƀƀЋއ†”‹˜‹‰–Š”‘—‰Š–Ї†‡•‡ŜŜŜ
ɫśſ –ɐ•ɑ‡‰ƒŠɑރ”–ɩƀƒ‹––‹ŽŽ›‘—•‡‡Š‘™–Š‹•‡†ŜŜŜ
ɬśſ  –”ƒ‹Ž‡”ƀЇ‹ˆƒ‘—•‘†‡”Ş†ƒ› ƒ˜‡ƒŜŜŜ
ɭśſ –ɐ•ɑ‡‰ƒŠɑރ”–ɨƀ‘—– ‘”‡‡‘Ž•Šƒ”‡••‘‡ŜŜŜ
ɮśſ‹†‹‰Š–‘˜‹‡•Š‘™ś‡‡‰ƒŠƀ” Š ƒŽŽ ”ŜŜŜ
Š‹ Š™‘—ކ›‘—Ž‹‡–‘•‡‡ſɥ–‘ɮƀţɩ
‘ƒ†‹‰Š––’•śŵŵƒ” Š‹˜‡Ŝ‘”‰ŵ†‡–ƒ‹Ž•ŵ‡‰ƒŠ

1
В этом фильме Ричард Кил снялся в роли пещерного человека за много лет до того, как
сыграл Челюсти в фильме о Джеймсе Бонде.
ǫȓȈȊȈǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț  

Он отобразил страницу в моем браузере, она готова к запуску (рис. 18.2).

ǸȐșǸȍȏțȓȤȚȈȚȗȖȐșȒȈȜȐȓȤȔȈ

ǿȐȚȈȑȚȍȌȈȓȍȍ
Следующая глава чрезвычайно практична, в ней рассматриваются основы совре-
менной разработки на Python. Узнайте же, как стать хладнокровным питонщиком.

ǻȗȘȈȎȕȍȕȐȧ
18.1. Если вы еще не установили Flask, то сделайте сейчас. Это также позволит
установить ™‡”œ‡—‰, Œ‹Œƒɩ и, возможно, другие пакеты.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

18.2. Создайте скелет сайта с помощью веб-сервера Flask. Убедитесь, что сервер
начинает свою работу по адресу ‘ ƒŽŠ‘•– на стандартном порте 5000. Если
ваш компьютер уже использует этот порт для чего-то еще, то воспользуйтесь
другим портом.
18.3. Добавьте функцию Š‘‡ſƀ для обработки запросов к главной странице. Пусть
она возвращает строку –ɐ• ƒŽ‹˜‡Š.
18.4. Создайте шаблон для Œ‹Œƒɩ, который называется Š‘‡ŜŠ–Ž и содержит сле-
дующий контент:
ʳŠ–Žʴ
ʳЇƒ†ʴ
ʳ–‹–އʴ –ɐ•ƒŽ‹˜‡Šʳŵ–‹–އʴ
ʳ„‘†›ʴ
ɐ‘ˆ ‘—”•‡”‡ˆ‡””‹‰–‘ƇƇ–Š‹‰ƈƈř™Š‹ Š‹•ƇƇЇ‹‰Š–ƈƈˆ‡‡––ƒŽŽƒ†
ƇƇ ‘Ž‘”ƈƈŜ
ʳŵ„‘†›ʴ
ʳŵŠ–Žʴ

18.5. Модифицируйте функцию Š‘‡ſƀ вашего сервера, чтобы она использовала


шаблон Š‘‡ŜŠ–Ž. Передайте ей три параметра для команды : thing, height
и ‘Ž‘”.
ƋƓƈƊƈ
ǩȣȚȤȗȐȚȖȕȡȐȒȖȔ

Всегда хотели отправиться во времени назад, чтобы


сразиться с более молодой версией себя? Карьера
в разработке ПО — то, что вам нужно!

Эллиот Лох

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

ǶȗȘȖȋȘȈȔȔȐȘȖȊȈȕȐȐ
Для начала я хочу сказать пару слов о программировании с высоты личного
опыта.
Я начинал свою деятельность в области науки и обучился программированию,
чтобы анализировать и отображать экспериментальные данные. Мне казалось, про-
граммирование окажется похожим на бухгалтерский учет: будет точным и скучным.
Но я удивился, когда понял, что мне это нравится. Одними из интересных для меня
аспектов стали логическая — программирование похоже на складывание пазлов —
и творческая составляющие. Вы должны написать программу так, чтобы получить
правильные результаты, но вольны написать ее тем способом, который вам больше
нравится. Такое соотношение использования левого и правого полушарий мозга
необычно.
Начав свою карьеру в программировании, я также узнал, что в этой области су-
ществует множество ниш для разных задач и типов людей. Вы можете погрузиться
в область компьютерной графики, операционных систем, бизнес-приложений
и даже науки.
Если вы программист, то у вас мог быть похожий опыт. В противном случае
можете попробовать начать программировать, чтобы посмотреть, подходит ли это
вам или хотя бы помогает ли решить какие-либо задачи. Как я уже писал в данной
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

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

ǰȡȍȔȒȖȌȕȈ3\WKRQ
Когда вам нужно написать некий код, самым быстрым решением является кража…
из тех источников, которые позволяют это делать.
Стандартная библиотека Python (KWWSGRFVS\WKRQRUJOLEUDU\) широка, глубока
и довольно понятна.
Как и в случае с залами славы в спорте, модулю требуется время, чтобы попасть
в стандартную библиотеку. Новые пакеты появляются довольно часто, и на про-
тяжении этой книги я отмечал те из них, которые либо делают что-то новое, либо
улучшают что-то старое. Python поставляется сразу «с батарейками», но иногда вам
нужна батарейка другого вида.
Так где же, помимо стандартной библиотеки, следует искать хороший код
Python?
Первое место, на которое вы должны обратить внимание, — это каталог пакетов
Python (Python Package Index, PyPI) (KWWSVS\SLRUJ). Ранее носивший имя Cheese
Shop в честь скетча Monty Python, данный сайт постоянно обновляется — на момент
написания этой книги он содержит более 113 000 пакетов. Когда вы используете
pip (см. следующий раздел), он ищет пакет на сайте PyPI. Основная страница PyPI
показывает самые свежие пакеты. Вы также можете выполнить прямой поиск, вве-
дя что-нибудь в строку поиска посередине главной страницы PyPI. Например, по
ключевому слову genealogy определяется 21 совпадение, а по слову ‘˜‹‡• — 528.
Еще один популярный репозиторий — GitHub. Взгляните, какие пакеты Python
популярны в данный момент (KWWSVJLWKXEFRPWUHQGLQJ"O S\WKRQ).
Сайт Popular Python recipes (KWWSELWO\SRSXODUUHFLSHV) содержит более 4000 ко-
ротких программ Python на любую тему.

ǻșȚȈȕȖȊȒȈȗȈȒȍȚȖȊ
Существует множество способов установить пакет Python.
‰Использовать pip, если есть такая возможность. На данный момент это самый
распространенный метод установки. С помощью pip вы можете установить
большинство пакетов.
‰Задействовать pipenv, в нем объединены pip и virtualenv.
‰Иногда вы можете применить менеджер пакетов своей операционной системы.
‰Использовать ‘†ƒ, если вы выполняете большое количество научной работы
и хотите задействовать дистрибутив Python, который называется Anaconda.
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

Прочтите раздел «Устанавливаем Anaconda» приложения Б на с. 536 для полу-


чения более подробной информации.
‰С помощью исходного кода.
Если вам нужно установить несколько пакетов из одной области, то вы можете
обнаружить дистрибутив, который уже содержит их. Например, глава 22 позволяет
попробовать поработать с несколькими числовыми и научными программами, кото-
рые было бы трудно устанавливать вручную, но все они включены в дистрибутивы,
такие как Anaconda.

SLS
Использование пакетов Python имело несколько ограничений. Более ранний инстру-
мент для установки ‡ƒ•›ɏ‹•–ƒŽŽ был заменен pip, но ни один из них не находился
в стандартном пакете Python. Если мы должны устанавливать пакеты с помощью
pip, то где же его взять? Начиная с Python 3.4, pip наконец-то включили в стандарт-
ный пакет Python, чтобы избежать подобного экзистенциального кризиса. Если вы
работаете с более ранней версией Python и у вас не установлен pip, то можете скачать
его, перейдя по ссылке KWWSZZZSLSLQVWDOOHURUJ.
Простейший вариант использования pip — установка последней версии одного
пакета с помощью следующей команды:
ɛpip install flask

Вы увидите детали происходящего, просто чтобы не подумали, будто pip ленится:


скачивание, запуск •‡–—’Ŝ’›, установка файлов на диск и др.
Вы также можете дать pip команду установить определенную версию:
ɛpip install flask==0.9.0

Или минимальную версию (это полезно, когда некая особенность, без которой
вы жить не можете, появляется только в определенной версии):
ɛ’‹’‹•–ƒŽŽɐˆŽƒ•ʶɥŜɰŜɥɐ

В предыдущем примере одинарные кавычки не дают оболочке интерпре-


тировать символ ʴ, чтобы перенаправить поток выходной информации в файл
с именем ʰɥŜɰŜɥ.
Если вы хотите установить более одного пакета, то можете воспользоваться фай-
лом требований (KWWSELWO\SLSUHTXLUH). Несмотря на обилие вариантов, простейший
вариант использования — список пакетов, в каждой строке по одному, опционально
содержащий точные или относительные версии:
ɛpip -r [Link]

Например, файл ”‡“—‹”‡‡–•Ŝ–š– может содержать следующее:


ˆŽƒ•ʰʰɥŜɰŜɥ
†Œƒ‰‘
’•› ‘’‰ɩ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Еще несколько примеров:


‰установите последнюю версию: pip install ŞŞ—’‰”ƒ†‡ ȣȔȞșȦ;
‰удалите пакет: pip uninstall ȣȔȞșȦ.

YLUWXDOHQY
Стандартный способ установки сторонних пакетов — это использование pip
и virtualenv . Я покажу, как устанавливать virtualenv , в разделе «Установка
virtualenv» приложения Б на с. 535.
Виртуальное окружение — это обычный каталог, содержащий интерпретатор
Python, несколько других программ наподобие pip, а также некие пакеты. Вы мо-
жете активизировать его, запустив сценарий оболочки, который лежит в каталоге
bin этого виртуального окружения. Это изменит значение переменной окружения
ɛ , и теперь ваша оболочка будет знать, где искать программы. Активизируя
виртуальное окружение, вы помещаете его каталог bin перед остальными катало-
гами в переменной ɛ . В результате, когда вы введете такие команды, как pip
или python, ваша оболочка сначала найдет те программы, которые располагаются
в вашем виртуальном окружении, а не те, что находятся в системных каталогах на-
подобие ŵ„‹, ŵ—•”ŵ„‹ или ŵ—•”ŵŽ‘ ƒŽŵ„‹.
Вы не захотите устанавливать программы в эти системные каталоги в любом
случае, поскольку:
‰у вас нет разрешения на запись в них;
‰даже если бы вы могли выполнить запись, переписывание стандартных программ
вашей системы (такой как python) может вызвать проблемы.

SLSHQY
Недавно появился пакет pipenv (KWWSVJLWKXEFRPS\SDSLSHQY), в котором объединены
уже знакомые нам pip и virtualenv. Вдобавок он решает проблемы с зависимостями,
которые могут возникнуть при использовании pip в разных окружениях (например,
на локальной машине, а также на этапе подготовки и развертывания):
ɛpip install pipenv

Использовать этот пакет рекомендует Python Packaging Authority ( KWWSV


ZZZS\SDLR) — рабочая группа, которая старается улучшить процесс взаимодействия
с пакетами в Python. Эта группа не занимается разработкой ядра Python, поэтому
pipenv не входит в состав стандартной библиотеки.

ǴȍȕȍȌȎȍȘȗȈȒȍȚȖȊ
Операционная система macOS от Apple содержит сторонние менеджеры пакетов
homebrew (brew) (KWWSEUHZVK) и ports (KWWSZZZPDFSRUWVRUJ). Они работают при-
мерно так же, как и pip, но не ограничены пакетами Python.
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

В операционных системах семейства Linux имеется отдельный менеджер пакетов


для каждого дистрибутива. Самые популярные — ƒ’–މ‡–, ›—, †’‰ и œ›’’‡”.
В операционных системах семейства Windows имеются Windows Installer и фай-
лы пакетов с суффиксом Ŝ•‹. Если вы устанавливали Python для Windows, то,
скорее всего, файл пакета имел формат MSI.

ǻșȚȈȕȖȊȒȈȐȏȐșȝȖȌȕȖȋȖȒȖȌȈ
Иногда пакет еще совсем новый или же автор просто не сделал его доступным через
pip. Чтобы создать пакет, вы, как правило, делаете следующее:

‰загружаете код;
‰извлекаете файлы с помощью œ‹’, tar или другого подходящего инструмента,
если они заархивированы или сжаты;
‰запускаете команду python •‡–—’Ŝ’› install в каталоге, который содержит файл
•‡–—’Ŝ’›.

DzȈȒȊșȍȋȌȈȊȈȔșȓȍȌțȍȚȉȣȚȤȖșȚȖȘȖȎȕȣȔȐșȚȍȔȟȚȖȊȣșȒȈȟȐȊȈȍȚȍȐțșȚȈȕȈȊȓȐ
ȊȈȍȚȍǪȗȘȖȋȘȈȔȔȈȝȕȈȗȐșȈȕȕȣȝȕȈ3\WKRQȊȘȍȌȖȕȖșȕȣȑȒȖȌșȗȘȧȚȈȚȤȚȘțȌȕȍȍ
ȗȖșȒȖȓȤȒțȖȕȐȗȘȍȌșȚȈȊȓȧȦȚșȖȉȖȑȟȐȚȈȉȍȓȤȕȣȑȚȍȒșȚȕȖȐȕȖȋȌȈȥȚȖșȓțȟȈȍȚșȧ

ǰȕȚȍȋȘȐȘȖȊȈȕȕȣȍșȘȍȌȣȘȈȏȘȈȉȖȚȒȐ
Для написания программ, представленных в данной книге, я использовал текстовый
интерфейс, но это не значит, что вы должны запускать весь код в консоли или тек-
стовом окне. Существует множество бесплатных и коммерческих интегрированных
сред разработки (Integrated Development Environment, IDE), которые являются гра-
фическими интерфейсами, поддерживающими такие инструменты, как текстовые
редакторы, отладчики, поиск по библиотеке и т. д.

,'/(
IDLE (KWWSELWO\S\LGOH) — это IDE, предназначенная только для Python, которая
поставляется со стандартным дистрибутивом. Она основана на интерфейсе tkinter
и имеет простой GUI.

3\&KDUP
PyCharm (KWWSZZZMHWEUDLQVFRPS\FKDUP) — это относительно новая графическая
IDE, имеющая множество возможностей. Версия для сообщества бесплатна, также
вы можете получить бесплатную лицензию для профессиональной версии, чтобы ис-
пользовать ее для обучения или работы над проектом с открытым исходным кодом.
На рис. 19.1 показан ее начальный экран.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǸȐșǵȈȟȈȓȤȕȣȑȥȒȘȈȕ3\&KDUP

,3\WKRQ
IPython (KWWSLS\WKRQRUJ) начал свой путь как улучшенная терминальная (тексто-
вая) IDE для Python, но затем эволюционировал и приобрел графический интер-
фейс, похожий на блокнот. Он интегрировал множество пакетов, рассмотренных
в этой книге, включая Matplotlib и NumPy, и стал популярным инструментом для
научных вычислений.
Вы можете установить базовую текстовую версию (как уже догадались) с по-
мощью команды pip install ipython. Запустив ее, вы увидите нечто похожее на
следующий блок:
ɛipython
›–Š‘ɪŜɮŜɪſ˜ɪŜɮŜɪś‡ˆɫ‡ ɭ‡†ɨɩřƒ”ɩɬɩɥɨɰřɨɭśɪɰśɥɥƀ
›’‡ɐ ‘’›”‹‰Š–ɐřɐ ”‡†‹–•ɐ‘”ɐŽ‹ ‡•‡ɐˆ‘”‘”‡‹ˆ‘”ƒ–‹‘
›–Š‘ɮŜɪŜɥŞŞ‡Šƒ ‡† –‡”ƒ –‹˜‡›–Š‘Ŝ›’‡ɐţɐˆ‘”ЇޒŜ

ƃɨƄś

Как вам известно, стандартный интерпретатор Python использует приглашения


ʴʴʴ и ŜŜŜ, чтобы указать, где и когда вам нужно вводить код. IPython отслеживает
все, что вы вводите, в списке, который называется , а все выходные данные —
в списке —–. Каждый элемент списка  может быть длиннее одной строки, поэто-
му отправлять свои данные следует, удерживая нажатой клавишу 6KLIW и нажимая
клавишу (QWHU.
Рассмотрим однострочный пример:
ƃɨƄśprint("Hello? World?")
‡ŽŽ‘ţ‘”ކţ

ƃɩƄś
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

Элементы в списках  и —– нумеруются автоматически, позволяя получить


доступ ко всем входным и выходным данным.
Если после имени переменной вы введете знак ţ, то IPython подскажет вам ее
тип, значение, способы создания переменной подобного типа, а также некоторые
пояснения:
ƃɫƄśanswer = 42

ƃɬƄśanswer?

›’‡ś‹–
–”‹‰ ‘”śɫɩ
‘ •–”‹‰ś
‹–ſšʰɥƀŞʴ‹–‡‰‡”
‹–ſšř„ƒ•‡ʰɨɥƀŞʴ‹–‡‰‡”

‘˜‡”–ƒ—„‡”‘”•–”‹‰–‘ƒ‹–‡‰‡”ř‘””‡–—”ɥ‹ˆ‘ƒ”‰—‡–•
ƒ”‡‰‹˜‡Ŝ ˆš‹•ƒ—„‡”ř”‡–—”šŜɏɏ‹–ɏɏſƀŜ ‘”ˆŽ‘ƒ–‹‰’‘‹–—„‡”•ř
–Š‹•–”— ƒ–‡•–‘™ƒ”†•œ‡”‘Ŝ

ˆš‹•‘–ƒ—„‡”‘”‹ˆ„ƒ•‡‹•‰‹˜‡ř–Їš—•–„‡ƒ•–”‹‰ř
„›–‡•ř‘”„›–‡ƒ””ƒ›‹•–ƒ ‡”‡’”‡•‡–‹‰ƒ‹–‡‰‡”Ž‹–‡”ƒŽ‹–Ї
‰‹˜‡„ƒ•‡ŜЇŽ‹–‡”ƒŽ ƒ„‡’”‡ ‡†‡†„›ɐʫɐ‘”ɐŞɐƒ†„‡•—””‘—†‡†
„›™Š‹–‡•’ƒ ‡ŜЇ„ƒ•‡†‡ˆƒ—Ž–•–‘ɨɥŜƒŽ‹†„ƒ•‡•ƒ”‡ɥƒ†ɩŞɪɭŜ
ƒ•‡ɥ‡ƒ•–‘‹–‡”’”‡––Ї„ƒ•‡ˆ”‘–Ї•–”‹‰ƒ•ƒ‹–‡‰‡”Ž‹–‡”ƒŽŜ
ʴʴʴ‹–ſɐɥ„ɨɥɥɐř„ƒ•‡ʰɥƀ
ɫ

Поиск по имени — это популярная возможность такой IDE, как IPython. Если
вы нажмете клавишу 7DE после того, как введете некие символы, то IPython пока-
жет все переменные, ключевые слова и функции, начинающиеся с этих символов.
Определим некоторые переменные, а затем найдем все, что начинается с буквы f:
ƃɭƄśfee = 1

ƃɮƄśfie = 2

ƃɯƄśfo = 3

ƃɰƄśfum = 4

ƃɨɥƄśftab
ʩʩˆ‹Ž‡ˆ‹‡ˆ‹ƒŽŽ›ˆ‘ˆ‘”ƒ–ˆ”‘œ‡•‡–
ˆ‡‡ˆ‹Ž–‡”ˆŽ‘ƒ–ˆ‘”ˆ”‘ˆ—

Если вы введете fe, а затем нажмете клавишу 7DE, то увидите только переменную
fee, единственную переменную в этой программе, которая начинается с буквосоче-
тания fe:
ƃɨɨƄśfee
—–ƃɨɨƄśɨ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

У IPython много других возможностей. Взгляните на это руководство (KWWSV


RUHLOO\3,Y9.), чтобы получить представление о них.

-XS\WHU1RWHERRN
Jupyter (KWWSVMXS\WHURUJ) — это эволюционировавший IPython. В его названии объ-
единены языки Julia, Python и R — все они популярны в области науки о данных
и научных вычислений. Jupyter Notebooks — современный способ разработки и пу-
бликации вашего кода, содержащий документацию к этим языкам.
Если вы хотите исследовать его, не устанавливая на свой компьютер, то можете
запустить его (KWWSVMXS\WHURUJWU\) в браузере.
Чтобы установить Jupyter Notebook локально, введите команду pip install
Œ—’›–‡”. Запустите его с помощью Œ—’›–‡” ‘–‡„‘‘.

-XS\WHU/DE
JupyterLab — это Jupyter Notebook нового поколения, в конечном счете он заменит
старую версию. Как и в случае с Notebook, вы сначала можете попробовать (KWWSV
MXS\WHURUJWU\) JupyterLab в своем браузере. Установить его локально можно с помо-
щью команды pip install Œ—’›–‡”Žƒ„, а запустить — с помощью Œ—’›–‡” lab.

ǰȔȍȕȖȊȈȕȐȍȐȌȖȒțȔȍȕȚȐȘȖȊȈȕȐȍ
Вы не вспомните написанное. Иногда случается так, что я смотрю на код, даже на
тот, который написал недавно, и не понимаю, откуда он взялся. Именно поэтому
полезно документировать собственный код. Это могут быть комментарии; также
полезно давать переменным, функциям, модулям и классам осмысленные имена.
Однако не перегибайте палку, как в этом примере:
ʴʴʴɤǧȘșȥȰȳȥȢȕȜȤȔȲȥȰȣȤȜȥȖȢȜȦȰțȡȔȫșȡȜșɨɥȣșȤșȠșȡȡȢȝɑ—ɑś
ŜŜŜ—ʰɨɥ
ʴʴʴɤǭȔȘșȲȥȰřȱȦȢȥȤȔȕȢȦȔȟȢŜ
ŜŜŜ’”‹–ſ—ƀ
ɨɥ
ʴʴʴɤǴȧȩŜ

Вместо этого напишите, почему вы присвоили значение ɨɥ. Укажите, почему


дали переменной именно имя —. Если вы пишете почтенный преобразователь
температуры от шкалы Фаренгейта к шкале Цельсия, то вам следует назвать пере-
менные так, чтобы было понятно их функционирование, а не производить на свет
кучу волшебного кода. Небольшой тест также не повредит (пример 19.1):

ǷȘȐȔȍȘIWRFS\
†‡ˆˆ–‘ ſˆɏ–‡’ƀś
ɑ‘˜‡”– ƒŠ”‡Š‡‹––‡’‡”ƒ–—”‡ʳˆɏ–‡’ʴ–‘‡Ž•‹—•ƒ†”‡–—”‹–Ŝɑ
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

ˆɏ„‘‹Žɏ–‡’ʰɩɨɩŜɥ
ˆɏˆ”‡‡œ‡ɏ–‡’ʰɪɩŜɥ
 ɏ„‘‹Žɏ–‡’ʰɨɥɥŜɥ
 ɏˆ”‡‡œ‡ɏ–‡’ʰɥŜɥ
ˆɏ”ƒ‰‡ʰˆɏ„‘‹Žɏ–‡’ވɏˆ”‡‡œ‡ɏ–‡’
 ɏ”ƒ‰‡ʰ ɏ„‘‹Žɏ–‡’Ş ɏˆ”‡‡œ‡ɏ–‡’
ˆɏ ɏ”ƒ–‹‘ʰ ɏ”ƒ‰‡ŵˆɏ”ƒ‰‡
 ɏ–‡’ʰſˆɏ–‡’ވɏˆ”‡‡œ‡ɏ–‡’ƀƋˆɏ ɏ”ƒ–‹‘ʫ ɏˆ”‡‡œ‡ɏ–‡’
”‡–—” ɏ–‡’

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
ˆ‘”ˆɏ–‡’‹ƃŞɫɥŜɥřɥŜɥřɪɩŜɥřɨɥɥŜɥřɩɨɩŜɥƄś
 ɏ–‡’ʰˆ–‘ ſˆɏ–‡’ƀ
’”‹–ſɐʩˆ ʰʴʩˆɐʩſˆɏ–‡’ř ɏ–‡’ƀƀ

Запустим тесты:
ɛpython [Link]

ŞɫɥŜɥɥɥɥɥɥ ʰʴŞɫɥŜɥɥɥɥɥɥ
ɥŜɥɥɥɥɥɥ ʰʴŞɨɮŜɮɮɮɮɮɯ
ɪɩŜɥɥɥɥɥɥ ʰʴɥŜɥɥɥɥɥɥ
ɨɥɥŜɥɥɥɥɥɥ ʰʴɪɮŜɮɮɮɮɮɯ
ɩɨɩŜɥɥɥɥɥɥ ʰʴɨɥɥŜɥɥɥɥɥɥ

Мы можем сделать как минимум два улучшения.


‰В языке Python нет констант, но таблица стилей PEP-8 рекомендует (KWWS
ELWO\SHSFRQVWDQW) использовать прописные буквы и подчеркивания (например,
ɏ) при именовании переменных, которые должны считаться константами.
Переименуем эти «константные» переменные в нашем примере.
‰Поскольку мы заранее вычислили значения, основываясь на константах, пере-
несем их в верхнюю часть модуля. Таким образом, они будут рассчитываться
только один раз при каждом вызове функции ˆ–‘ ſƀ.
В примере 19.2 показан переделанный код.

ǷȘȐȔȍȘIWRFS\
ɏ ɏʰɩɨɩŜɥ
ɏ ɏʰɪɩŜɥ
ɏ ɏʰɨɥɥŜɥ
ɏ ɏʰɥŜɥ
ɏ ʰ ɏ ɏŞ ɏ ɏ
ɏ ʰɏ ɏŞɏ ɏ
ɏɏ ʰɏ ŵ ɏ 
†‡ˆˆ–‘ ſˆɏ–‡’ƀś
ɑ‘˜‡”– ƒŠ”‡Š‡‹––‡’‡”ƒ–—”‡ʳˆɏ–‡’ʴ–‘‡Ž•‹—•ƒ†”‡–—”‹–Ŝɑ
 ɏ–‡’ʰſˆɏ–‡’Ş ɏ ɏƀƋ ɏɏ ʫɏ ɏ
”‡–—” ɏ–‡’
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
ˆ‘”ˆɏ–‡’‹ƃŞɫɥŜɥřɥŜɥřɪɩŜɥřɨɥɥŜɥřɩɨɩŜɥƄś
 ɏ–‡’ʰˆ–‘ ſˆɏ–‡’ƀ
’”‹–ſɐʩˆ ʰʴʩˆɐʩſˆɏ–‡’ř ɏ–‡’ƀƀ

ǬȖȉȈȊȓȍȕȐȍȗȖȌșȒȈȏȖȒȚȐȗȖȊ
Статические языки требуют от вас определять типы переменных, они могут отлавли-
вать ошибки на этапе компиляции. Как вам известно, Python так не делает, вы можете
столкнуться с багом только при запуске кода. Переменные в Python — это имена, они
лишь ссылаются на реальные объекты. Объекты имеют строго определенный тип, но
имя может указывать на разные объекты в различные моменты времени.
В реальном коде (на Python и других языках) имя, как правило, ссылается на
конкретный объект. Было бы полезно, по крайней мере в документации, если бы мы
могли оставлять аннотации (к объектам, возвращаемым значениям функций и т. д.),
указывавшие бы на ожидаемый тип объекта, на который они ссылаются. В таком
случае разработчикам не пришлось бы просматривать большое количество кода,
чтобы увидеть, как переменная должна вести себя.
В Python версий 3.х для решения этой проблемы были добавлены подсказки
типов (или аннотации типов). Ими пользоваться не обязательно, они не задают
жесткий тип переменной. Подсказки типов предназначены для того, чтобы помочь
разработчикам, привыкшим к статическим языкам, понять, где должны быть объ-
явлены типы переменных.
Подсказка для функции, которая преобразует строку в число, может выглядеть
так:
†‡ˆ—ɏ–‘ɏ•–”ſ—ś‹–ƀŞʴ•–”ś
”‡–—”•–”ſ—ƀ

Это лишь подсказки, они не меняют способ работы Python. Они нужны для
документирования, однако люди придумывают и другое применение. Например,
веб-фреймворк FastAPI (KWWSVIDVWDSLWLDQJRORFRP) использует подсказки для того,
чтобы сгенерировать веб-документацию, а также лайв-формы для тестирования.

ǺȍșȚȐȘȖȊȈȕȐȍȒȖȌȈ
Возможно, вы уже знаете, однако на всякий случай напомню: даже тривиальные
изменения в коде могут сломать вашу программу. В Python недостает проверки
типов, присущей статическим языкам, что упрощает некоторые аспекты програм-
мирования, но повышает вероятность получить нежелательные результаты. Тести-
рование — это важно.
Самый простой способ протестировать программы, написанные на Python, —
добавить операторы ’”‹–ſƀ. Read-Evaluate-Print Loop (REPL) интерактивного
интерпретатора позволяет быстро изменять код и тестировать изменения. Однако
в производственном коде операторы ’”‹–ſƀ использовать не стоит, поэтому вам
нужно помнить о том, что их все следует удалять.
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

ǷȘȖȋȘȈȔȔȣS\OLQWS\IODNHVIODNHȐȓȐ3(3
Следующий шаг перед созданием настоящих программ для тестирования — исполь-
зование контролера кода Python. Самыми популярными являются pylint (KWWS
ZZZS\OLQWRUJ) и ’›ˆŽƒ‡• (KWWSELWO\S\IODNHV). Вы можете установить любой из них
(или даже оба) с помощью pip:
ɛpip install pylint
ɛpip install pyflakes

Они проверяют на наличие реальных ошибок в коде (например, обращения


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

ǷȘȐȔȍȘVW\OHS\
ƒʰɨ
„ʰɩ
’”‹–ſƒƀ
’”‹–ſ„ƀ
’”‹–ſ ƀ

Так выглядит выходная информация от pylint:


ɛpylint [Link]
‘ ‘ˆ‹‰ˆ‹Ž‡ˆ‘—†ř—•‹‰†‡ˆƒ—Ž– ‘ˆ‹‰—”ƒ–‹‘
****ƋƋƋƋƋƋƋƋƋ‘†—އ•–›Ž‡ɨ
śɨřɥś‹••‹‰†‘ •–”‹‰
śɨřɥś ˜ƒŽ‹†ƒ‡ɑƒɑˆ‘”–›’‡ ‘•–ƒ–
ſ•Š‘—ކƒ– ŠſſƃŞɏƄƃŞɥŞɰɏƄƋƀŶſɏɏŜƋɏɏƀƀɛƀ
śɩřɥś ˜ƒŽ‹†ƒ‡ɑ„ɑˆ‘”–›’‡ ‘•–ƒ–
ſ•Š‘—ކƒ– ŠſſƃŞɏƄƃŞɥŞɰɏƄƋƀŶſɏɏŜƋɏɏƀƀɛƀ
śɬřɭś†‡ˆ‹‡†˜ƒ”‹ƒ„އɐ ɐ

Если пролистать дальше, к разделу Ž‘„ƒŽ evaluation, то можно увидеть наш счет
(10.0 — это высший балл):
‘—” ‘†‡Šƒ•„‡‡”ƒ–‡†ƒ–ŞɪŜɪɪŵɨɥ

Ой! Сначала исправим ошибку. Строка вывода pylint, начинающаяся с , ука-


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

ǷȘȐȔȍȘVW\OHS\
ƒʰɨ
„ʰɩ
ʰɪ
’”‹–ſƒƀ
’”‹–ſ„ƀ
’”‹–ſ ƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ɛpylint [Link]
‘ ‘ˆ‹‰ˆ‹Ž‡ˆ‘—†ř—•‹‰†‡ˆƒ—Ž– ‘ˆ‹‰—”ƒ–‹‘
ƋƋƋƋƋƋƋƋƋƋƋƋƋ‘†—އ•–›Ž‡ɩ
śɨřɥś‹••‹‰†‘ •–”‹‰
śɨřɥś ˜ƒŽ‹†ƒ‡ɑƒɑˆ‘”–›’‡ ‘•–ƒ–
ſ•Š‘—ކƒ– ŠſſƃŞɏƄƃŞɥŞɰɏƄƋƀŶſɏɏŜƋɏɏƀƀɛƀ
śɩřɥś ˜ƒŽ‹†ƒ‡ɑ„ɑˆ‘”–›’‡ ‘•–ƒ–
ſ•Š‘—ކƒ– ŠſſƃŞɏƄƃŞɥŞɰɏƄƋƀŶſɏɏŜƋɏɏƀƀɛƀ
śɪřɥś ˜ƒŽ‹†ƒ‡ɑ ɑˆ‘”–›’‡ ‘•–ƒ–
ſ•Š‘—ކƒ– ŠſſƃŞɏƄƃŞɥŞɰɏƄƋƀŶſɏɏŜƋɏɏƀƀɛƀ

Отлично, больше строк, начинающихся с ǥ, нет. Наш счет увеличился с –3,33


до 4,29:
‘—” ‘†‡Šƒ•„‡‡”ƒ–‡†ƒ–ɫŜɩɰŵɨɥ

Контролер pylint хочет увидеть строку документации (короткий текстовый


фрагмент в верхней части модуля или функции, описывающий код) и считает, что
короткие имена переменных, такие как a, b и , не очень аккуратны. Сделаем pylint
более счастливым, а наш код — еще лучше (пример 19.5):

ǷȘȐȔȍȘVW\OHS\
ɑ‘†—އ†‘ •–”‹‰‰‘‡•Ї”‡ɑ

†‡ˆˆ— ſƀś
ɑ — –‹‘†‘ •–”‹‰‰‘‡•Ї”‡Ŝ ‹ř‘Šɑ
ˆ‹”•–ʰɨ
•‡ ‘†ʰɩ
–Š‹”†ʰɪ
’”‹–ſˆ‹”•–ƀ
’”‹–ſ•‡ ‘†ƀ
’”‹–ſ–Š‹”†ƀ

ˆ— ſƀ

ɛpylint [Link]
‘ ‘ˆ‹‰ˆ‹Ž‡ˆ‘—†ř—•‹‰†‡ˆƒ—Ž– ‘ˆ‹‰—”ƒ–‹‘

Жалоб нет. А какой у нас счет?


‘—” ‘†‡Šƒ•„‡‡”ƒ–‡†ƒ–ɨɥŜɥɥŵɨɥ

Не так уж и плохо?
Еще один контролер стиля — ’‡’ɯ (KWWSVS\SLS\WKRQRUJS\SLSHS), вы можете
установить его привычным способом:
ɛpip install pep8

Что он скажет о нашей последней версии кода?


ɛpep8 [Link]
•–›Ž‡ɪŜ’›śɪśɨśɪɥɩ‡š’‡ –‡†ɩ„ŽƒŽ‹‡•řˆ‘—†ɨ

Чтобы сделать код еще более стильным, он рекомендует добавить пустую строку
после начальной строки документации модуля.
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

ǷȈȒȍȚXQLWWHVW
Мы убедились, что больше не оскорбляем чувство стиля богов кода, поэтому теперь
можно перейти к настоящим тестам логики вашей программы.
Хорошим тоном являются написание и запуск тестовых программ до отправки
кода в систему контроля исходного кода. Написание тестов поначалу может быть
утомительным, но они действительно помогают находить проблемы быстрее, осо-
бенно регрессионные тесты (суть которых заключается в том, чтобы сломать то,
что раньше работало). Болезненный опыт учит всех разработчиков: даже самое
маленькое изменение, которое, по их заверениям, не затрагивает другие области при-
ложения, на самом деле влияет на них. Если вы взглянете на качественные пакеты
Python, то заметите, что они поставляются с набором тестов.
Стандартная библиотека содержит не один, а целых два пакета для тестирова-
ния приложений. Начнем с unittest (KWWSVRUHLOO\,P)P(). Мы напишем модуль,
который записывает слова с прописной буквы. Наша первая версия будет ис-
пользовать стандартную строковую функцию ƒ’‹–ƒŽ‹œ‡ſƀ, что, как вы увидите,
приведет к неожиданным результатам. Сохраните этот файл под именем ƒ’Ŝ’›
(пример 19.6).

ǷȘȐȔȍȘFDSS\
†‡ˆŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀś
”‡–—”–‡š–Ŝ ƒ’‹–ƒŽ‹œ‡ſƀ

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


вы хотите получить при определенных входных данных (в нашем примере вы хотите
получить введенный текст записанным с прописной буквы), отправить результат
функции тестирования, а затем проверить, получен ли ожидаемый результат. Ожи-
даемый результат называется утверждением (assertion), поэтому в рамках пакета
unittest вы проверяете результат с помощью методов, чьи имена начинаются со
слова assert, скажем метода ƒ••‡”–“—ƒŽ, показанного в примере 19.7.
Сохраните этот сценарий тестирования под именем –‡•–ɏ ƒ’Ŝ’›.

ǷȘȐȔȍȘWHVWBFDSS\
‹’‘”–—‹––‡•–
‹’‘”– ƒ’

Žƒ••‡•–ƒ’ſ—‹––‡•–Ŝ‡•–ƒ•‡ƀś

†‡ˆ•‡–’ſ•‡Žˆƀś
’ƒ••

†‡ˆ–‡ƒ”‘™ſ•‡Žˆƀś
’ƒ••

†‡ˆ–‡•–ɏ‘‡ɏ™‘”†ſ•‡Žˆƀś
–‡š–ʰɐ†— ɐ
”‡•—Ž–ʰ ƒ’ŜŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀ
•‡ŽˆŜƒ••‡”–“—ƒŽſ”‡•—Ž–řɐ— ɐƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

†‡ˆ–‡•–ɏ—Ž–‹’އɏ™‘”†•ſ•‡Žˆƀś
–‡š–ʰɐƒ˜‡”‹–ƒ„އˆŽ‘ ‘ˆ†— •ɐ
”‡•—Ž–ʰ ƒ’ŜŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀ
•‡ŽˆŜƒ••‡”–“—ƒŽſ”‡•—Ž–řɐ‡”‹–ƒ„އ Ž‘ ˆ— •ɐƀ

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
—‹––‡•–Ŝƒ‹ſƀ

Перед каждым методом тестирования вызывается метод •‡–’ſƀ, а после каждого


из методов тестирования — метод –‡ƒ”‘™ſƀ. Их задача — выделение и освобо-
ждение внешних ресурсов, необходимых для тестов, таких как соединение с базой
данных или создание неких тестовых данных. В нашем случае тесты автономны,
и нам даже не нужно определять методы •‡–’ſƀ и –‡ƒ”‘™ſƀ, однако создать их
пустые версии не повредит. Сердце наших тестов — две функции с именами –‡•–ɏ
‘‡ɏ™‘”†ſƀ и –‡•–ɏ—Ž–‹’އɏ™‘”†•ſƀ. Каждая из них запускает определенную нами
функцию Œ—•–ɏ†‘ɏ‹–ſƀ с разными входными параметрами и проверяет, получен ли
ожидаемый результат. О’кей, запустим тест. Эта команда вызовет два наших метода
тестирования:
ɛpython test_cap.py

 Ŝ
ʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰ
  ś–‡•–ɏ—Ž–‹’އɏ™‘”†•ſɏɏƒ‹ɏɏŜ‡•–ƒ’ƀ
ŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑ–‡•–ɏ ƒ’Ŝ’›ɑřŽ‹‡ɩɥř‹–‡•–ɏ—Ž–‹’އɏ™‘”†•
•‡ŽˆŜƒ••‡”–“—ƒŽſ”‡•—Ž–řɐ‡”‹–ƒ„އ Ž‘ ˆ— •ɐƀ
••‡”–‹‘””‘”śɐ˜‡”‹–ƒ„އˆŽ‘ ‘ˆ†— •ɐŠʰɐ‡”‹–ƒ„އ Ž‘ ˆ— •ɐ
ޘ‡”‹–ƒ„އˆŽ‘ ‘ˆ†— •
ţɋɋɋɋ
ʫ‡”‹–ƒ„އ Ž‘ ˆ— •
ţɋɋɋɋ

ŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞ
ƒɩ–‡•–•‹ɥŜɥɥɨ•

  ſˆƒ‹Ž—”‡•ʰɨƀ

Пакет устроил результат первой проверки (–‡•–ɏ‘‡ɏ™‘”†), но не результат второй


(–‡•–ɏ—Ž–‹’އɏ™‘”†•). Стрелки вверх (ɋ) показывают, какие строки отличаются.
Что такого особенного в примере с несколькими словами? После прочтения
документации для строковой функции ƒ’‹–ƒŽ‹œ‡ (KWWSVRUHLOO\[,9) мы поняли
причину проблемы: она увеличивает только первую букву первого слова. Возможно,
нам сразу нужно было начать с чтения документации.
Нам нужна другая функция. После прочтения той страницы мы нашли функцию
–‹–އſƀ (KWWSVRUHLOO\&1.1O). Изменим файл ƒ’Ŝ’› так, чтобы в нем вместо функ-
ции ƒ’‹–ƒŽ‹œ‡ſƀ использовалась функция –‹–އſƀ (пример 19.8).
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

ǷȘȐȔȍȘǪȖȏȊȘȈȡȈȍȔșȧȒFDSS\
†‡ˆŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀś
”‡–—”–‡š–Ŝ–‹–އſƀ

Повторите тесты и взгляните на результат:


ɛpython test_cap.py

ŜŜ
ŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞ
ƒɩ–‡•–•‹ɥŜɥɥɥ•



Все прошло отлично. Хотя на самом деле нет. Нам нужно добавить в файл –‡•–ɏ
ƒ’Ŝ’› как минимум еще один метод (пример 19.9).

ǷȘȐȔȍȘǪȖȏȊȘȈȡȈȍȔșȧȒWHVWBFDSS\
†‡ˆ–‡•–ɏ™‘”†•ɏ™‹–Šɏƒ’‘•–”‘’Ї•ſ•‡Žˆƀś
–‡š–ʰɑ ɐˆ”‡•Š‘—–‘ˆ‹†‡ƒ•ɑ
”‡•—Ž–ʰ ƒ’ŜŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀ
•‡ŽˆŜƒ••‡”–“—ƒŽſ”‡•—Ž–řɑ ɐ ”‡•Š—–ˆ †‡ƒ•ɑƀ

Запустите тесты еще раз:


ɛpython test_cap.py

ŜŜ
ʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰ
  ś–‡•–ɏ™‘”†•ɏ™‹–Šɏƒ’‘•–”‘’Ї•ſɏɏƒ‹ɏɏŜ‡•–ƒ’ƀ
ŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑ–‡•–ɏ ƒ’Ŝ’›ɑřŽ‹‡ɩɬř‹–‡•–ɏ™‘”†•ɏ™‹–Šɏƒ’‘•–”‘’Ї•
•‡ŽˆŜƒ••‡”–“—ƒŽſ”‡•—Ž–řɑ ɐ ”‡•Š—–ˆ †‡ƒ•ɑƀ
••‡”–‹‘””‘”śɑ ɐ ”‡•Š—–ˆ †‡ƒ•ɑŠʰɑ ɐ ”‡•Š—–ˆ †‡ƒ•ɑ
Ş ɐ ”‡•Š—–ˆ †‡ƒ•
ţɋ
ʫ ɐ ”‡•Š—–ˆ †‡ƒ•
ţɋ

ŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞ
ƒɪ–‡•–•‹ɥŜɥɥɨ•

  ſˆƒ‹Ž—”‡•ʰɨƀ

Наша функция увеличила букву  в конструкции ɐ. В документации к функции


–‹–އſƀ мы обнаружили, что она плохо работает с апострофами. Нам действительно
стоило сначала прочитать текст документации целиком.
В самом конце документации стандартной библиотеки, касающейся строк, мы
находим еще одного кандидата — вспомогательную функцию с именем ƒ’™‘”†•ſƀ.
Используем ее в файле ƒ’Ŝ’› (пример 19.10).
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǷȘȐȔȍȘǹȕȖȊȈȊȖȏȊȘȈȡȈȍȔșȧȒFDSS\

†‡ˆŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀś
ˆ”‘•–”‹‰‹’‘”– ƒ’™‘”†•
”‡–—” ƒ’™‘”†•ſ–‡š–ƀ

ɛpython test_cap.py

ŜŜŜ
ŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞ
ƒɪ–‡•–•‹ɥŜɥɥɫ•



Наконец-то мы это сделали! Э-э-э, на самом деле нет. Нужно добавить еще один
тест в файл –‡•–ɏ ƒ’Ŝ’› (пример 19.11).

ǷȘȐȔȍȘǹȕȖȊȈȊȖȏȊȘȈȡȈȍȔșȧȒWHVWBFDSS\

†‡ˆ–‡•–ɏ™‘”†•ɏ™‹–Šɏ“—‘–‡•ſ•‡Žˆƀś
–‡š–ʰɑɎɑ‘—ɐ”‡†‡•’‹ ƒ„އřɎɑ•ƒ‹†ƒˆˆ›— ɑ
”‡•—Ž–ʰ ƒ’ŜŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀ
•‡ŽˆŜƒ••‡”–“—ƒŽſ”‡•—Ž–řɑɎɑ‘—ɐ”‡‡•’‹ ƒ„އřɎɑƒ‹†ƒˆˆ›— ɑƀ

Сработало?
ɛpython test_cap.py

ŜŜŜ
ʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰ
  ś–‡•–ɏ™‘”†•ɏ™‹–Šɏ“—‘–‡•ſɏɏƒ‹ɏɏŜ‡•–ƒ’ƀ
ŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑ–‡•–ɏ ƒ’Ŝ’›ɑřŽ‹‡ɪɥř‹–‡•–ɏ™‘”†•ɏ™‹–Šɏ“—‘–‡•
•‡ŽˆŜƒ••‡”–“—ƒŽſ”‡•—Ž–řɑɎɑ‘—ɐ”‡
‡•’‹ ƒ„އřɎɑƒ‹†ƒˆˆ›— ɑƀ••‡”–‹‘””‘”śɐɑ›‘—Ɏɐ”‡‡•’‹ ƒ„އřɑ
ƒ‹†ƒˆˆ›— ɐ
Šʰɐɑ‘—Ɏɐ”‡‡•’‹ ƒ„އřɑƒ‹†ƒˆˆ›— ɐŞɑ›‘—ɐ”‡‡•’‹ ƒ„އřɑ
ƒ‹†ƒˆˆ›— 
ţɋʫɑ‘—ɐ”‡‡•’‹ ƒ„އřɑƒ‹†ƒˆˆ›— 
ţɋ
ŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞ
ƒɫ–‡•–•‹ɥŜɥɥɫ•

  ſˆƒ‹Ž—”‡•ʰɨƀ

Выглядит так, будто первая двойная кавычка смутила даже функцию ƒ’™‘”†•,
нашего текущего фаворита. Она попробовала увеличить символ " и уменьшить все
остальное (‘—ɐ”‡). Нам также нужно проверить, оставила ли функция-увеличитель
остальную часть строки нетронутой.
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

Люди, которые зарабатывают тестированием на жизнь, способны замечать такие


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

ǷȈȒȍȚGRFWHVW
Второй пакет для тестирования стандартной библиотеки — †‘ –‡•– (KWWSELWO\S\
GRFWHVW). Он позволяет писать тесты внутри строки документации, которые и сами
будут служить документацией. Он выглядит как интерактивный интерпретатор:
символы ʴʴʴ , за ними следует вызов, а затем результаты в следующей строке.
Вы можете запустить некоторые тесты в интерактивном интерпретаторе и просто
вставить результат в свой тестовый файл. Модифицируем файл ƒ’Ŝ’› (убрав тот
проблемный тест с кавычками) и сохраним его под именем ƒ’ɩŜ’›, как показано
в примере 19.12.

ǷȘȐȔȍȘFDSS\
†‡ˆŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀś
ɑɑɑ
ʴʴʴŒ—•–ɏ†‘ɏ‹–ſɐ†— ɐƀ
ɐ— ɐ
ʴʴʴŒ—•–ɏ†‘ɏ‹–ſɐƒ˜‡”‹–ƒ„އˆŽ‘ ‘ˆ†— •ɐƀ
ɐ‡”‹–ƒ„އ Ž‘ ˆ— •ɐ
ʴʴʴŒ—•–ɏ†‘ɏ‹–ſɑ ɐˆ”‡•Š‘—–‘ˆ‹†‡ƒ•ɑƀ
ɑ ɐ ”‡•Š—–ˆ †‡ƒ•ɑ
ɑɑɑ
ˆ”‘•–”‹‰‹’‘”– ƒ’™‘”†•
”‡–—” ƒ’™‘”†•ſ–‡š–ƀ

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
‹’‘”–†‘ –‡•–
†‘ –‡•–Ŝ–‡•–‘†ſƀ

Когда вы его запустите, в случае успеха он не выведет ничего:


ɛpython [Link]

Запустите его с опцией Ş˜, чтобы увидеть произошедшее на самом деле:


ɛpython [Link] -v
”›‹‰ś
Œ—•–ɏ†‘ɏ‹–ſɐ†— ɐƀ
š’‡ –‹‰ś
ɐ— ɐ
‘
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

”›‹‰ś
Œ—•–ɏ†‘ɏ‹–ſɐƒ˜‡”‹–ƒ„އˆŽ‘ ‘ˆ†— •ɐƀ
š’‡ –‹‰ś
ɐ‡”‹–ƒ„އ Ž‘ ˆ— •ɐ
‘
”›‹‰ś
Œ—•–ɏ†‘ɏ‹–ſɑ ɐˆ”‡•Š‘—–‘ˆ‹†‡ƒ•ɑƀ
š’‡ –‹‰ś
ɑ ɐ ”‡•Š—–ˆ †‡ƒ•ɑ
‘
ɨ‹–‡•Šƒ†‘–‡•–•ś
ɏɏƒ‹ɏɏ
ɨ‹–‡•’ƒ••‡†ƒŽŽ–‡•–•ś
ɪ–‡•–•‹ɏɏƒ‹ɏɏŜŒ—•–ɏ†‘ɏ‹–
ɪ–‡•–•‹ɩ‹–‡•Ŝ
ɪ’ƒ••‡†ƒ†ɥˆƒ‹Ž‡†Ŝ
‡•–’ƒ••‡†Ŝ

ǷȈȒȍȚQRVH
Сторонний пакет nose (KWWSVRUHLOO\J:.U) — еще одна альтернатива пакету unittest.
Команда, позволяющая установить его, выглядит так:
ɛpip install nose

Вам не нужно создавать класс, который содержит тестовые методы, как мы де-
лали при работе с unittest. Любая функция, содержащая в своем имени слово test,
будет запущена. Модифицируем наш последний тестировщик ‹––‡•– и сохраним
его под именем –‡•–ɏ ƒ’ɏ‘•‡Ŝ’› (пример 19.13).

ǷȘȐȔȍȘWHVWBFDSBQRVHS\
‹’‘”– ƒ’ɩ
ˆ”‘‘•‡Ŝ–‘‘Ž•‹’‘”–‡“ɏ

†‡ˆ–‡•–ɏ‘‡ɏ™‘”†ſƀś
–‡š–ʰɐ†— ɐ
”‡•—Ž–ʰ ƒ’ŜŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀ
‡“ɏſ”‡•—Ž–řɐ— ɐƀ

†‡ˆ–‡•–ɏ—Ž–‹’އɏ™‘”†•ſƀś
–‡š–ʰɐƒ˜‡”‹–ƒ„އˆŽ‘ ‘ˆ†— •ɐ
”‡•—Ž–ʰ ƒ’ŜŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀ
‡“ɏſ”‡•—Ž–řɐ‡”‹–ƒ„އ Ž‘ ˆ— •ɐƀ

†‡ˆ–‡•–ɏ™‘”†•ɏ™‹–Šɏƒ’‘•–”‘’Ї•ſƀś
–‡š–ʰɑ ɐˆ”‡•Š‘—–‘ˆ‹†‡ƒ•ɑ
”‡•—Ž–ʰ ƒ’ŜŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀ
‡“ɏſ”‡•—Ž–řɑ ɐ ”‡•Š—–ˆ †‡ƒ•ɑƀ

†‡ˆ–‡•–ɏ™‘”†•ɏ™‹–Šɏ“—‘–‡•ſƀś
–‡š–ʰɑɎɑ‘—ɐ”‡†‡•’‹ ƒ„އřɎɑ•ƒ‹†ƒˆˆ›— ɑ
”‡•—Ž–ʰ ƒ’ŜŒ—•–ɏ†‘ɏ‹–ſ–‡š–ƀ
‡“ɏſ”‡•—Ž–řɑɎɑ‘—ɐ”‡‡•’‹ ƒ„އřɎɑƒ‹†ƒˆˆ›— ɑƀ
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

Запустим тесты:
ɛnosetests test_cap_nose.py

ŜŜŜ
ʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰʰ
  ś–‡•–ɏ ƒ’ɏ‘•‡Ŝ–‡•–ɏ™‘”†•ɏ™‹–Šɏ“—‘–‡•
ŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑŵ•‡”•ŵŜŜŜŵ•‹–‡Ş’ƒ ƒ‰‡•ŵ‘•‡ŵ ƒ•‡Ŝ’›ɑřŽ‹‡ɨɰɯř‹”—‡•–
•‡ŽˆŜ–‡•–ſƋ•‡ŽˆŜƒ”‰ƀ
 ‹Ž‡ɑŵ•‡”•ŵŜŜŜŵ„‘‘ŵ–‡•–ɏ ƒ’ɏ‘•‡Ŝ’›ɑřŽ‹‡ɩɪř‹–‡•–ɏ™‘”†•ɏ™‹–Šɏ“—‘–‡•
‡“ɏſ”‡•—Ž–řɑɎɑ‘—ɐ”‡‡•’‹ ƒ„އřɎɑƒ‹†ƒˆˆ›— ɑƀ
••‡”–‹‘””‘”śɐɑ›‘—Ɏɐ”‡‡•’‹ ƒ„އřɑƒ‹†ƒˆˆ›— ɐŠʰ
ɐɑ‘—Ɏɐ”‡‡•’‹ ƒ„އřɑƒ‹†ƒˆˆ›— ɐ
ŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞŞ
ƒɫ–‡•–•‹ɥŜɥɥɬ•

  ſˆƒ‹Ž—”‡•ʰɨƀ
Мы нашли ту же ошибку, что и при использовании unittest. К счастью, в конце
этой главы приводится упражнение, в котором вам предстоит ее исправить.

ǬȘțȋȐȍȜȘȍȑȔȊȖȘȒȐȌȓȧȚȍșȚȐȘȖȊȈȕȐȧ
По какой-то причине людям нравится писать тестовые фреймворки для Python.
Если вам любопытно, то можете взглянуть на другие популярные решения:
‰–‘š (KWWSWR[UHDGWKHGRFVRUJ);
‰’›Ŝ–‡•– (KWWSVS\WHVWRUJ);
‰green (KWWSVJLWKXEFRP&OHDQ&XWJUHHQ).

ǷȖșȚȖȧȕȕȈȧȐȕȚȍȋȘȈȞȐȧ
Когда ваша группа генерирует много кода каждый день, полезно автоматизировать
тесты по мере появления изменений. Вы можете автоматизировать системы кон-
троля версий так, чтобы тесты запускались при возникновении нового кода. Таким
образом, каждый будет знать, сломал ли кто-то сборку и убежал обедать пораньше —
или на новую работу.
Эти системы велики, и я не буду рассматривать детали их установки и исполь-
зования. Если они вам когда-нибудь понадобятся, то вы будете знать, где их искать:
‰„—‹Ž†„‘– (KWWSEXLOGERWQHW) — эта система контроля версий, написанная на
Python, автоматизирует построение, тестирование и выпуск кода;
‰Œ‡‹• (KWWSMHQNLQVFLRUJ) — система написана на Java, в данный момент вы-
глядит наиболее предпочтительным инструментом для постоянной интеграции;
‰–”ƒ˜‹•Ş ‹ (KWWSWUDYLVFLFRP) — эта система автоматизирует проекты, размещен-
ные на GitHub, бесплатна для проектов с открытым исходным кодом;
‰ ‹” އ ‹ (KWWSVFLUFOHFLFRP) — эта система коммерческая, но бесплатна для част-
ных проектов и проектов с открытым исходным кодом.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǶȚȓȈȌȒȈȒȖȌȈ
Отладка — почти как расследование преступления,
где главный преступник — тоже вы.

Филипе Фортес

Все знают: отладка кода вдвое сложнее, чем его


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

Брайан Керниган

Всегда тестируйте код. Чем лучше ваши тесты, тем меньше кода вам потом при-
дется исправлять. Но иногда баги все равно случаются, и их нужно исправлять при
обнаружении.
Обычно код ломается из-за действий, которые вы сделали только что. Поэтому
обычно отладка выполняется «снизу вверх», начиная с ваших самых последних из-
менений1.
Но иногда причина кроется где-то еще, в чем-то, чему вы доверяли и думали, что
оно работает. Вы могли бы подумать: если бы проблема была в том, чем пользовались
многие люди, то кто-то уже заметил бы ее. Но так бывает не всегда. Самые хитрые
баги, которые требовали на свое исправление больше недели, появились из внешних
источников. Поэтому после того, как обвините человека в зеркале, пересмотрите
свои предположения. Данный подход называется нисходящим и занимает больше
времени.
Далее мы рассмотрим некоторые приемы отладки, начиная с быстрых и «гряз-
ных» и заканчивая медленными и зачастую такими же «грязными».

ǼțȕȒȞȐȧSULQW
Самый простой способ выполнять отладку в Python — построчно выполнять код.
Полезно отображать результат работы функции ˜ƒ”•ſƀ, которая извлекает значения
ваших локальных переменных, включая аргументы функций:
ʴʴʴ†‡ˆˆ— ſƋƒ”‰•řƋƋ™ƒ”‰•ƀś
ŜŜŜ’”‹–ſ˜ƒ”•ſƀƀ
ŜŜŜ
ʴʴʴˆ— ſɨřɩřɪƀ
Ƈɐƒ”‰•ɐśſɨřɩřɪƀřɐ™ƒ”‰•ɐśƇƈƈ
ʴʴʴˆ— ſƃɐƒɐřɐ„ɐřɐƒ”‰ŠɐƄƀ
Ƈɐƒ”‰•ɐśſƃɐƒɐřɐ„ɐřɐƒ”‰ŠɐƄřƀřɐ™ƒ”‰•ɐśƇƈƈ

1
Вы как детектив: «Я знаю, что я здесь! И если не выйду с поднятыми руками, то приду за
собой!»
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

Зачастую на экран следует выводить Ž‘ ƒŽ•ſƀ и ‰Ž‘„ƒŽ•ſƀ.


Если в вашем коде также встречается и стандартный вывод данных, то можете
написать собственные сообщения об ошибке в поток вывода для ошибок с помощью
конструкции ’”‹–ſ•–—ˆˆř ˆ‹Ž‡ʰ•›•Ŝ•–†‡””ƀ.

ǶȚȓȈȌȒȈșȗȖȔȖȡȤȦȌȍȒȖȘȈȚȖȘȖȊ
Как вы уже знаете из раздела «Декораторы» главы 9, декоратор может вызывать код,
располагающийся до или после функции, не модифицируя его внутри нее самой.
Это значит, что вы можете использовать декоратор для выполнения какого-либо
действия до или после вызова любой функции, а не только тех, которые написали
вы. Определим декоратор †—’, позволяющий вывести на экран входные аргументы
и выводимые значения любой функции по мере ее вызова (разработчики знают, что
выходные данные нужно декорировать), как показано в примере 19.14.

ǷȘȐȔȍȘGXPSS\
†‡ˆ†—’ſˆ— ƀś
ɑ”‹–‹’—–ƒ”‰—‡–•ƒ†‘—–’—–˜ƒŽ—‡ſ•ƀɑ
†‡ˆ™”ƒ’’‡†ſƋƒ”‰•řƋƋ™ƒ”‰•ƀś
’”‹–ſɑ — –‹‘ƒ‡śɑřˆ— Ŝɏɏƒ‡ɏɏƀ
’”‹–ſɑ ’—–ƒ”‰—‡–•śɑřɐɐŜŒ‘‹ſƒ’ſ•–”řƒ”‰•ƀƀƀ
’”‹–ſɑ ’—–‡›™‘”†ƒ”‰—‡–•śɑř™ƒ”‰•Ŝ‹–‡•ſƀƀ
‘—–’—–ʰˆ— ſƋƒ”‰•řƋƋ™ƒ”‰•ƀ
’”‹–ſɑ—–’—–śɑř‘—–’—–ƀ
”‡–—”‘—–’—–
”‡–—”™”ƒ’’‡†

Перейдем к декорируемой части. Это функция с именем †‘—„އſƀ , которая


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

ǷȘȐȔȍȘWHVWBGXPSS\
ˆ”‘†—’‹’‘”–†—’

ɒ†—’
†‡ˆ†‘—„އſƋƒ”‰•řƋƋ™ƒ”‰•ƀś
ɑ‘—„އ‡˜‡”›ƒ”‰—‡–ɑ
‘—–’—–ɏŽ‹•–ʰƃɩƋƒ”‰ˆ‘”ƒ”‰‹ƒ”‰•Ƅ
‘—–’—–ɏ†‹ –ʰƇśɩƋ˜ˆ‘”ř˜‹™ƒ”‰•Ŝ‹–‡•ſƀƈ
”‡–—”‘—–’—–ɏŽ‹•–ř‘—–’—–ɏ†‹ –

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
‘—–’—–ʰ†‘—„އſɪřɬřˆ‹”•–ʰɨɥɥř‡š–ʰɰɯŜɭřŽƒ•–ʰŞɫɥƀ

Запустите пример:
ɛpython test_dump.py

— –‹‘ƒ‡ś†‘—„އ
’—–ƒ”‰—‡–•śɪɬ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

’—–‡›™‘”†ƒ”‰—‡–•ś†‹ –ɏ‹–‡•ſƃſɐˆ‹”•–ɐřɨɥɥƀřſɐ‡š–ɐřɰɯŜɭƀř
ſɐŽƒ•–ɐřŞɫɥƀƄƀ
—–’—–śſƃɭřɨɥƄřƇɐˆ‹”•–ɐśɩɥɥřɐ‡š–ɐśɨɰɮŜɩřɐŽƒ•–ɐśŞɯɥƈƀ

ǶȚȓȈȌȟȐȒSGE
Эти приемы полезны, но иногда ничто не сможет заменить настоящий отладчик.
Большинство IDE содержат отладчики, возможности и пользовательские интер-
фейсы которых могут варьироваться. В данном подразделе я опишу использование
стандартного отладчика Python ’†„ (KWWSVRUHLOO\,,1\).

ǭșȓȐȊȣȏȈȗțșȒȈȍȚȍȗȘȖȋȘȈȔȔțșȜȓȈȋȖȔLȚȖȗȘȐȍȍȕȍțȌȈȟȕȖȔȏȈȊȍȘȠȍȕȐȐ3\WKRQ
ȊȍȘȕȍȚȊȈșȊȐȕȚȍȘȈȒȚȐȊȕȣȑȐȕȚȍȘȗȘȍȚȈȚȖȘ

Рассмотрим программу с ошибкой, которая зависит от входных данных, — та-


кую ошибку может быть особенно трудно найти. Это реальная ошибка, которая
возникла в ранние дни компьютеризации и довольно долго сбивала с толку про-
граммистов.
Мы собираемся считать файл, содержащий названия стран и их столиц, разде-
ленные запятыми, и вывести их на экран в формате «столица, страна». Прописные
буквы в них могут быть расставлены неправильно, так что нам нужно исправить это
при выводе на экран. В файле также могут быть лишние пробелы, следует избавиться
и от них. Наконец, несмотря на то, что было бы логично считать весь файл до конца,
по какой-то причине наш менеджер сказал нам остановиться, если мы встретим
слово quit (состоящее из смеси прописных и строчных букв). В примере 19.16 по-
казан файл с данными.

ǷȘȐȔȍȘFLWLHVFVY
”ƒ ‡řƒ”‹•
˜‡—œ—‡Žƒř ƒ”ƒ ƒ•
‹–Š—ƒ‹ř˜‹Ž‹—•
“—‹–

Разработаем алгоритм (способ решения задачи). Это псевдокод, он выглядит как


программа, но является лишь способом выразить логику простым языком до преоб-
разования его в настоящую программу. Одна из причин, по которым программисты
любят Python, — он выглядит очень похожим на псевдокод, поэтому его не так трудно
преобразовать в рабочую программу, когда приходит время:
ȘȟȳȞȔȚȘȢȝȥȦȤȢȞȜȖȦșȞȥȦȢȖȢȠȨȔȝȟșś
ȥȫȜȦȔȦȰȥȦȤȢȞȧ
ȧȘȔȟȜȦȰȣȤȢȕșȟȯȖȡȔȫȔȟșȜȞȢȡȪșȥȦȤȢȞȜ
șȥȟȜȡȔȝȘșȡȔȥȦȤȢȞȔɑ“—‹–ɑȖȥȦȤȢȞșřțȔȣȜȥȔȡȡȢȝȖȡȜȚȡșȠȤșȗȜȥȦȤșś
ȢȥȦȔȡȢȖȜȦȰȥȳ
ȜȡȔȫșś
ȤȔțȘșȟȜȦȰȥȦȤȔȡȧȜȥȦȢȟȜȪȧȥȜȠȖȢȟȢȠțȔȣȳȦȢȝ
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

ȧȘȔȟȜȦȰȣȤȢȕșȟȯȖȡȔȫȔȟșȜȞȢȡȪș
țȔȣȜȥȔȦȰȥȦȤȔȡȧȜȥȦȢȟȜȪȧȥȣȤȢȣȜȥȡȢȝȕȧȞȖȯ
ȖȯȖșȥȦȜȡȔȱȞȤȔȡȥȦȢȟȜȪȧřțȔȣȳȦȧȲȜȥȦȤȔȡȧ

Нам нужно удалить из имен начальные и конечные пробелы, поскольку таково


требование к программе. Аналогично мы поступаем со сравнением со строкой quit
и записью названий страны и города с прописной буквы. Имея это в виду, напишем
файл ƒ’‹–ƒŽ•Ŝ’›, который точно будет работать корректно (пример 19.17).

ǷȘȐȔȍȘFDSLWDOVS\
†‡ˆ’”‘ ‡••ɏ ‹–‹‡•ſˆ‹Ž‡ƒ‡ƀś
™‹–Š‘’‡ſˆ‹Ž‡ƒ‡řɐ”–ɐƀƒ•ˆ‹Ž‡ś
ˆ‘”Ž‹‡‹ˆ‹Ž‡ś
Ž‹‡ʰŽ‹‡Ŝ•–”‹’ſƀ
‹ˆɐ“—‹–ɐ‹Ž‹‡ŜŽ‘™‡”ſƀś
”‡–—”
 ‘—–”›ř ‹–›ʰŽ‹‡Ŝ•’Ž‹–ſɐřɐƀ
 ‹–›ʰ ‹–›Ŝ•–”‹’ſƀ
 ‘—–”›ʰ ‘—–”›Ŝ•–”‹’ſƀ
’”‹–ſ ‹–›Ŝ–‹–އſƀř ‘—–”›Ŝ–‹–އſƀř•‡’ʰɐřɐƀ

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
‹’‘”–•›•
’”‘ ‡••ɏ ‹–‹‡•ſ•›•Ŝƒ”‰˜ƃɨƄƀ

Протестируем программу с помощью файла, созданного ранее. На старт, внима-


ние, марш:
ɛpython [Link] [Link]
ƒ”‹•ř ”ƒ ‡
ƒ”ƒ ƒ•ř‡—œ—‡Žƒ
‹Ž‹—•ř‹–Š—ƒ‹ƒ

Выглядит отлично! Программа прошла один тест, поэтому отправим ее в про-


изводство, обрабатывать столицы и страны со всего мира, пока она не ошибется на
этом файле данных (пример 19.18).

ǷȘȐȔȍȘFLWLHVFVY
ƒ”‰‡–‹ƒř„—‡‘•ƒ‹”‡•
„‘Ž‹˜‹ƒřŽƒ’ƒœ
„”ƒœ‹Žř„”ƒ•‹Ž‹ƒ
Ћއř•ƒ–‹ƒ‰‘
‘Ž‘„‹ƒř‘‰‘–ž
‡ —ƒ†‘”ř“—‹–‘
ˆƒŽŽƒ†‹•Žƒ†•ř•–ƒŽ‡›
ˆ”‡ Љ—‹ƒƒř ƒ›‡‡
‰—›ƒƒř‰‡‘”‰‡–‘™
’ƒ”ƒ‰—ƒ›ř•— ‹Ü
’‡”—řŽ‹ƒ
•—”‹ƒ‡ř’ƒ”ƒƒ”‹„‘
—”—‰—ƒ›ř‘–‡˜‹†‡‘
˜‡‡œ—‡Žƒř ƒ”ƒ ƒ•
quit
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Несмотря на то что в файле было 15 строк, программа завершается после вывода


всего пяти:
ɛpython [Link] [Link]
—‡‘•‹”‡•ř”‰‡–‹ƒ
ƒƒœř‘Ž‹˜‹ƒ
”ƒœ‹Ž‹ƒř”ƒœ‹Ž
ƒ–‹ƒ‰‘řЋއ
‘‰‘–žř‘Ž‘„‹ƒ

Что случилось? Мы можем продолжать редактировать файл ƒ’‹–ƒŽ•Ŝ’›, раз-


мещая выражения ’”‹–ſƀ в местах потенциального возникновения ошибки, но
посмотрим, сможет ли помочь отладчик.
Чтобы использовать отладчик, импортируйте модуль ’†„ из командной строки,
введя ŷ ’†„, например, так:
ɛpython -m pdb [Link] [Link]

ʴŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ„‘‘ŵ ƒ’‹–ƒŽ•Ŝ’›ſɨƀʳ‘†—އʴſƀ


Şʴ†‡ˆ’”‘ ‡••ɏ ‹–‹‡•ſˆ‹Ž‡ƒ‡ƀś
ſ†„ƀ

Это запустит программу и разместит вас на первой строке. Если вы введете


символ ȥ (от слова continue — «продолжить»), то программа будет работать, пока
не завершится либо естественным образом, либо из-за ошибки:
ſ†„ƀc

—‡‘•‹”‡•ř”‰‡–‹ƒ
ƒƒœř‘Ž‹˜‹ƒ
”ƒœ‹Ž‹ƒř”ƒœ‹Ž
ƒ–‹ƒ‰‘řЋއ
‘‰‘–žř‘Ž‘„‹ƒ
Ї’”‘‰”ƒˆ‹‹•Ї†ƒ†™‹ŽŽ„‡”‡•–ƒ”–‡†
ʴŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ„‘‘ŵ ƒ’‹–ƒŽ•Ŝ’›ſɨƀʳ‘†—އʴſƀ
Şʴ†‡ˆ’”‘ ‡••ɏ ‹–‹‡•ſˆ‹Ž‡ƒ‡ƀś

Программа завершилась нормально, точно так же, как и раньше, когда мы запу-
скали ее вне отладчика. Попробуем запустить ее снова, использовав специальные
команды, чтобы сузить место поиска проблемы. Похоже, имеет место логическая
ошибка, а не синтаксическая проблема или исключение (которые бы выдали со-
общение об ошибке).
Введите s (step — «шаг»), чтобы пройти по отдельным строкам кода. Это позво-
лит пройти по всем строкам кода Python: вашим, стандартной библиотеки и любых
других применяемых вами модулей. Используя команду s, вы также входите во все
функции и проходите каждую построчно. Введите n (next — «следующий»), чтобы
идти по шагам, но не заходить внутрь функций: когда вы находитесь на строке,
где вызывается функция, эта команда выполняет всю функцию и вы оказываетесь
на следующей строке. Используйте s, если не уверены в том, где конкретно есть
проблема, а n — будучи уверенными, что некая функция не вызывает проблем,
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

особенно когда она длинная. Зачастую вы будете проходить построчно весь свой
код и пропускать библиотечный, поскольку подразумевается, что он хорошо проте-
стирован. Используем s с целью начать двигаться от начала программы к функции
’”‘ ‡••ɏ ‹–‹‡•ſƀ:
ſ†„ƀs

ʴŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ„‘‘ŵ ƒ’‹–ƒŽ•Ŝ’›ſɨɩƀʳ‘†—އʴſƀ


Şʴ‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐśʳŵ’”‡ʴ

ſ†„ƀs

ʴŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ„‘‘ŵ ƒ’‹–ƒŽ•Ŝ’›ſɨɪƀʳ‘†—އʴſƀ


Şʴ‹’‘”–•›•

ſ†„ƀs

ʴŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ„‘‘ŵ ƒ’‹–ƒŽ•Ŝ’›ſɨɫƀʳ‘†—އʴſƀ


Şʴ’”‘ ‡••ɏ ‹–‹‡•ſ•›•Ŝƒ”‰˜ƃɨƄƀ

ſ†„ƀs

ŞŞƒŽŽŞŞ
ʴŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ„‘‘ŵ ƒ’‹–ƒŽ•Ŝ’›ſɨƀ’”‘ ‡••ɏ ‹–‹‡•ſƀ
Şʴ†‡ˆ’”‘ ‡••ɏ ‹–‹‡•ſˆ‹Ž‡ƒ‡ƀś

ſ†„ƀs
ʴŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ„‘‘ŵ ƒ’‹–ƒŽ•Ŝ’›ſɩƀ’”‘ ‡••ɏ ‹–‹‡•ſƀ
Şʴ™‹–Š‘’‡ſˆ‹Ž‡ƒ‡řɐ”–ɐƀƒ•ˆ‹Ž‡ś

Введите l (list — «перечислить»), чтобы увидеть следующие несколько строк


своей программы:
ſ†„ƀl

ɨ†‡ˆ’”‘ ‡••ɏ ‹–‹‡•ſˆ‹Ž‡ƒ‡ƀś


ɩŞʴ™‹–Š‘’‡ſˆ‹Ž‡ƒ‡řɐ”–ɐƀƒ•ˆ‹Ž‡ś
ɪˆ‘”Ž‹‡‹ˆ‹Ž‡ś
ɫŽ‹‡ʰŽ‹‡Ŝ•–”‹’ſƀ
ɬ‹ˆɐ“—‹–ɐ‹Ž‹‡ŜŽ‘™‡”ſƀś
ɭ”‡–—”
ɮ ‘—–”›ř ‹–›ʰŽ‹‡Ŝ•’Ž‹–ſɐřɐƀ
ɯ ‹–›ʰ ‹–›Ŝ•–”‹’ſƀ
ɰ ‘—–”›ʰ ‘—–”›Ŝ•–”‹’ſƀ
ɨɥ’”‹–ſ ‹–›Ŝ–‹–އſƀř ‘—–”›Ŝ–‹–އſƀř•‡’ʰɐřɐƀ
ɨɨ
ſ†„ƀ

Стрелка (Şʴ) указывает на текущую строку.


Мы могли бы и дальше применять команды s или n в надежде что-то найти, но
используем одну из главных особенностей отладчика — точки останова. Такая
точка останавливает выполнение программы на указанной вами строке. В данном
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

случае мы хотим узнать, почему функция ’”‘ ‡••ɏ ‹–‹‡•ſƀ вызывает завершение
программы до прочтения всех введенных строк. Строка 3 (for line in ˆ‹Ž‡ś) будет
считывать каждую строку входного файла, поэтому выглядит невинно. Единствен-
ное место, где мы можем вернуться из функции до прочтения всех данных, — это
строка 6 (return). Поставим точку останова на этой строке:
ſ†„ƀb 6

”‡ƒ’‘‹–ɨƒ–ŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ„‘‘ŵ ƒ’‹–ƒŽ•Ŝ’›śɭ

Далее продолжим выполнение программы до тех пор, пока она либо не достигнет
точки останова, либо не завершится обычным образом:
ſ†„ƀc

—‡‘•‹”‡•ř”‰‡–‹ƒ
ƒƒœř‘Ž‹˜‹ƒ
”ƒ•‹Ž‹ƒř”ƒœ‹Ž
ƒ–‹ƒ‰‘řЋއ
‘‰‘–žř‘Ž‘„‹ƒ
ʴŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ„‘‘ŵ ƒ’‹–ƒŽ•Ŝ’›ſɭƀ’”‘ ‡••ɏ ‹–‹‡•ſƀ
Şʴ”‡–—”

Ага, она остановилась на точке останова в строке 6. Это показывает, что програм-
ма хочет завершиться после прочтения страны, которая идет вслед за Колумбией.
Выведем значение переменной line с целью увидеть только что прочитанное нами:
ſ†„ƀp line

ɐ‡ —ƒ†‘”ř“—‹–‘ɐ

Серьезно? Столица называется quito ? Ваш менеджер не ожидал, что строка


quit станет частью входных данных, поэтому показалось логичным использовать
ее в качестве контрольного значения (индикатора конца). Вам следует отправиться
прямо к нему и сказать все как на духу, я подожду.
Если после этого у вас все еще есть работа, то можете просмотреть все точки
останова с помощью команды b:
ſ†„ƀb

—›’‡‹•’„Ї”‡
ɨ„”‡ƒ’‘‹–‡‡’›‡•ƒ–ŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ„‘‘ŵ ƒ’‹–ƒŽ•Ŝ’›śɭ
„”‡ƒ’‘‹–ƒŽ”‡ƒ†›Š‹–ɨ–‹‡

Команда l покажет строки кода, текущую строку (Şʴ) и все имеющиеся точки
останова (). Вызов команды l без аргументов выведет все строки, начиная с точки
предыдущего вызова этой команды, поэтому включите в вызов опциональный па-
раметр — стартовую строку (в нашем примере начнем с ɨ):
ſ†„ƀl 1

ɨ†‡ˆ’”‘ ‡••ɏ ‹–‹‡•ſˆ‹Ž‡ƒ‡ƀś


ɩ™‹–Š‘’‡ſˆ‹Ž‡ƒ‡řɐ”–ɐƀƒ•ˆ‹Ž‡ś
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

ɪˆ‘”Ž‹‡‹ˆ‹Ž‡ś
ɫŽ‹‡ʰŽ‹‡Ŝ•–”‹’ſƀ
ɬ‹ˆɐ“—‹–ɐ‹Ž‹‡ŜŽ‘™‡”ſƀś
ɭŞʴ”‡–—”
ɮ ‘—–”›ř ‹–›ʰŽ‹‡Ŝ•’Ž‹–ſɐřɐƀ
ɯ ‹–›ʰ ‹–›Ŝ•–”‹’ſƀ
ɰ ‘—–”›ʰ ‘—–”›Ŝ•–”‹’ſƀ
ɨɥ’”‹–ſ ‹–›Ŝ–‹–އſƀř ‘—–”›Ŝ–‹–އſƀř•‡’ʰɐřɐƀ
ɨɨ

Теперь модифицируем наш тест, как показано в примере 19.19, чтобы выполня-
лась проверка на полное совпадение со строкой quit без всяких других символов.

ǷȘȐȔȍȘFDSLWDOVS\
†‡ˆ’”‘ ‡••ɏ ‹–‹‡•ſˆ‹Ž‡ƒ‡ƀś
™‹–Š‘’‡ſˆ‹Ž‡ƒ‡řɐ”–ɐƀƒ•ˆ‹Ž‡ś
ˆ‘”Ž‹‡‹ˆ‹Ž‡ś
Ž‹‡ʰŽ‹‡Ŝ•–”‹’ſƀ
‹ˆɐ“—‹–ɐʰʰŽ‹‡ŜŽ‘™‡”ſƀś
”‡–—”
 ‘—–”›ř ‹–›ʰŽ‹‡Ŝ•’Ž‹–ſɐřɐƀ
 ‹–›ʰ ‹–›Ŝ•–”‹’ſƀ
 ‘—–”›ʰ ‘—–”›Ŝ•–”‹’ſƀ
’”‹–ſ ‹–›Ŝ–‹–އſƀř ‘—–”›Ŝ–‹–އſƀř•‡’ʰɐřɐƀ

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
‹’‘”–•›•
’”‘ ‡••ɏ ‹–‹‡•ſ•›•Ŝƒ”‰˜ƃɨƄƀ

Запустим программу еще раз:


ɛpython [Link] [Link]

—‡‘•‹”‡•ř”‰‡–‹ƒ
ƒƒœř‘Ž‹˜‹ƒ
”ƒ•‹Ž‹ƒř”ƒœ‹Ž
ƒ–‹ƒ‰‘řЋއ
‘‰‘–žř‘Ž‘„‹ƒ
—‹–‘ř —ƒ†‘”
–ƒŽ‡›ř ƒŽŽƒ† •Žƒ†•
ƒ›‡‡ř ”‡ Š —‹ƒƒ
‡‘”‰‡–‘™ř —›ƒƒ
•— ‹Üřƒ”ƒ‰—ƒ›
‹ƒř‡”—
ƒ”ƒƒ”‹„‘ř—”‹ƒ‡
‘–‡˜‹†‡‘ř”—‰—ƒ›
ƒ”ƒ ƒ•ř‡‡œ—‡Žƒ

Это был краткий обзор отладчика — его достаточно для демонстрации того,
что вы можете сделать и какие команды будете использовать бо' льшую часть
времени.
Помните: больше тестов — меньше отладки.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǼțȕȒȞȐȧEUHDNSRLQW
В Python 3.7 появилась новая встроенная функция „”‡ƒ’‘‹–ſƀ. Если вы добавите
ее в свой код, то отладчик запустится автоматически и будет останавливаться в каж-
дой локации. Без нее вам придется запускать такой отладчик, как ’†„, и расставлять
точки останова вручную, как вы уже видели ранее.
Отладчик, используемый по умолчанию, вам уже знаком (’†„), но его можно из-
менить, установив переменную окружения   . Например, вы можете
использовать удаленный отладчик, работающий на основе веб-подключения ™‡„Ş’†„
(KWWSVS\SLRUJSURMHFWZHESGE):
ɛexport PYTHONBREAKPOINT='web_pdb.set_trace'

Официальная документация несколько суховата, но хорошие обзоры этой функ-


ции можно найти здесь (KWWSVRUHLOO\40=) и здесь (KWWSVRUHLOO\/-.\).

ǯȈȗȐșȣȊȈȍȔȊȎțȘȕȈȓșȖȖȉȡȍȕȐȧȖȉȖȠȐȉȒȈȝ
В какой-то момент вам может понадобиться перейти от использования выражений
’”‹–ſƀ к записи сообщений в журнал. Журнал, как правило, представляет собой
системный файл, в котором накапливаются сообщения, содержащие полезную
информацию, например временную метку или имя пользователя, запустившего
программу. Зачастую журналы ежедневно ротируются (переименовываются) и сжи-
маются, благодаря чему не переполняют ваш диск и не создают проблем. Если ваша
программа работает «не так», то вы можете просмотреть соответствующий файл
журнала и увидеть, что произошло. Содержимое исключений особенно полезно за-
писывать в журнал, поскольку оно подсказывает номер строки, после выполнения
которой программа завершилась, и причину такого завершения.
Для журналирования используется модуль стандартной библиотеки logging
(KWWSELWO\S\ORJJLQJ). Большинство его описаний я считаю немного непонятными.
Спустя некоторое время они будут казаться осмысленными, но поначалу выглядят
чересчур сложными. Модуль logging содержит следующие концепции:
‰сообщение, которое вы хотите сохранить в журнал;
‰уровни приоритета и соответствующие функции — †‡„—‰ſƀ , ‹ˆ‘ſƀ , ™ƒ”ſƀ ,
‡””‘”ſƀ и ”‹–‹ ƒŽſƀ;
‰один или несколько объектов журналирования для основной связи с модулем;
‰обработчики, которые направляют значение в терминал, файл, базу данных или
куда-либо еще;
‰средства форматирования выходных данных;
‰фильтры, принимающие решения в зависимости от входных данных.
Рассмотрим простейший пример журналирования — просто импортируем модуль
и воспользуемся некоторыми из его функций:
ʴʴʴ‹’‘”–Ž‘‰‰‹‰
ʴʴʴŽ‘‰‰‹‰Ŝ†‡„—‰ſɑ‘‘•Ž‹‡”ƒ‹ɑƀ
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

ʴʴʴŽ‘‰‰‹‰Ŝ‹ˆ‘ſɑ†Šƒ‹Žɑƀ
ʴʴʴŽ‘‰‰‹‰Ŝ™ƒ”ſɑ‹† Їƒ”–Š—†‡”ţɑƀ
  ś”‘‘–ś‹† Їƒ”–Š—†‡”ţ
ʴʴʴŽ‘‰‰‹‰Ŝ‡””‘”ſɑƒ•–Šƒ–Ž‹‰Š–‹‰ţɑƀ
ś”‘‘–śƒ•–Šƒ–Ž‹‰Š–‹‰ţ
ʴʴʴŽ‘‰‰‹‰Ŝ ”‹–‹ ƒŽſɑ–‘’ˆ‡ ‹‰ƒ†‰‡–‹•‹†‡Šɑƀ
  ś”‘‘–ś–‘’ˆ‡ ‹‰ƒ†‰‡–‹•‹†‡Š

Вы заметили, что вызовы †‡„—‰ſƀ и ‹ˆ‘ſƀ не сделали ничего, а два других вывели
на экран строку dzǰǮǢǥǭǼś”‘‘–ś перед каждым сообщением? Пока они выглядят как
оператор ’”‹–ſƀ, имеющий несколько личностей.
Но это полезно. Вы можете выполнить поиск определенного значения уровня
в журнале с целью найти конкретные сообщения, сравнить временны ' е метки и уви-
деть, что случилось, прежде чем упал ваш сервер, и т. д.
Глубокое погружение в документацию отвечает на первую загадку (на вторую
мы ответим уже через пару страниц): уровень приоритета по умолчанию —   ,
он будет записан в журнал, когда мы вызовем первую функцию (Ž‘‰‰‹‰Ŝ†‡„—‰ſƀ).
Мы можем указать уровень по умолчанию с помощью функции „ƒ•‹ ‘ˆ‹‰ſƀ. Самый
низкий уровень —  , это дает возможность поймать более высокие уровни:
ʴʴʴ‹’‘”–Ž‘‰‰‹‰
ʴʴʴŽ‘‰‰‹‰Ŝ„ƒ•‹ ‘ˆ‹‰ſއ˜‡ŽʰŽ‘‰‰‹‰Ŝ ƀ
ʴʴʴŽ‘‰‰‹‰Ŝ†‡„—‰ſɑ –ɐ•”ƒ‹‹‰ƒ‰ƒ‹ɑƀ
 ś”‘‘–ś –ɐ•”ƒ‹‹‰ƒ‰ƒ‹
ʴʴʴŽ‘‰‰‹‰Ŝ‹ˆ‘ſɑ‹–ŠŠƒ‹Ž–Ї•‹œ‡‘ˆŠƒ‹Ž•–‘‡•ɑƀ
 ś”‘‘–ś‹–ŠŠƒ‹Ž–Ї•‹œ‡‘ˆŠƒ‹Ž•–‘‡•

Мы сделали это с помощью стандартных функций журналирования, не создавая


специализированный объект. Каждый объект журналирования имеет имя. Создадим
объект, который называется bunyan:
ʴʴʴ‹’‘”–Ž‘‰‰‹‰
ʴʴʴŽ‘‰‰‹‰Ŝ„ƒ•‹ ‘ˆ‹‰ſއ˜‡Žʰɐ ɐƀ
ʴʴʴŽ‘‰‰‡”ʰŽ‘‰‰‹‰Ŝ‰‡–‘‰‰‡”ſɐ„—›ƒɐƀ
ʴʴʴŽ‘‰‰‡”Ŝ†‡„—‰ſɐ‹„‡”Šɐƀ
 ś„—›ƒś‹„‡”Š

Если имя объекта журналирования содержит точки, то они разделяют уровни


иерархии таких объектов, каждый из которых потенциально имеет разные приорите-
ты. Это значит, что объект с именем “—ƒ” выше объекта “—ƒ”Ŝ Šƒ”‡†. На вершине
иерархии находится корневой объект журналирования с именем ɐ ɐ.
До сего момента мы только выводили сообщения, и это практически не отлича-
ется от функции ’”‹–ſƀ. Чтобы направить сообщения в разные места назначения,
используем обработчики. Самое распространенное место — файл журнала, напра-
вить туда сообщения можно так:
ʴʴʴ‹’‘”–Ž‘‰‰‹‰
ʴʴʴŽ‘‰‰‹‰Ŝ„ƒ•‹ ‘ˆ‹‰ſއ˜‡Žʰɐ ɐřˆ‹Ž‡ƒ‡ʰɐ„Ž—‡ɏ‘šŜŽ‘‰ɐƀ
ʴʴʴŽ‘‰‰‡”ʰŽ‘‰‰‹‰Ŝ‰‡–‘‰‰‡”ſɐ„—›ƒɐƀ
ʴʴʴŽ‘‰‰‡”Ŝ†‡„—‰ſɑЇ”‡ɐ•›ƒš‡ţɑƀ
ʴʴʴŽ‘‰‰‡”Ŝ™ƒ”ſɑ ‡‡†›ƒš‡ɑƀ
ʴʴʴ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Ага, строки больше не показываются на экране, вместо этого попадают в файл


„Ž—‡ɏ‘šŜŽ‘‰:
 ś„—›ƒśЇ”‡ɐ•›ƒš‡ţ
  ś„—›ƒś ‡‡†›ƒš‡

Вызов функции „ƒ•‹ ‘ˆ‹‰ſƀ и передача имени файла в качестве аргумента


создали для вас объект типа ‹Ž‡ ƒ†Ž‡” и сделали его доступным объекту журна-
лирования. Модуль журналирования содержит как минимум 15 обработчиков для
отправки сообщений в разные места, такие как электронная почта, веб-серверы,
экраны и файлы.
Наконец, вы можете управлять форматом сообщений журнала. В нашем первом
примере использовался формат по умолчанию, в результате чего появилась следу-
ющая строка:
  ś”‘‘–ś‡••ƒ‰‡ŜŜŜ

Если вы предоставите строку ˆ‘”ƒ– функции „ƒ•‹ ‘ˆ‹‰ſƀ, то можете изменить


формат по собственному желанию:
ʴʴʴ‹’‘”–Ž‘‰‰‹‰
ʴʴʴˆ–ʰɐʩſƒ• –‹‡ƀ•ʩſއ˜‡Žƒ‡ƀ•ʩſŽ‹‡‘ƀ•ʩſ‡••ƒ‰‡ƀ•ɐ
ʴʴʴŽ‘‰‰‹‰Ŝ„ƒ•‹ ‘ˆ‹‰ſއ˜‡Žʰɐ ɐřˆ‘”ƒ–ʰˆ–ƀ
ʴʴʴŽ‘‰‰‡”ʰŽ‘‰‰‹‰Ŝ‰‡–‘‰‰‡”ſɐ„—›ƒɐƀ
ʴʴʴŽ‘‰‰‡”Ŝ‡””‘”ſɑЇ”‡ɐ•›‘–Ї”’Žƒ‹†•Š‹”–ţɑƀ
ɩɥɨɫŞɥɫŞɥɯɩɪśɨɪśɬɰřɯɰɰɨЇ”‡ɐ•›‘–Ї”’Žƒ‹†•Š‹”–ţ

Мы позволили объекту журналирования снова отправить выходные данные на


экран, но изменили их формат.
Модуль logging распознал количество имен переменных в строке формата ˆ–.
Мы использовали ƒ• –‹‡ (дата и время как строка ISO 8601), އ˜‡Žƒ‡, lineno
(номер строки) и само сообщение в переменной ‡••ƒ‰‡ . Существуют и другие
встроенные переменные, вы можете предоставить и собственные переменные.
Пакет logging содержит гораздо больше особенностей, чем можно описать
в приведенном небольшом обзоре. Вы можете писать в несколько журналов одно-
временно, указывая разные приоритеты и форматы. Данный пакет довольно гибок,
но иногда это достигается за счет простоты.

ǶȗȚȐȔȐȏȈȞȐȧȒȖȌȈ
Обычно Python довольно быстр, однако иногда его скорости не хватает. В боль-
шинстве случаев вы можете ускорить работу, выбрав более качественный алгоритм
или структуру данных. Идея заключается в том, чтобы знать, где это сделать. Даже
опытные программисты ошибаются довольно часто. Нужно быть очень осторожны-
ми и семь раз отмерить, прежде чем отрезать. Это приводит нас к использованию
таймеров.
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

ǰȏȔȍȘȧȍȔȊȘȍȔȧ
Вы уже видели, что функция –‹‡ модуля –‹‡ возвращает текущее время в фор-
мате ‡’‘ Š как число секунд с плавающей точкой. Быстрый способ засечь время —
получить текущее, что-то сделать, получить новое время и вычесть из него первое.
Напишем соответствующий код, показанный в примере 19.20, и назовем файл
(как бы вы думали?) –‹‡ɨŜ’›.

ǷȘȐȔȍȘWLPHS\
ˆ”‘–‹‡‹’‘”––‹‡

–ɨʰ–‹‡ſƀ
—ʰɬ
—Ƌʰɩ
’”‹–ſ–‹‡ſƀŞ–ɨƀ

Здесь мы измеряем время, которое требуется на присвоение значения ɬ пере-


менной — и умножение его на ɩ. Данный пример не является реалистичным тестом
производительности, это лишь образец того, как замерить время выполнения про-
извольного кода. Попробуйте запустить его несколько раз, чтобы увидеть — время
может варьироваться:
ɛpython [Link]
ɩŜɨɫɬɮɭɮɩɨɨɰɨɫɥɭɩɬ‡Şɥɭ
ɛpython [Link]
ɩŜɨɫɬɮɭɮɩɨɨɰɨɫɥɭɩɬ‡Şɥɭ
ɛpython [Link]
ɩŜɨɫɬɮɭɮɩɨɨɰɨɫɥɭɩɬ‡Şɥɭ
ɛpython [Link]
ɨŜɰɥɮɪɫɯɭɪɩɯɨɩɬ‡Şɥɭ
ɛpython [Link]
ɪŜɥɰɰɫɫɨɬɩɯɪɩɥɪɨɩɬ‡Şɥɭ

Программа работала 2–3 миллионные доли секунды. Попробуем выполнить что-


то помедленнее, скажем функцию •އ‡’ſƀ1. Если мы усыпим выполнение на секунду,
то наш таймер покажет значение чуть больше секунды. В примере 19.21 показан код,
сохраните его в файле под именем –‹‡ɩŜ’›.

ǷȘȐȔȍȘWLPHS\
ˆ”‘–‹‡‹’‘”––‹‡ř•އ‡’

–ɨʰ–‹‡ſƀ
•އ‡’ſɨŜɥƀ
’”‹–ſ–‹‡ſƀŞ–ɨƀ

1
Во многих книгах в примерах, где требуется пропустить какое-то время, приводится расчет
чисел Фибоначчи, но я бы лучше проспал это время.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Чтобы быть уверенными в результатах, запустим программу несколько раз:


ɛpython [Link]
ɨŜɥɥɥɮɰɮɰɯɭɰɯɫɩɬɪ
ɛpython [Link]
ɨŜɥɥɨɥɨɪɥɫɥɬɫɩɭɥɩɬ
ɛpython [Link]
ɨŜɥɥɨɥɪɰɥɩɯɨɭɮɮɩɫɭ

Как и ожидалось, программе для работы требуется около секунды. Если бы это
оказалось не так, то либо нашему таймеру, либо функции •Ž‡‡’ſƀ должно было
стать стыдно.
Существует более удобный способ измерить время выполнения таких фрагмен-
тов кода, как этот, — использование стандартного модуля –‹‡‹– (KWWSELWO\S\WLPHLW).
У него имеется функция с именем, как вы уже догадались, –‹‡‹–ſƀ, которая запу-
стит ваш код заданное количество раз и выведет результаты. Ее синтаксис выглядит
следующим образом: –‹‡‹–Ŝ–‹‡‹–ſȞȢȘř ȫȜȥȟȢř ȞȢȟȜȫșȥȦȖȢɕȤȔțƀ.
В примерах этого подраздела код должен находиться в кавычках, чтобы он вы-
полнялся не после нажатия клавиши 5HWXUQ, а лишь внутри функции –‹‡‹–ſƀ.
(В следующем подразделе вы увидите, как можно измерить время выполнения
некой функции, передав ее имя в функцию –‹‡‹–ſƀ .) Запустим предыдущий
пример и измерим время его выполнения. Назовем этот файл –‹‡‹–ɨŜ’› (при-
мер 19.22).

ǷȘȐȔȍȘWLPHLWS\
ˆ”‘–‹‡‹–‹’‘”––‹‡‹–
’”‹–ſ–‹‡‹–ſɐ—ʰɬڐ—Ƌʰɩɐř—„‡”ʰɨƀƀ

Запустим его несколько раз:


ɛpython [Link]
ɩŜɬɭɥɥɥɩɥɪɥɯɥɫɮɬɪɪ‡Şɥɭ
ɛpython [Link]
ɨŜɰɥɩɥɥɥɯɥɪɰɭɭɥɮɬɩ‡Şɥɭ
ɛpython [Link]
ɨŜɮɪɯɥɥɥɮɨɰɪɫɩɪɯɥɯ‡Şɥɭ

Эти две строки кода снова выполняются примерно за две миллионные доли се-
кунды. Мы можем использовать аргумент repeat функции ”‡’‡ƒ–ſƀ модуля –‹‡‹–,
чтобы выполнить код большее количество раз. Сохраните этот файл под именем
–‹‡‹–ɩŜ’› (пример 19.23).

ǷȘȐȔȍȘWLPHLWS\
ˆ”‘–‹‡‹–‹’‘”–”‡’‡ƒ–
’”‹–ſ”‡’‡ƒ–ſɐ—ʰɬڐ—Ƌʰɩɐř—„‡”ʰɨř”‡’‡ƒ–ʰɪƀƀ

Попробуйте запустить его, чтобы увидеть дальнейшее развитие событий:


ɛpython [Link]
ƃɨŜɭɰɨɰɰɯɫɮɮɪɩɭɮɥɭ‡ŞɥɭřɫŜɥɮɥɥɩɬɨɮɥɩɩɨɰɩɬ‡ŞɥɮřɩŜɫɮɥɥɥɬɮɨɨɥɮɫɰɨɯɬ‡ŞɥɮƄ
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

Первый запуск занял две миллионные доли секунды, а второй и третий про-
шли быстрее. Почему? Так могло произойти по многим причинам. Например, мы
тестировали очень небольшой фрагмент кода и скорость его выполнения зависит
от того, что компьютер делал в эти моменты, как система Python оптимизировала
вычисления, и от многого другого.
Использование –‹‡‹–ſƀ означает, что вы оборачиваете код, производительность
которого измеряете, в строку. А если у вас несколько строк? Вы могли бы передать
их как строку с тройными кавычками, но такую нотацию будет сложно прочитать.
Определим ленивую функцию •‘‘œ‡ſƀ, которая дремлет одну секунду, как и мы
все время от времени.
Для начала обернем саму функцию •‘‘œ‡ſƀ. Нам нужно включить аргументы
‰Ž‘„ƒŽ•ʰ‰Ž‘„ƒŽ•ſƀ (это поможет Python найти функцию •‘‘œ‡) и —„‡”ʰɨ (запу-
стить ее только один раз; по умолчанию используется значение ɨɥɥɥɥɥɥ, а у нас нет
столько времени):
ʴʴʴ‹’‘”––‹‡
ʴʴʴˆ”‘–‹‡‹–‹’‘”––‹‡‹–
ʴʴʴ
ʴʴʴ†‡ˆ•‘‘œ‡ſƀś
ŜŜŜ–‹‡Ŝ•އ‡’ſɨƀ
ŜŜŜ
ʴʴʴ•‡ ‘†•ʰ–‹‡‹–ſɐ•‘‘œ‡ſƀɐř‰Ž‘„ƒŽ•ʰ‰Ž‘„ƒŽ•ſƀř—„‡”ʰɨƀ
ʴʴʴ’”‹–ſɑʩŜɫˆɑʩ•‡ ‘†•ƀ
ɨŜɥɥɪɬ

Или мы можем использовать декоратор:


ʴʴʴ‹’‘”––‹‡
ʴʴʴ
ʴʴʴ†‡ˆ•‘‘œ‡ſƀś
ŜŜŜ–‹‡Ŝ•އ‡’ſɨƀ
ŜŜŜ
ʴʴʴ†‡ˆ–‹‡ɏ†‡ ‘”ƒ–‘”ſˆ— ƀś
ŜŜŜ†‡ˆ‹‡”ſƋƒ”‰•řƋƋ™ƒ”‰•ƀś
ŜŜŜ–ɨʰ–‹‡Ŝ–‹‡ſƀ
ŜŜŜ”‡•—Ž–ʰˆ— ſƋƒ”‰•řƋƋ™ƒ”‰•ƀ
ŜŜŜ–ɩʰ–‹‡Ŝ–‹‡ſƀ
ŜŜŜ’”‹–ſˆɑƇſ–ɩŞ–ɨƀśŜɫˆƈɑƀ
ŜŜŜ”‡–—””‡•—Ž–
ŜŜŜ”‡–—”‹‡”
ŜŜŜ
ʴʴʴɒ–‹‡ɏ†‡ ‘”ƒ–‘”
ŜŜŜ†‡ˆƒ’–‹‡ſƀś
ŜŜŜ•‘‘œ‡ſƀ
ŜŜŜ
ʴʴʴƒ’–‹‡ſƀ
ɨŜɥɥɨɬ

Еще один вариант — задействовать менеджер контекста:


ʴʴʴ‹’‘”––‹‡
ʴʴʴ
ʴʴʴ†‡ˆ•‘‘œ‡ſƀś
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ŜŜŜ–‹‡Ŝ•އ‡’ſɨƀ
ŜŜŜ
ʴʴʴ Žƒ••‹‡‘–‡š–ƒƒ‰‡”ś
ŜŜŜ†‡ˆɏɏ‡–‡”ɏɏſ•‡Žˆƀś
ŜŜŜ•‡ŽˆŜ–ɨʰ–‹‡Ŝ–‹‡ſƀ
ŜŜŜ”‡–—”•‡Žˆ
ŜŜŜ†‡ˆɏɏ‡š‹–ɏɏſ•‡Žˆř–›’‡ř˜ƒŽ—‡ř–”ƒ ‡„ƒ ƀś
ŜŜŜ–ɩʰ–‹‡Ŝ–‹‡ſƀ
ŜŜŜ’”‹–ſˆɑƇſ–ɩŞ•‡ŽˆŜ–ɨƀśŜɫˆƈɑƀ
ŜŜŜ
ʴʴʴ
ʴʴʴ™‹–Š‹‡‘–‡š–ƒƒ‰‡”ſƀś
ŜŜŜ•‘‘œ‡ſƀ
ŜŜŜ
ɨŜɥɥɨɰ

Метод ɏɏ‡š‹–ſƀɏɏ принимает три дополнительных аргумента, которые мы здесь


не использовали; мы могли бы применить *args вместо них.
О’кей, мы узнали множество способов измерить время, за которое выполняется
код. Теперь измерим производительность, сравнив эффективность нескольких алго-
ритмов (программной логики) и структур данных (механизмов хранения).

ǨȓȋȖȘȐȚȔȣȐșȚȘțȒȚțȘȣȌȈȕȕȣȝ
Дзен Python (KWWSELWO\]HQS\) гласит: «Должен существовать один, и желательно
только один, очевидный способ сделать это». К сожалению, иногда способ не явля-
ется очевидным и вам приходится сравнивать альтернативные варианты. Например,
что лучше использовать для создания списка: цикл for или включение списка? И что
на самом деле значит «лучше»: быстрее, проще для понимания, менее затратно по
ресурсам или более характерно для Python?
В следующем упражнении мы создадим список разными способами, сравнив
скорость, читабельность и стиль. Перед вами файл –‹‡ɏŽ‹•–•Ŝ’› (пример 19.24).

ǷȘȐȔȍȘWLPHBOLVWVS\
ˆ”‘–‹‡‹–‹’‘”––‹‡‹–

†‡ˆƒ‡ɏŽ‹•–ɏɨſƀś
”‡•—Ž–ʰƃƄ
ˆ‘”˜ƒŽ—‡‹”ƒ‰‡ſɨɥɥɥƀś
”‡•—Ž–Ŝƒ’’‡†ſ˜ƒŽ—‡ƀ
”‡–—””‡•—Ž–

†‡ˆƒ‡ɏŽ‹•–ɏɩſƀś
”‡•—Ž–ʰƃ˜ƒŽ—‡ˆ‘”˜ƒŽ—‡‹”ƒ‰‡ſɨɥɥɥƀƄ
”‡–—””‡•—Ž–

’”‹–ſɐƒ‡ɏŽ‹•–ɏɨ–ƒ‡•ɐř–‹‡‹–ſƒ‡ɏŽ‹•–ɏɨř—„‡”ʰɨɥɥɥƀřɐ•‡ ‘†•ɐƀ
’”‹–ſɐƒ‡ɏŽ‹•–ɏɩ–ƒ‡•ɐř–‹‡‹–ſƒ‡ɏŽ‹•–ɏɩř—„‡”ʰɨɥɥɥƀřɐ•‡ ‘†•ɐƀ
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

В каждой функции мы добавляем в список 1000 элементов и вызываем каж-


дую функцию 1000 раз. Обратите внимание: в этом тесте мы вызываем функцию
–‹‡‹–ſƀ, передавая ей имя функции в качестве первого аргумента вместо кода.
Запустим ее:
ɛpython time_lists.py

ƒ‡ɏŽ‹•–ɏɨ–ƒ‡•ɥŜɨɫɨɨɮɫɩɯɭɰɰɭɯɩɰɪɩ•‡ ‘†•
ƒ‡ɏŽ‹•–ɏɩ–ƒ‡•ɥŜɥɭɨɮɫɨɫɬɰɥɥɨɫɰɬɰɮ•‡ ‘†•

Включение списка отработало как минимум в два раза быстрее, чем добавление
элементов в список с помощью функции ƒ’’‡†ſƀ. Как правило, включение быстрее,
чем создание вручную.
Используйте эти идеи, чтобы ускорить свой код.

&\WKRQ1XP3\ȐȘȈșȠȐȘȍȕȐȧ&
Если вы усердно работаете, но все еще не можете достичь необходимой произво-
дительности, то у вас есть и другие варианты.
Cython (KWWSF\WKRQRUJ) — гибрид языков Python и C, разработанный для преоб-
разования Python: в скомпилированный код языка С внесены некоторые улучшения
производительности. Эти аннотации относительно малы, они похожи на объявление
типов некоторых переменных, аргументов функций или возвращаемых функциями
значений. Подобные подсказки значительно ускорят научные вычисления, вы-
полняющиеся в циклах, — в 1000 раз. Документацию и примеры см. в Cython wiki
(KWWSVRUHLOO\0P:BY).
В главе 22 вы можете подробнее узнать о NumPy. Это математическая библио-
тека Python, написанная для ускорения на С.
Многие части Python и его стандартной библиотеки написаны на С для скорости
и обернуты кодом на Python для удобства. При написании приложений эти приемы
доступны и вам. Если вы знаете С и Python и действительно хотите, чтобы ваш код
«летал», то напишите расширение на языке С — это труднее, но улучшение оправ-
дает затраченные усилия.

3\3\
Около 20 лет назад, когда язык Java только появился, он был медленным, как
шнауцер, больной артритом. Но когда он стал дорого стоить компании Sun и про-
чим, они вложили миллионы в оптимизацию интерпретатора Java и лежащей в его
основе виртуальной машины Java (Java Virtual Machine, JVM), заимствуя приемы
из уже существовавших тогда языков Smalltalk и LISP. Компания Microsoft также
вложила много усилий в оптимизацию своего языка C# и .NET VM.
У языка Python нет владельца, поэтому никто так сильно не старается сделать его
быстрее. Возможно, вы используете стандартную реализацию Python. Она написана
на С и часто называется CPython (не путать с Cython).
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Как и языки PHP, Perl и даже Java, Python не компилируется в машинный код,
он преобразуется в промежуточный язык (называемый байт-кодом или p-кодом),
который затем интерпретирует виртуальная машина.
PyPy (KWWSS\S\RUJ) — это новый интерпретатор Python, который пользуется
некоторыми приемами, ускорившими язык программирования Java. Тесты произ-
водительности интерпретатора (KWWSVSHHGS\S\RUJ) показывают, что PyPy в каждом
тесте быстрее CPython в среднем более чем в шесть раз и до 20 раз в отдельных
случаях. PyPy работает с Python 2 и 3. Вы можете скачать его и использовать вместо
CPython. PyPy постоянно улучшается и однажды может заменить CPython. Чтобы
узнать, подходит ли он вам, посетите его официальный сайт.

1XPED
Вы можете использовать пакет Numba (KWWSQXPEDS\GDWDRUJ), чтобы динамически
скомпилировать свой код в машинный и ускорить его.
Устанавливается этот пакет так же, как и другие:
ɛpip install numba

Сначала измерим время выполнения функции, которая высчитывает гипотенузу:


ʴʴʴ‹’‘”–ƒ–Š
ʴʴʴˆ”‘–‹‡‹–‹’‘”––‹‡‹–
ʴʴʴˆ”‘—„ƒ‹’‘”–Œ‹–
ʴʴʴ
ʴʴʴ†‡ˆŠ›’‘–ſƒř„ƀś
ŜŜŜ”‡–—”ƒ–ŠŜ•“”–ſƒƋƋɩʫ„ƋƋɩƀ
ŜŜŜ
ʴʴʴ–‹‡‹–ſɐŠ›’‘–ſɬřɭƀɐř‰Ž‘„ƒŽ•ʰ‰Ž‘„ƒŽ•ſƀƀ
ɥŜɭɪɫɰɨɯɰɩɯɥɥɥɥɨɯɰ
ʴʴʴ–‹‡‹–ſɐŠ›’‘–ſɬřɭƀɐř‰Ž‘„ƒŽ•ʰ‰Ž‘„ƒŽ•ſƀƀ
ɥŜɭɪɫɯɬɯɰɩɪɰɰɰɰɯɬɪ

Используйте декоратор ɒŒ‹–, чтобы ускорить все вызовы после первого:


ʴʴʴɒŒ‹–
ŜŜŜ†‡ˆŠ›’‘–ɏŒ‹–ſƒř„ƀś
ŜŜŜ”‡–—”ƒ–ŠŜ•“”–ſƒƋƋɩʫ„ƋƋɩƀ
ŜŜŜ
ʴʴʴ–‹‡‹–ſɐŠ›’‘–ɏŒ‹–ſɬřɭƀɐř‰Ž‘„ƒŽ•ʰ‰Ž‘„ƒŽ•ſƀƀ
ɥŜɬɪɰɭɨɬɭɥɰɰɰɰɰɰɯɬ
ʴʴʴ–‹‡‹–ſɐŠ›’‘–ɏŒ‹–ſɬřɭƀɐř‰Ž‘„ƒŽ•ʰ‰Ž‘„ƒŽ•ſƀƀ
ɥŜɨɬɪɫɮɮɨɨɪɥɥɥɥɥɯɨ

Примените декоратор ɒŒ‹–ſ‘’›–Š‘ʰ”—‡ƀ, чтобы избежать накладных расходов,


связанных с использованием обычного интерпретатора Python:
ʴʴʴɒŒ‹–ſ‘’›–Š‘ʰ”—‡ƀ
ŜŜŜ†‡ˆŠ›’‘–ɏŒ‹–ɏ‘’›ſƒř„ƀś
ŜŜŜ”‡–—”ƒ–ŠŜ•“”–ſƒƋƋɩʫ„ƋƋɩƀ
ŜŜŜ
ʴʴʴ–‹‡‹–ſɐŠ›’‘–ɏŒ‹–ɏ‘’›ſɬřɭƀɐř‰Ž‘„ƒŽ•ʰ‰Ž‘„ƒŽ•ſƀƀ
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

ɥŜɨɯɪɫɪɬɪɬɮɥɥɥɥɥɮɬɮ
ʴʴʴ–‹‡‹–ſɐŠ›’‘–ɏŒ‹–ɏ‘’›ſɬřɭƀɐř‰Ž‘„ƒŽ•ʰ‰Ž‘„ƒŽ•ſƀƀ
ɥŜɨɬɪɯɮɥɭɮɪɥɥɥɥɩɯɬɬ

Пакет Numba особенно полезен в связке с NumPy и другими пакетами, выпол-


няющими вычисления.

ǻȗȘȈȊȓȍȕȐȍȐșȝȖȌȕȣȔȒȖȌȖȔ
Работая над небольшой группой программ, вы обычно можете отслеживать измене-
ния, внесенные собственноручно, — до тех пор пока не сделаете глупую ошибку и не
потеряете несколько дней работы. Системы управления исходным кодом защитят
ваш код от сил зла в лице вас самих. Если вы работаете в группе, то управление исход-
ным кодом становится необходимостью. Для этой области было создано множество
коммерческих и бесплатных решений. Наиболее популярные в мире открытого ис-
ходного кода (где и живет Python) — Mercurial и Git. Они оба являются примерами
распределенных систем контроля версий, которые создают несколько копий репо-
зиториев кода. Ранние системы наподобие Subversion работают на одном сервере.

0HUFXULDO
Mercurial (KWWSPHUFXULDOVFPRUJ) написан на Python. Научиться пользоваться им
довольно легко, он имеет множество подкоманд для скачивания кода из репозито-
рия Mercurial, добавления файлов, проверки на наличие изменений и объединения
изменений из разных источников. Сайт bitbucket (KWWSVELWEXFNHWRUJ) и другие пред-
лагают бесплатный или коммерческий хостинг.

*LW
Изначально Git (KWWSJLWVFPFRP) создавался для разработки ядра Linux, но теперь
является доминирующим в области открытого исходного кода в целом. Он похож
на Mercurial, хотя некоторые считают, что обучиться ему сложнее. GitHub (KWWS
JLWKXEFRP) — это самый крупный хостинг для git, содержащий более миллиона
репозиториев, но существует и множество других хостов (KWWSELWO\JLWKRVWVFP).
Отдельные примеры программ из этой книги доступны в публичном репозито-
рии git на GitHub (KWWSVRUHLOO\85P\). Если у вас установлена программа git, то
вы можете скачать примеры с помощью следующей команды:
ɛgit clone [Link]

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


‰&ORQHLQ'HVNWRS (Клонировать на рабочий стол), чтобы открыть версию git, уста-
новленную на ваш компьютер;
‰'RZQORDG=,3 (Загрузить архив), чтобы получить архивированную версию про-
грамм.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Если у вас нет git , но вы хотите попробовать поработать с ним, то прочтите


инструкцию по установке (KWWSELWO\JLWLQVWDOO). Здесь я буду говорить о версии с ко-
мандной строкой, но вам могут быть интересны сайты наподобие GitHub, предо-
ставляющие дополнительные услуги, которые в ряде случаев использовать было бы
проще: git имеет много возможностей, но не всегда интуитивно понятен.
Проведем тест-драйв. Далеко уходить не будем, просто посмотрим, как работают
некоторые команды.
Создадим новый каталог и перейдем в него:
ɛmkdir newdir
ɛcd newdir

Создадим локальный репозиторий git в текущем каталоге QHZGLU:


ɛgit init

‹–‹ƒŽ‹œ‡†‡’–› ‹–”‡’‘•‹–‘”›‹ŵ•‡”•ŵ™‹ŽŽ‹ƒŽ—„ƒ‘˜‹ ŵ‡™†‹”ŵŜ‰‹–ŵ

Создадим в каталоге QHZGLU файл с кодом, который называется –‡•–Ŝ’› (показан


в примере 19.25), содержащий следующее.

ǷȘȐȔȍȘWHVWS\
’”‹–ſɐ‘’•ɐƀ

Добавим файл в репозиторий git:


ɛgit add [Link]

Что вы об этом думаете, мистер git?


ɛgit status

„”ƒ Šƒ•–‡”

‹–‹ƒŽ ‘‹–

Šƒ‰‡•–‘„‡ ‘‹––‡†ś
ſ—•‡ɑ‰‹–”ŞŞ ƒ Ї†ʳˆ‹Ž‡ʴŜŜŜɑ–‘—•–ƒ‰‡ƀ

‡™ˆ‹Ž‡ś–‡•–Ŝ’›

Это значит, что файл –‡•–Ŝ’› стал частью локального репозитория, но изменения
еще не были отправлены. Исправим данное обстоятельство:
ɛgit commit -m "simple print program"

ƃƒ•–‡”ſ”‘‘–Ş ‘‹–ƀɬɩ†ɭɥ†ɮƄ›ˆ‹”•– ‘‹–


ɨˆ‹Ž‡ Šƒ‰‡†řɨ‹•‡”–‹‘ſʫƀ
 ”‡ƒ–‡‘†‡ɨɥɥɭɫɫ–‡•–Ŝ’›

Строка Ş ɑ› first ‘‹–ɑ — ваш комментарий. Если вы опустите ее, то git
выведет на экран редактор и тем самым предложит вам ввести сообщение. Оно ста-
новится частью истории изменений нашего файла.
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

Взглянем на текущий статус:


ɛgit status

„”ƒ Šƒ•–‡”
‘–Š‹‰–‘ ‘‹–ř™‘”‹‰†‹”‡ –‘”› އƒ

О’кей, все текущие изменения были отправлены. Это значит, что мы можем ме-
нять содержимое файла и не беспокоиться о потере его оригинала. Внесем изменение
в файл –‡•–Ŝ’› — заменим ‘’• на ’•Š и сохраним файл (пример 19.26).

ǷȘȐȔȍȘǪȖȏȊȘȈȡȈȍȔșȧȒWHVWS\
’”‹–ſɐ’•Šɐƀ

Посмотрим, что теперь думает git:


ɛgit status

„”ƒ Šƒ•–‡”
Šƒ‰‡•‘–•–ƒ‰‡†ˆ‘” ‘‹–ś
ſ—•‡ɑ‰‹–ƒ††ʳˆ‹Ž‡ʴŜŜŜɑ–‘—’†ƒ–‡™Šƒ–™‹ŽŽ„‡ ‘‹––‡†ƀ
ſ—•‡ɑ‰‹– Ї ‘—–ŞŞʳˆ‹Ž‡ʴŜŜŜɑ–‘†‹• ƒ”† Šƒ‰‡•‹™‘”‹‰†‹”‡ –‘”›ƀ

‘†‹ˆ‹‡†ś–‡•–Ŝ’›

‘ Šƒ‰‡•ƒ††‡†–‘ ‘‹–ſ—•‡ɑ‰‹–ƒ††ɑƒ†ŵ‘”ɑ‰‹– ‘‹–ރɑƀ

Используйте команду git †‹ˆˆ, чтобы увидеть, какие строки изменились с момен-
та последней отправки:
ɛgit diff

†‹ˆˆŞŞ‰‹–ƒŵ–‡•–Ŝ’›„ŵ–‡•–Ŝ’›
‹†‡šɮɭ„ɯ ɪɰŜŜɭɩɮɯɩ„ɩɨɥɥɭɫɫ
ŞŞŞƒŵ–‡•–Ŝ’›
ʫʫʫ„ŵ–‡•–Ŝ’›
ɒɒŞɨʫɨɒɒ
Ş’”‹–ſɐ‘’•ɐƀ
ʫ’”‹–ſɐ’•Šɐƀ

Если вы попробуете отправить это изменение сейчас, то git пожалуется:


ɛgit commit -m "change the print string"

„”ƒ Šƒ•–‡”
Šƒ‰‡•‘–•–ƒ‰‡†ˆ‘” ‘‹–ś
‘†‹ˆ‹‡†ś–‡•–Ŝ’›

‘ Šƒ‰‡•ƒ††‡†–‘ ‘‹–

Фраза •–ƒ‰‡† for ‘‹– означает, что вам нужно добавить файл; в примерном
переводе она выглядит как «Эй, git, смотри сюда!»:
ɛgit add [Link]
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Вы также могли ввести команду git ƒ†† Ŝ, чтобы добавить все измененные фай-
лы в текущий каталог, — это удобно, когда вы изменили несколько файлов с целью
гарантировать отправку всех изменений. Теперь можно отправить изменения:
ɛgit commit -m "my first change"

ƃƒ•–‡”‡ɨ‡ɨɨ‡ Ƅ›ˆ‹”•– Šƒ‰‡


ɨˆ‹Ž‡ Šƒ‰‡†řɨ‹•‡”–‹‘ſ咎—•Śƀřɨ†‡Ž‡–‹‘ſŞƀ

Если вы хотите увидеть все те ужасные вещи, которые проделывали с файлом


–‡•–Ŝ’›, начиная с недавних, то используйте команду git log:
ɛgit log [Link]
 ‘‹–‡ɨ‡ɨɨ‡ ˆɯɥɩƒ‡ɨƒɮɯ†‡„‡ɭɨɰɪ ɬɬɩ† †ɨɬ ƒɨɭɥƒ
—–Š‘”ś‹ŽŽ‹ƒ—„ƒ‘˜‹ ʳ„‹ŽŽɒƒ†• Ї‡Ŝ ‘ʴ
ƒ–‡ś—‡ƒ›ɨɪɩɪśɪɫśɬɰɩɥɨɫŞɥɬɥɥ

 Šƒ‰‡–Ї’”‹–•–”‹‰

 ‘‹–ɬɩ†ɭɥ†ɮɭɬɰɫƒɭɩɩɰɰˆɭˆ†ɬɭɨ„ɩɫɫɭ ɯ„ɨɩɩɮ ˆ‡ɨ


—–Š‘”ś‹ŽŽ‹ƒ—„ƒ‘˜‹ ʳ„‹ŽŽɒƒ†• Ї‡Ŝ ‘ʴ
ƒ–‡ś—‡ƒ›ɨɪɩɪśɩɭśɨɫɩɥɨɫŞɥɬɥɥ

•‹’އ’”‹–’”‘‰”ƒ

ǸȈșȗȘȖșȚȘȈȕȍȕȐȍȊȈȠȐȝȗȘȖȋȘȈȔȔ
Вы знаете, что ваши файлы нужно установить в файлы и каталоги, а также то, что
программу, написанную на Python, можно запустить с помощью интерпретатора.
Менее известен тот факт, что интерпретатор Python тоже может выполнять код,
размещенный в архивах ZIP. Еще менее известно то, что особые архивы, которые на-
зываются pex-файлами (KWWSVSH[UHDGWKHGRFVLR), также могут быть скомпилированы.

DzȓȖȕȐȘțȑȚȍȥȚțȒȕȐȋț
Вы можете получить копию всех программ из данной книги. Посетите репозито-
рий Git (KWWSVRUHLOO\)E)$() и следуйте инструкциям по их копированию на ваш
локальный компьютер. Если у вас есть git, то запустите команду git Ž‘‡ Š––’•śŵŵ
‰‹–Š—„Ŝ ‘ŵƒ†• Ї‡ŵ‹–”‘†— ‹‰Ş’›–Š‘, чтобы создать репозиторий Git на вашем
компьютере. Вы также можете загрузить файлы в формате ZIP.

DzȈȒțȏȕȈȚȤȉȖȓȤȠȍ
Вы прочитали лишь введение. Скорее всего, в нем говорится слишком много о не-
нужном вам и слишком мало о том, что вам интересно. Позвольте мне порекомен-
довать ресурсы, связанные с Python, которые я считаю полезными.
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

DzȕȐȋȐ
Я обнаружил, что книги, представленные в следующем списке, особенно полез-
ны. Их уровень варьируется от начального до продвинутого, в них описываются
и Python 2, и Python 3.
‰Бизли Д., Джонс Б. Python. Книга рецептов. — М.: ДМК-Пресс, 2020.
‰Рейтц К., Шлюссер Т. Автостопом по Python. — СПб.: Питер, 2017.
‰Barry P. Head First Python (2nd Edition). — O’Reilly, 2016.
‰Beazley D. M. Python Essential Reference. 5th ed. — Addison-Wesley, 2019.
‰Gorelick M., Ozsvald I. High Performance Python. — O’Reilly, 2014.
‰Maxwell A. Powerful Python. — Powerful Python Press, 2017.
‰McKinney W. Python for Data Analysis: Data Wrangling with Pandas, NumPy and
IPython. — O’Reilly, 2012.
‰Ramalho L. Fluent Python. — O’Reilly, 2015.
‰Slatkin B. Effective Python. — Addison-Wesley, 2015.
‰Summerfield M. Python in Practice: Create Better Programs Using Concurrency,
Libraries and Patterns. — Addison-Wesley, 2013.
Конечно же, хороших книг гораздо больше (KWWSVZLNLS\WKRQRUJPRLQ3\WKRQ%RRNV).

ǹȈȑȚȣ
Вот несколько сайтов, где вы можете найти полезные руководства:
‰Python for You and Me (KWWSVS\PERRNUHDGWKHGRFVLR) — введение в Python, в ко-
тором также рассматриваются нюансы работы с ОС Windows;
‰Real Python (KWWSUHDOS\WKRQFRP) — многие авторы внесли свой вклад в создание
этих руководств;
‰Learn Python the Hard Way (KWWSOHDUQS\WKRQWKHKDUGZD\RUJERRN), автор Зед Шоу;
‰Dive Into Python 3 (KWWSVRUHLOO\8-F*0), автор Марк Пилгрим;
‰Mouse Vs. Python (KWWSZZZEORJS\WKRQOLEUDU\RUJ), автор Майкл Дрисколл.
Если вам интересно узнавать о том, что происходит в мире Python, то обратите
внимание на эти новостные сайты:
‰[Link] (KWWSELWO\FRPSODQJS\WKRQ);
‰[Link] (KWWSELWO\FRPSODQJS\DQQRXQFH);
‰r/python subreddit (KWWSZZZUHGGLWFRPUS\WKRQ);
‰Planet Python (KWWSSODQHWS\WKRQRUJ).
Наконец, рассмотрим сайты, с которых можно скачать разнообразные пакеты:
‰The Python Package Index (KWWSVS\SLS\WKRQRUJS\SL);
‰Awesome Python (KWWSVDZHVRPHS\WKRQFRP);
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰Stack Overflow Python Questions (KWWSVRUHLOO\6Y(/);


‰ActiveState Python recipes (KWWSFRGHDFWLYHVWDWHFRPUHFLSHVODQJVS\WKRQ);
‰Python packages trending on GitHub (KWWSVJLWKXEFRPWUHQGLQJ"O S\WKRQ).

ǫȘțȗȗȣ
В сообществах программистов вы можете найти широкий диапазон типажей: энту-
зиастов, спорщиков, глупцов, хипстеров, интеллигентов — и множество других. Со-
общество Python довольно дружелюбно. В зависимости от вашего местонахождения
вы можете найти группы, увлекающиеся Python (KWWSS\WKRQPHHWXSFRP). Проводят
встречи и местные пользовательские группы по всему миру (KWWSVZLNLS\WKRQRUJ
PRLQ/RFDO8VHU*URXSV). Другие группы распределены по всему миру и основываются
на общих интересах. Например, PyLadies (KWWSZZZS\ODGLHVFRP) — сеть женщин,
заинтересованных в Python и ПО с открытым исходным кодом.

DzȖȕȜȍȘȍȕȞȐȐ
Самые крупные из множества конференций (KWWSZZZS\FRQRUJ) и совещаний по
всему миру (KWWSVZZZS\WKRQRUJFRPPXQLW\ZRUNVKRSV) проводятся в Северной Аме-
рике (KWWSVXVS\FRQRUJ) и Европе (KWWSVHXURS\WKRQHXHQ).

ǪȈȒȈȕșȐȐșȊȧȏȈȕȕȣȍș3\WKRQ
Чтобы найти вакансии, связанные с Python, воспользуйтесь следующими сайтами:
‰Indeed (KWWSVZZZLQGHHGFRP);
‰Stack Overflow (KWWSVVWDFNRYHUIORZFRPMREV);
‰ZipRecruiter (KWWSVZZZ]LSUHFUXLWHUFRPFDQGLGDWHVXJJHVWHGMREV);
‰Simply Hired (KWWSVZZZVLPSO\KLUHGFRP);
‰CareerBuilder (KWWSVZZZFDUHHUEXLOGHUFRP);
‰Google (KWWSVZZZJRRJOHFRPVHDUFK"T MREV);
‰LinkedIn (KWWSVZZZOLQNHGLQFRPMREVVHDUFK).
На большей части этих сайтов введите слово python в первой строке поиска и ваше
местоположение во второй. Среди хороших локальных сайтов могу порекомендо-
вать Craigslist, эта ссылка, например, работает для Сиэтла (KWWSVVHDWWOHFUDLJVOLVWRUJ
VHDUFKMMM). Просто измените seattle на sfbay, boston, › или другой префикс сайта
Craigslist, чтобы выполнить поиск в других районах. Для поиска вакансий Python,
подразумевающих удаленную работу (на базе дистанционного доступа или «работу
из дома»), воспользуйтесь следующими сайтами:
‰Indeed (KWWSVRUHLOO\S)4ZE);
‰Google (KWWSVRUHLOO\/,);
‰LinkedIn (KWWSVRUHLOO\QK9V);
ǫȓȈȊȈǩȣȚȤȗȐȚȖȕȡȐȒȖȔ  

‰Stack Overflow (KWWSVRUHLOO\57[);


‰Remote Python (KWWSVRUHLOO\E3:,);
‰We Work Remotely (KWWSVRUHLOO\FV&);
‰ZipRecruiter (KWWSVRUHLOO\RKZ$<);
‰Glassdoor (KWWSVRUHLOO\W.I);
‰Remotely Awesome Jobs (KWWSVRUHLOO\0N0HJ);
‰Working Nomads (KWWSVRUHLOO\X+9();
‰GitHub (KWWSVRUHLOO\VPPU=).

ǿȐȚȈȑȚȍȌȈȓȍȍ
Но погодите, это еще не конец! В следующих трех главах вы можете узнать, как
использовать Python в искусстве, бизнесе и науке. Вы найдете как минимум одну
область для исследований. В Сети можно отыскать множество блестящих объектов.
Только вы сможете сказать, какие из них — бижутерия, а какие — серебряные пули.
И даже если вас в данный момент не преследуют оборотни, серебряные пули могут
пригодиться. На всякий случай.
Наконец, вы узнаете ответы на все эти раздражающие упражнения в конце
каждой главы, детали установки Python и его друзей, а также получите несколько
вспомогательных таблиц для вещей, которые мне постоянно нужно подсматривать.
Ваш мозг, скорее всего, лучше подготовлен, но так они всегда будут под рукой.

ǻȗȘȈȎȕȍȕȐȧ
Питонщикам сегодня ничего не задавали.
ƋƓƈƊƈ
ǷȐǨȘȚ

Ну, искусство есть искусство, не так ли? С другой


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

Граучо Маркс

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


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

ǬȊțȔȍȘȕȈȧȋȘȈȜȐȒȈ
Все языки программирования в какой-то степени работают с компьютерной гра-
фикой. Многие мощные платформы в этом приложении в целях быстродействия
были написаны на С или С++, но для продуктивности добавлены библиотеки
Python. Начнем с рассмотрения некоторых библиотек для работы с двумерными
изображениями.

ǹȚȈȕȌȈȘȚȕȈȧȉȐȉȓȐȖȚȍȒȈ
В стандартной библиотеке содержатся всего несколько модулей, связанных с изо-
бражениями. Рассмотрим два из них:
‰‹‰Š†” — этот модуль определяет тип некоторых файлов изображений;
‰ ‘Ž‘”•›• — этот модуль преобразует цвета между разными системами: RGB, YIQ,
HSV и HLS.
ǫȓȈȊȈǷȐǨȘȚ  

Если вы загрузили логотип издательства O’Reilly и сохранили его под именем


‘”‡‹ŽŽ›Ŝ’‰, то можете запустить этот код:
ʴʴʴ‹’‘”–‹‰Š†”
ʴʴʴ‹‰Š†”Ŝ™Šƒ–ſɐ‘”‡‹ŽŽ›Ŝ’‰ɐƀ
ɐ’‰ɐ

Еще одна стандартная библиотека называется turtle (KWWSVRUHLOO\EY(]), она


иногда используется для обучения молодых людей программированию. Вы можете
запустить демонстрацию с помощью следующей команды:
ɛpython -m turtledemo

На рис. 20.1 показан снимок экрана, на котором демонстрируется пример розетки.

ǸȐșǰȏȖȉȘȈȎȍȕȐȍȐȏWXUWOHGHPR

Чтобы сделать с графикой в Python нечто серьезное, нужно загрузить сторонние


пакеты. Рассмотрим их.

3,/Ȑ3LOORZ
Многие годы библиотека изображений Python (Python Image Library, PIL) (KWWS
ELWO\S\LPDJH), несмотря на ее отсутствие в стандартной библиотеке, является самой
известной библиотекой для обработки двумерных изображений. Она предшествова-
ла таким установщикам, как pip, поэтому был создан «дружественный форк» с на-
званием Pillow (KWWSSLOORZUHDGWKHGRFVRUJ). Код для работы с изображениями Pillow
совместим с кодом PIL, а его документация хороша, поэтому используем его здесь.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Установить его просто — достаточно ввести следующую команду:


ɛpip install Pillow

Если вы уже устанавливали пакеты Ž‹„Œ’‡‰, libfreetype и œŽ‹„, то они будут об-
наружены и использованы Pillow. На странице с инструкциями по установке (KWWS
ELWO\SLOORZLQVWDOO) вы узнаете больше.
Откроем файл изображения:
ʴʴʴˆ”‘ ‹’‘”– ƒ‰‡
ʴʴʴ‹‰ʰ ƒ‰‡Ŝ‘’‡ſɐ‘”‡‹ŽŽ›Ŝ’‰ɐƀ
ʴʴʴ‹‰Ŝˆ‘”ƒ–
ɐ ɐ
ʴʴʴ‹‰Ŝ•‹œ‡
ſɨɬɫřɨɫɨƀ
ʴʴʴ‹‰Ŝ‘†‡
ɐ ɐ

Хоть пакет и называется ‹ŽŽ‘™, вы импортируете его как  , чтобы код был
совместим со старым  .
Чтобы отобразить изображение на экране с помощью метода •Š‘™ſƀ объекта
ƒ‰‡, вы сначала должны установить пакет ImageMagick, описанный в следующем
подразделе, а затем попробовать вот что:
ʴʴʴ‹‰Ŝ•Š‘™ſƀ

Изображение, показанное на рис. 20.2, открывается в другом окне. (Этот сни-


мок экрана был сделан на компьютере Mac, где функция •Š‘™ſƀ используется для
приложения предварительного просмотра изображений. Отображение ваших окон
может быть иным.)

ǸȐșǰȏȖȉȘȈȎȍȕȐȍȗȖȓțȟȍȕȕȖȍșȗȖȔȖȡȤȦȉȐȉȓȐȖȚȍȒȐȐȏȖȉȘȈȎȍȕȐȑ3\WKRQ

Обрежем изображение в памяти, сохраним результат как новый объект с име-


нем ‹‰ɩ и отобразим его. Изображения всегда измеряются в горизонтальных (х)
и вертикальных (у) значениях. Один из углов изображения называется стартовой
точкой (origin), его значения х и у равны 0. В этой библиотеке origin (0, 0) находится
в левом верхнем углу изображения, х увеличивается при смещении вправо, а у — при
ǫȓȈȊȈǷȐǨȘȚ  

смещении вниз. Мы хотим задать значения левого края х (55), верхнего края у (70),
правого края х (85) и нижнего края у (100) для метода ”‘’ſƀ, поэтому передаем
кортеж, содержащий эти значения в соответствующем порядке:
ʴʴʴ ”‘’ʰſɬɬřɮɥřɯɬřɨɥɥƀ
ʴʴʴ‹‰ɩʰ‹‰Ŝ ”‘’ſ ”‘’ƀ
ʴʴʴ‹‰ɩŜ•Š‘™ſƀ

Результат показан на рис. 20.3.

ǸȐșǶȉȘȍȏȈȕȕȖȍȐȏȖȉȘȈȎȍȕȐȍ

Сохраним изображение с помощью метода •ƒ˜‡ſƀ. Он принимает имя файла


и опциональный путь. Если у имени файла есть суффикс, то библиотека использует
его, чтобы определить тип. Но вы также можете указать тип файла явно. Сохранить
изображение с расширением GIF можно, проделав следующее:
ʴʴʴ‹‰ɩŜ•ƒ˜‡ſɐ ”‘’’‡†Ŝ‰‹ˆɐřɐ ɐƀ
ʴʴʴ‹‰ɪʰ ƒ‰‡Ŝ‘’‡ſɐ ”‘’’‡†Ŝ‰‹ˆɐƀ
ʴʴʴ‹‰ɪŜˆ‘”ƒ–
ɐ ɐ
ʴʴʴ‹‰ɪŜ•‹œ‡
ſɪɥřɪɥƀ

В качестве последнего примера «улучшим» наш маленький талисман. Сначала


загрузим копию исходного изображения нашего зверька, показанную на рис. 20.4.
У него какая-то неопрятная тень, повернутая на пять часов, поэтому найдем изо-
бражение, которое позволит улучшить его образ (рис. 20.5).

ǸȐșǵȈȠȔȐȓȣȑȏȊȍȘȍȒ ǸȐșǰȕȖȗȓȈȕȍȚȕȈȧȚȍȝȕȖȓȖȋȐȧ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Объединим их, используя магию альфа-канала, чтобы сделать пересечение полу-


прозрачным, как показано в примере 20.1.

ǷȘȐȔȍȘFKBFULWWHUS\
ˆ”‘ ‹’‘”– ƒ‰‡

”‹––‡”ʰ ƒ‰‡Ŝ‘’‡ſɐ Šɩɥɏ ”‹––‡”Ŝ’‰ɐƀ


•–ƒ Їʰ ƒ‰‡Ŝ‘’‡ſɐ Šɩɥɏ•–ƒ ЇŜ’‰ɐƀ
•–ƒ ЇŜ’—–ƒŽ’Šƒſɨɥɥƀ
‹‰ʰ ƒ‰‡Ŝ‡™ſɐ ɐř ”‹––‡”Ŝ•‹œ‡řſɩɬɬřɩɬɬřɩɬɬřɥƀƀ
‹‰Ŝ’ƒ•–‡ſ ”‹––‡”řſɥřɥƀƀ
‹‰Ŝ’ƒ•–‡ſ•–ƒ Їřſɫɬřɰɥƀřƒ•ʰ•–ƒ Їƀ
‹‰Ŝ•Š‘™ſƀ ǸȐșǵȈȠ
ȕȖȊȣȑȉȖȓȍȍ
На рис. 20.6 показан новый образ зверька. ȖȗȘȧȚȕȣȑȚȈȓȐșȔȈȕ

,PDJH0DJLFN
ImageMagick (KWWSZZZLPDJHPDJLFNRUJ) — это комплект программ для конверти-
рования, изменения и отображения двумерных изображений. Он существует более
20 лет. Различные библиотеки Python подключены к библиотеке ImageMagick,
написанной на С. Самая недавняя из них, поддерживающая Python 3, называется
wand (KWWSGRFVZDQGS\RUJ). Чтобы установить ее, введите следующую команду:
ɛpip install Wand

Библиотека ™ƒ† позволяет делать примерно то же, что и Pillow:


ʴʴʴˆ”‘™ƒ†Ŝ‹ƒ‰‡‹’‘”– ƒ‰‡
ʴʴʴˆ”‘™ƒ†Ŝ†‹•’Žƒ›‹’‘”–†‹•’Žƒ›
ʴʴʴ
ʴʴʴ‹‰ʰ ƒ‰‡ſˆ‹Ž‡ƒ‡ʰɐ‘”‡‹ŽŽ›Ŝ’‰ɐƀ
ʴʴʴ‹‰Ŝ•‹œ‡
ſɨɬɫřɨɫɨƀ
ʴʴʴ‹‰Ŝˆ‘”ƒ–
ɐ ɐ

Как и в случае с Pillow, эта строка отобразит изображение на экране:


ʴʴʴ†‹•’Žƒ›ſ‹‰ƀ

Благодаря ™ƒ† можно поворачивать изображение, изменять его размер, писать


текст, рисовать линии и многое другое, что вы можете найти и в Pillow. Оба этих
пакета имеют хорошие API и документацию.

ǺȘȍȝȔȍȘȕȈȧȋȘȈȜȐȒȈ
Для работы с трехмерной графикой в Python существуют следующие пакеты:
‰VPython (KWWSVYS\WKRQRUJ) содержит примеры (KWWSVRUHLOO\-W), которые вы
можете запустить в своем браузере;
ǫȓȈȊȈǷȐǨȘȚ  

‰pi3d (KWWSVSLGJLWKXELR) работает на базе Raspberry Pi, Windows, Linux и Android;


‰Open3D (KWWSZZZRSHQGRUJGRFV) — это полноценная библиотека для работы
с трехмерной графикой.

ǺȘȍȝȔȍȘȕȈȧȈȕȐȔȈȞȐȧ
Посмотрите длинные финальные титры любого современного фильма, и вы увидите
огромное количество людей, занимавшихся спецэффектами и анимацией. Боль-
шинство крупных студий: Walt Disney Animation, ILM, Weta, Dreamworks, Pixar —
нанимают людей, имеющих опыт работы с Python. Поищите в Интернете «python
анимация работа», чтобы увидеть действующие предложения.
Далее показаны некоторые пакеты Python для работы с 3D.
‰Panda3D (KWWSZZZSDQGDGRUJ) — этот пакет имеет открытый исходный код,
и его можно использовать бесплатно даже для создания коммерческих приложе-
ний. Вы можете скачать его версию с сайта Panda3D (KWWSELWO\GOSDQGD).
‰VPython (KWWSVYS\WKRQRUJ) — поставляется с большим количеством примеров
(KWWSVRUHLOO\-W).
‰Blender (KWWSZZZEOHQGHURUJ) — это бесплатное средство создания 3D-анимации
и игр. Если вы скачаете и установите его (KWWSZZZEOHQGHURUJGRZQORDG), то на ваш
компьютер также будет установлена копия Python 3.
‰Maya (KWWSVRUHLOO\3K:Q) — это коммерческая система для создания 3D-анимации
и графики. Она поставляется вместе с версией Python — в данный момент
Python 2.7. Чед Вернон написал о ней бесплатно загружаемую книгу Python
Scripting for Maya Artists (KWWSELWO\S\PD\D). Если вы поищете в Интернете ин-
формацию о Python и Maya, то сможете найти множество других ресурсов, как
бесплатных, так и коммерческих, включая видеоролики.
‰Houdini (KWWSVZZZVLGHI[FRP) — это коммерческий пакет, однако вы можете
скачать бесплатную версию, которая называется Apprentice. Как и другие пакеты
для анимации, он поставляется с привязкой к Python (KWWSVRUHLOO\/&U).

ǫȘȈȜȐȟȍșȒȐȍȗȖȓȤȏȖȊȈȚȍȓȤșȒȐȍ
ȐȕȚȍȘȜȍȑșȣ *8,
Название содержит слово «графический», но GUI (Graphical User Interface) кон-
центрируется скорее на пользовательском интерфейсе: виджетах для представления
данных, методах ввода, меню, кнопках и окнах.
Страница «Википедии» GUI programming (KWWSELWO\JXLSURJUDP) и список часто
задаваемых вопросов (KWWSELWO\JXLIDT) содержат множество примеров GUI, создан-
ных с помощью Python. Начнем с единственного встроенного в стандартную библио-
теку примера — Tkinter (KWWSVZLNLS\WKRQRUJPRLQ7N,QWHU). Он прост, но работает на
всех платформах и создает естественно выглядящие окна и виджеты.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Рассмотрим небольшую программу, в которой используется Tkinter. Она ото-


бражает наш любимый талисман в отдельном окне:
ʴʴʴ‹’‘”––‹–‡”
ʴʴʴˆ”‘ ‹’‘”– ƒ‰‡ř ƒ‰‡
ʴʴʴ
ʴʴʴƒ‹ʰ–‹–‡”Ŝſƀ
ʴʴʴ‹‰ʰ ƒ‰‡Ŝ‘’‡ſɐ‘”‡‹ŽŽ›Ŝ’‰ɐƀ
ʴʴʴ–‹‰ʰ ƒ‰‡ŜŠ‘–‘ ƒ‰‡ſ‹‰ƀ
ʴʴʴ–‹–‡”Ŝƒ„‡Žſƒ‹ř‹ƒ‰‡ʰ–‹‰ƀŜ’ƒ ſƀ
ʴʴʴƒ‹Ŝƒ‹Ž‘‘’ſƀ

Обратите внимание: мы использовали некоторые модули


PIL/Pillow. Вы снова должны увидеть логотип издательства
O’Reilly, как показано на рис. 20.7.
Чтобы окно пропало, нажмите кнопку &ORVH (Закрыть)
или выйдите из интерпретатора Python.
О библиотеке Tkinker вы можете прочитать в tkinter wiki
(KWWSVZLNLS\WKRQRUJPRLQ7N,QWHU). Теперь поговорим о GUI,
которые не входят в стандартную библиотеку.
‰Qt (KWWSTWSURMHFWRUJ). Это профессиональный инстру- ǸȐșǰȏȖȉȘȈȎȍȕȐȍ
ментарий для создания GUI и приложений, созданный ȗȖȒȈȏȈȕȕȖȍșȗȖȔȖȡȤȦ
около 20 лет назад норвежской компанией Trolltech. ȉȐȉȓȐȖȚȍȒȐ7NLQWHU
Использовался для создания таких приложений, как
Google Earth, Maya и Skype. Кроме того, применен как основа для KDE, графиче-
ской оболочки Linux. Для Qt существуют две основные библиотеки, работающие
с Python: PySide (KWWSTWSURMHFWRUJZLNL3\6LGH) бесплатна (по лицензии LGPL),
а PyQt (KWWSELWO\S\TWLQIR) лицензирована либо с GPL, либо коммерчески. Поль-
зователи Qt видят разницу (KWWSELWO\TWGLII). Скачать PySide можно с сайтов
PyPI (KWWSVS\SLS\WKRQRUJS\SL3\6LGH) или Qt (KWWSTWSURMHFWRUJZLNL*HW3\6LGH),
а также прочесть руководство (KWWSTWSURMHFWRUJZLNL3\6LGHB7XWRULDOV). Скачать Qt
бесплатно можно здесь: KWWSELWO\TWGO.
‰GTK+ (KWWSZZZJWNRUJ). Соперник Qt, также был использован для создания
множества приложений, таких как GIMP и оболочки Gnome для Linux. Для
Python используется PyGTK (KWWSZZZS\JWNRUJ). Чтобы скачать код, перейдите
на сайт PyGTK (KWWSELWO\S\JWNGO), где также можете прочитать документацию
(KWWSELWO\S\JWNGRFV).
‰WxPython (KWWSZZZZ[S\WKRQRUJ). Это привязка Python к WxWidgets (KWWS
ZZZZ[ZLGJHWVRUJ), представляющему еще один крупный пакет, который можно
бесплатно скачать онлайн (KWWSZ[S\WKRQRUJGRZQORDGSKS).
‰Kivy (KWWSNLY\RUJ). Это бесплатная современная библиотека для создания муль-
тимедийных интерфейсов пользователя, которые можно переносить на другие
платформы: стационарные (Windows, OS X, Linux) и мобильные (Android, iOS).
Включает поддержку мультитача. Вы можете скачать ее для всех платформ с сай-
ǫȓȈȊȈǷȐǨȘȚ  

та Kivy (KWWSNLY\RUJGRZQORDG). Библиотека содержит руководства по разработке


приложений (KWWSELWO\NLY\LQWUR).
‰PySimpleGUI (KWWSVS\VLPSOHJXLUHDGWKHGRFVLR). Создайте нативный или основан-
ный на веб интерфейс с помощью одной библиотеки. PySimpleGUI представляет
собой оболочку для других интерфейсов, упомянутых в этом разделе, включая
Tk, Kivy и Qt.
‰The Web. Такие фреймворки, как Qt, используют встроенные компоненты, но не-
которые другие программы применяют Web. Это универсальный GUI, содержа-
щий графику (SVG), текст (HTML) и даже мультимедиа (в HTML5). Вы можете
создать веб-приложения с любой комбинацией фронтенда (клиентской части)
и бэкенда (машинного интерфейса) инструментов. Тонкий клиент позволяет
бэкенду делать всю работу. Если доминирует фронтенд, то клиент называется
толстым или насыщенным; последний эпитет звучит более льстиво. Части при-
ложения могут общаться друг с другом с помощью RESTful API, AJAX и JSON.

ǬȐȈȋȘȈȔȔȣȋȘȈȜȐȒȐȐȊȐȏțȈȓȐȏȈȞȐȧ
Python — отличный инструмент для создания диаграмм, графиков и визуализации
данных и особенно популярен в научной среде (см. главу 22). Полезные обзоры
с примерами встречаются в официальной Python wiki (KWWSVRUHLOO\:GWHU) и Python
Graph Gallery (KWWSVS\WKRQJUDSKJDOOHU\FRP).
Рассмотрим самые популярные. В следующей главе вы снова увидите некоторые
из них, но они будут использованы для создания карт.

0DWSORWOLE
Бесплатную библиотеку для создания двумерных диаграмм Matplotlib (KWWS
PDWSORWOLERUJ) можно установить с помощью следующей команды:
ɛpip install matplotlib

Примеры из галереи (KWWSPDWSORWOLERUJJDOOHU\KWPO) показывают широту этой


библиотеки.
Попробуем написать такое же приложение для показа изображений (результаты
можно увидеть на рис. 20.8) только для того, чтобы увидеть, как будут выглядеть
код и презентация:
‹’‘”–ƒ–’Ž‘–Ž‹„Ŝ’›’Ž‘–ƒ•’Ž‘–
‹’‘”–ƒ–’Ž‘–Ž‹„Ŝ‹ƒ‰‡ƒ•‹ƒ‰‡

‹‰ʰ‹ƒ‰‡Ŝ‹”‡ƒ†ſɐ‘”‡‹ŽŽ›Ŝ’‰ɐƀ
’Ž‘–Ŝ‹•Š‘™ſ‹‰ƀ
’Ž‘–Ŝ•Š‘™ſƀ

Реальная мощь Matplotlib заключается в построении графиков (plotting), что


в целом понятно по средней части ее названия. Создадим два списка, каждый из
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

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

ǸȐșǰȏȖȉȘȈȎȍȕȐȍȗȖȒȈȏȈȕȕȖȍșȗȖȔȖȡȤȦȉȐȉȓȐȖȚȍȒȐ0DWSORWOLE

ǷȘȐȔȍȘ20.2.FKBPDWSORWOLES\
‹’‘”–ƒ–’Ž‘–Ž‹„Ŝ’›’Ž‘–ƒ•’Ž–
ˆ”‘”ƒ†‘‹’‘”–”ƒ†‹–

Ž‹‡ƒ”ʰŽ‹•–ſ”ƒ‰‡ſɨřɩɨƀƀ
™‹‰‰Ž›ʰŽ‹•–ſ—ʫ”ƒ†‹–ſŞɨřɨƀˆ‘”—‹Ž‹‡ƒ”ƀ

ˆ‹‰ř’Ž‘–•ʰ’Ž–Ŝ•—„’Ž‘–•ſ”‘™•ʰɨř ‘Ž•ʰɪƀ

–‹ •ʰŽ‹•–ſ”ƒ‰‡ſɥřɩɨřɬƀƀ
ˆ‘”’Ž‘–‹’Ž‘–•ś
’Ž‘–Ŝ•‡–ɏš–‹ •ſ–‹ •ƀ
’Ž‘–Ŝ•‡–ɏ›–‹ •ſ–‹ •ƀ

’Ž‘–•ƃɥƄŜ• ƒ––‡”ſŽ‹‡ƒ”ř™‹‰‰Ž›ƀ
’Ž‘–•ƃɨƄŜ’Ž‘–ſŽ‹‡ƒ”ř™‹‰‰Ž›ƀ
’Ž‘–•ƃɩƄŜ’Ž‘–ſŽ‹‡ƒ”ř™‹‰‰Ž›řɐ‘Şɐƀ

’Ž–Ŝ•Š‘™ſƀ
ǫȓȈȊȈǷȐǨȘȚ  

Если вы запустите эту программу, то получите результат, похожий на тот, что


представлен на рис. 20.9 (он не будет полностью идентичен, поскольку каждый вы-
зов функции ”ƒ†‹–ſƀ возвращает новый результат).

ǸȐșǩȈȏȖȊȣȍȋȘȈȜȐȒȐ0DWSORWOLE ȌȐȈȋȘȈȔȔȈȘȈșșȍȐȊȈȕȐȧ
ȐȓȐȕȍȑȕȣȍȋȘȈȜȐȒȐ

В этом примере показаны диаграмма рассеивания, линейный график и линейный


график с отметками. При их создании были использованы стили по умолчанию, но
внешний вид графиков можно изменять. Для получения более подробной инфор-
мации обратитесь к сайту Matplotlib (KWWSVPDWSORWOLERUJ) или к обзору, например
Python Plotting With Matplotlib (Guide) (KWWSVRUHLOO\7B[G7).
В главе 22 мы еще вернемся к Matplotlib — она тесно связана с NumPy и другими
научными приложениями.

6HDERUQ
Seaborn (KWWSVVHDERUQS\GDWDRUJ) — это библиотека для визуализации данных
(рис. 20.10), построенная на основе Matplotlib и имеющая соединение с Pandas.
Для нее работает базовая мантра инсталляции (pip install seaborn).
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǸȐșǩȈȏȖȊȈȧȌȐȈȋȘȈȔȔȈȘȈșșȍȐȊȈȕȐȧȐȗȘȧȔȖȓȐȕȍȑȕȈȧȘȍȋȘȍșșȐȧȊ6HDERUQ

Код, показанный в примере 20.3, основан на примере использования Seaborn


(KWWSVRUHLOO\H%)*L); он получает доступ к тестовым данным о чаевых в ресторане
и строит график зависимости чаевых от общей суммы счета, добавляя прямолиней-
ную регрессию.

ǷȘȐȔȍȘFKBVHDERUQS\
‹’‘”–•‡ƒ„‘”ƒ•••
‹’‘”–ƒ–’Ž‘–Ž‹„Ŝ’›’Ž‘–ƒ•’Ž–

–‹’•ʰ••ŜŽ‘ƒ†ɏ†ƒ–ƒ•‡–ſɑ–‹’•ɑƀ
••Ŝ”‡‰’Ž‘–ſšʰɑ–‘–ƒŽɏ„‹ŽŽɑř›ʰɑ–‹’ɑř†ƒ–ƒʰ–‹’•ƀŚ

’Ž–Ŝ•Š‘™ſƀ

ǷȘȐȏȈȗțșȒȍȌȈȕȕȖȋȖȒȖȌȈșȗȖȔȖȡȤȦșȚȈȕȌȈȘȚȕȖȋȖȐȕȚȍȘȗȘȍȚȈȚȖȘȈ3\WKRQȊȈȔȗȖ
ȕȈȌȖȉȐȚșȧțȒȈȏȈȚȤȗȍȘȊțȦșȚȘȖȒțȐȔȗȖȘȚȈ LPSRUWPDWSORWOLES\SORWDVSOW ȐȗȖșȓȍȌ
ȕȦȦșȚȘȖȒț SOWVKRZ ȒȈȒȗȖȒȈȏȈȕȖȊȗȘȐȔȍȘȍȐȕȈȟȍȋȘȈȜȐȒȕȍȖȚȖȉȘȈȏȐȚșȧ
ǭșȓȐȊȣȐșȗȖȓȤȏțȍȚȍ-XS\WHUȚȖȉȐȉȓȐȖȚȍȒȈ0DWSORWOLEțȎȍȊșȚȘȖȍȕȈȊșȘȍȌț²ȕȍȚ
ȕȍȖȉȝȖȌȐȔȖșȚȐȍȍȐȔȗȖȘȚȐȘȖȊȈȚȤǷȖȔȕȐȚȍȥȚȖȒȖȋȌȈȉțȌȍȚȍȐșșȓȍȌȖȊȈȚȤȗȘȐȔȍȘȣ
ȒȖȌȈȘȈȉȖȚȈȦȡȍȋȖșȐȕșȚȘțȔȍȕȚȈȔȐȗȖșȚȘȖȍȕȐȧȒȈȘȚȊ3\WKRQ
ǫȓȈȊȈǷȐǨȘȚ  

Как и Matplotlib, Seaborn предоставляет широкий спектр возможностей по об-


работке и отображению данных.

%RNHK
На заре существования Интернета разработчики генерировали графику на сервере
и давали браузеру URL для доступа к ней. С недавних пор JavaScript повысил свою
производительность и получил инструменты генерации графики на стороне клиента,
такие как D3. Пару страниц назад я говорил о возможности использовать Python
как часть архитектуры фронтенд-бэкенд-графики и GUIs. Новый инструмент, кото-
рый называется Bokeh (KWWSERNHKS\GDWDRUJ), совмещает плюсы Python (крупные
наборы данных, простота использования) и JavaScript (интерактивность, меньшая
латентность графики). Bokeh делает акцент на быстрой визуализации крупных на-
боров данных.
Если вы уже установили необходимые для Bokeh пакеты (NumPy, Pandas
и Redis), то можете установить и сам этот инструмент, введя следующую команду:
ɛpip install bokeh

(NumPy и Pandas в действии вы сможете увидеть в главе 22.)


Или же можете установить все сразу с сайта Bokeh (KWWSVRUHLOO\)\/). Несмо-
тря на то что на сервере запущен Matplotlib, Bokeh в основном работает в браузере
и может пользоваться всеми новыми возможностями клиентской стороны. Нажмите
любое изображение в галерее (KWWSVRUHLOO\':1G), чтобы получить интерактивное
представление дисплея и его код Python.

ǰȋȘȣ
Оказывается, Python — настолько хорошая платформа для написания игр, что об
этом пишут книги, например:
‰Invent Your Own Computer Games with Python, автор Эл Свайгарт (KWWSLQYHQWZLWK
S\WKRQFRP)1;
‰The Python Game Book, автор Хорст Йенс (книга в формате docuwiki) (KWWS
WKHS\WKRQJDPHERRNFRP).

В Python wiki (KWWSVZLNLS\WKRQRUJPRLQ3\WKRQ*DPHV) вы можете найти статью,


в которой содержится еще большее количество ссылок.
Самая известная платформа для написания игр, скорее всего, pygame (KWWS
S\JDPHRUJ). Вы можете скачать исполняемый установщик для своей платформы
с сайта Pygame (KWWSS\JDPHRUJGRZQORDGVKWPO) и прочесть построчный пример соз-
дания игры (KWWSVRUHLOO\OVZS).

1
Свайгарт Эл. Учим Python, делая крутые игры. — М.: Эксмо, 2017.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǨțȌȐȖȐȔțȏȣȒȈ
I sought the serif
But that did not suit Claude Debussy1.
Deservedly Anonymous

Что насчет звука, музыки и котов, которые поют Jingle Bells? Ну, как говорит
Meatloaf, два из трех — это не так плохо.
В напечатанной книге звук представить сложно, так что взгляните на эти акту-
альные ссылки на пакеты Python, предназначенные для работы со звуком и музыкой.
С помощью Google вы можете найти намного больше:
‰модули стандартной библиотеки для работы с аудио (KWWSGRFVS\WKRQRUJOLEUDU\
PPKWPO);
‰сторонние инструменты для работы с аудио (KWWSVZLNLS\WKRQRUJPRLQ$XGLR);
‰десятки сторонних музыкальных (KWWSVZLNLS\WKRQRUJPRLQ3\WKRQ,Q0XVLF) прило-
жений: графические и CLI-проигрыватели, преобразователи, нотации, анализ,
плейлисты, MIDI и др.
Наконец, как насчет онлайн-источников музыки? На протяжении этой книги вы
видели примеры кода, которые получали доступ к Internet Archive. Вот ссылки на
некоторые из аудио-архивов:
‰аудиозаписи (KWWSVDUFKLYHRUJGHWDLOVDXGLR) (> 5 000 000);
‰живая музыка (KWWSVDUFKLYHRUJGHWDLOVHWUHH) (> 200 000);
‰живые концерты группы Grateful Dead (KWWSVDUFKLYHRUJGHWDLOV*UDWHIXO'HDG )
(> 13 000).

ǿȐȚȈȑȚȍȌȈȓȍȍ
Имитируем бурную деятельность! В дело вступает Python.

ǻȗȘȈȎȕȍȕȐȧ
20.1. Установите ƒ–’Ž‘–Ž‹„. Нарисуйте диаграмму рассеивания для следующих
пар ſšř ›ƀ: ( ſɥř ɥƀ, ſɪřɬƀ, ſɭř ɩƀ, ſɰř ɯƀ, ſɨɫř ɨɥƀ ƀ.
20.2. Нарисуйте линейчатый график на основе тех же данных.
20.3. Нарисуйте график на основе тех же данных.

1
Обыгрывается строка из песни I shot the Sheriff. — Примеч. пер.
ƋƓƈƊƈ
ǯȈȘȈȉȖȚȖȑ

— Дела! — вскричал призрак, снова заламывая руки. — Забота


о ближнем — вот что должно было стать моим делом…
Чарльз Диккенс. Рождественские повести

Униформа бизнесмена — костюм и галстук. Но прежде чем взяться за дело, он ве-


шает пиджак на спинку стула, ослабляет галстук, закатывает рукава и наливает себе
кофе. Тем временем женщина-бизнесмен уже выполняет свою работу. Может быть,
возьмет латте.
В области бизнеса и правительства мы используем все технологии из предыду-
щих глав — базы данных, веб-системы и сети. Продуктивность Python делает его
более популярным и для корпораций (KWWSELWO\S\HQWHUSULVH), и для стартапов (KWWS
ELWO\S\VWDUWXSV).
Бизнес долго боролся с несовместимыми форматами файлов, скрытыми сетевыми
протоколами, обязательными языками и общей нехваткой точной документации.
Он может создавать более быстрые, более дешевые эластичные приложения, поль-
зуясь следующими инструментами:
‰динамическими языками, такими как Python;
‰сетью как универсальным графическим интерфейсом пользователя;
‰RESTful API как независимыми от языка интерфейсами сервисов;
‰реляционными и NoSQL-базами данных;
‰«большими данными» и аналитикой;
‰облаками для развертывания и экономии капитала.

7KH0LFURVRIW2IILFH6XLWH
Бизнес сильно зависит от приложений Microsoft Office и форматов файлов. Несмо-
тря на то что эти библиотеки Python не очень широко известны и в ряде случаев
плохо задокументированы, они могут пригодиться. Рассмотрим некоторые из них,
работающие с документами Microsoft Office:
‰docx (KWWSVS\SLS\WKRQRUJS\SLGRF[) — эта библиотека создает, считывает и запи-
сывает файлы для Microsoft Office Word 2007 с расширением Ŝ†‘ š;
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰python-excel (KWWSZZZS\WKRQH[FHORUJ) — здесь с помощью PDF-руководства


(KWWSELWO\S\H[FHO) рассматриваются модули šŽ”†, šŽ™– и šŽ—–‹Ž•. Excel также
может читать и записывать файлы, содержащие значения, разделенные запятыми
(Comma-Separated Value, CSV), с которыми вы уже умеете работать с помощью
стандартного модуля •˜;
‰oletools (KWWSELWO\ROHWRROV) — эта библиотека извлекает данные из форматов Office.
OpenOffice (KWWSRSHQRIILFHRUJ) — альтернатива Office, имеющая открытый ис-
ходный код. Работает в операционных системах Linux, Unix, Windows и macOS,
а также читает и записывает форматы файлов Office. Кроме того, это приложение
устанавливает версию Python 3 для себя. Вы можете запрограммировать OpenOffice
с помощью Python (KWWSVRUHLOO\P/L&U) и библиотеки PyUNO (KWWSVRUHLOO\)$61%).
OpenOffice принадлежал компании Sun Microsystems, и когда компания Oracle
приобрела компанию Sun, некоторые люди стали опасаться, что OpenOffice в буду-
щем станет недоступен. В результате появился LibreOffice (KWWSVZZZOLEUHRIILFHRUJ).
В DocumentHacker (KWWSELWO\GRFXKDFNHU) вы можете прочитать об использовании
библиотеки Python UNO вместе с LibreOffice.
Для создания OpenOffice и LibreOffice пришлось выполнить реверс-инжиниринг
форматов файлов Microsoft, что не так просто. Модуль Universal Office Converter
(KWWSGDJZLHHUVKRPHPDGHXQRFRQY) зависит от библиотеки UNO в OpenOffice или
LibreOffice. Он может преобразовывать файлы многих форматов: документы,
электронные таблицы, графику и презентации.
Если у вас имеется таинственный файл, то python-magic (KWWSVS\SLRUJSURMHFW
S\WKRQPDJLF) может угадать его формат, проанализировав определенные последо-
вательности байтов.
Библиотека python open document (KWWSDSS\IUDPHZRUNRUJSRGKWPO) позволяет
предоставить код Python внутри шаблонов для создания динамических документов.
Формат PDF распространен также в области бизнеса, несмотря на то что создан
не компанией Microsoft. Движок ReportLab (KWWSZZZUHSRUWODEFRPRSHQVRXUFH) имеет
бесплатную и коммерческую версии генератора PDF, созданные с помощью Python.
Если вам нужно отредактировать PDF-файл, то можете найти помощь на сайте
StackOverflow (KWWSELWO\DGGWH[WSGI).

ǪȣȗȖȓȕȧȍȔȉȐȏȕȍșȏȈȌȈȟȐ
Вы можете найти модуль Python практически для чего угодно. Посетите сайт PyPI
(KWWSVS\SLS\WKRQRUJS\SL) и введите что-либо в строку поиска. Многие модули — это
интерфейсы для общедоступных API различных сервисов. Вам могут быть интерес-
ны примеры, связанные с бизнес-задачами:
‰отправка через Fedex (KWWSVJLWKXEFRPJWD\ORUS\WKRQIHGH[) или UPS (KWWSVJLWKXEFRP
RSHQODEV3\836);
‰отправка почты с помощью API [Link] (KWWSVJLWKXEFRPM]HPSHOVWDPSV);
ǫȓȈȊȈǯȈȘȈȉȖȚȖȑ  

‰прочтите дискуссию о применении Python для корпоративного интеллекта (KWWS


ELWO\S\EL]);
‰если кофемашины слетают с полок в Аноке, то это результат действий покупателя
или полтергейст? Cubes (KWWSFXEHVGDWDEUHZHU\RUJ) — это веб-сервер и браузер
данных Online Analytical Processing (OLAP);
‰OpenERP (KWWSVZZZRSHQHUSFRP) — крупная коммерческая система Enterprise
Resource Planning (ERP), написанная с помощью Python и JavaScript, содержа-
щая тысячи модулей-надстроек.

ǶȉȘȈȉȖȚȒȈȉȐȏȕȍșȌȈȕȕȣȝ
Бизнес очень любит данные. К сожалению, во многих отраслях бизнеса с данными
принято обращаться весьма своеобразно, словно для того, чтобы специально услож-
нить вам работу.
Электронные таблицы стали хорошим изобретением, и с течением времени
бизнес пристрастился к ним. Многие непрограммисты стали заниматься програм-
мированием, поскольку эти таблицы стали называть макросами, а не программами.
Но Вселенная постоянно расширяется, и данные пытаются выдержать ее темп. Более
старые версии Excel были ограничены 65 536 рядами, а более новые не могли об-
работать больше миллиона. Когда данные организаций переросли один компьютер,
ситуация стала похожа на то, как если бы штат перерос сотню человек, — внезапно
вам требуются новые слои, промежуточные уровни и коммуникация.
Программы, работающие с большим количеством данных, появились не из-за
того, что данные на одном компьютере значительно разрослись, — они стали ре-
зультатом попытки обобщить все данные, появляющиеся в бизнесе. Реляционные
базы данных обрабатывают миллионы рядов, не взрываясь при этом, но могут взаи-
модействовать только с определенным количеством рядов или обновлений за раз.
Старые добрые текстовые или бинарные файлы могут занимать гигабайты памяти,
но если вам нужно обработать их все одновременно, то требуется иметь достаточное
количество памяти. Традиционное программное обеспечение для этого не подходит.
Таким компаниям, как Google и Amazon, пришлось изобрести решения, позволя-
ющие работать с данными такого масштаба. Netflix (KWWSELWO\S\QHWIOL[) — пример
такого решения, созданный в облаке AWS от Amazon, который использует Python
для объединения RESTful API, безопасности, развертывания и баз данных.

ǰȏȊȓȍȟȍȕȐȍȗȘȍȖȉȘȈȏȖȊȈȕȐȍȐȏȈȋȘțȏȒȈ
Подводные части айсбергов данных содержат всю работу по получению данных
в первую очередь. Если говорить языком бизнеса, распространенными терминами
являются «извлечение», «преобразование», «загрузка» (extract, transform, load, или
ETL). Синонимы наподобие «выпас данных» (data munging, data wrangling) могут
создать впечатление, будто вы приручаете непокорного зверя, — такая метафора
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

может оказаться близкой. Данная задача выглядит решенной с точки зрения инже-
нерии, но по большей части это искусство. Я немного говорил об этом в главе 12.
Мы рассмотрим науку о данных более подробно в главе 22, поскольку именно на эту
область разработчики тратят бо' льшую часть времени.
Если вы видели фильм «Волшебник страны Оз», то, помимо летающих обезьян,
должны помнить фрагмент в конце, когда добрая волшебница сказала Дороти, что
она может отправиться домой в Канзас, просто стукнув каблучком о каблучок.
Даже будучи моложе, я думал: «И она говорит об этом только сейчас?!» Хотя теперь
понимаю, что фильм был бы гораздо короче, если бы волшебница дала такой совет
раньше.
Вот только мы живем не в фильме, здесь мы говорим о мире бизнеса, где со-
кращение времени на выполнение задач — это хорошо. Позвольте мне поделиться
с вами парой советов. Большинство инструментов, которые вам понадобятся для
повседневной работы с данными в бизнесе, вы уже знаете, поскольку прочитали
о них в этой книге. Среди таких инструментов высокоуровневые структуры данных,
например словари и объекты, тысячи стандартных и сторонних библиотек, а также
сообщество экспертов, которое можно найти в поисковике.
Если вы программист, пишущий программы для бизнеса, то ваш рабочий процесс
практически всегда содержит следующее.
1. Извлечение данных из файлов странных форматов или баз данных.
2. Очистку данных, которая охватывает множество областей, заполненных подвод-
ными камнями.
3. Преобразование дат, времени и наборов символов.
4. Выполнение каких-либо действий над данными.
5. Сохранение полученного результата в базе данных.
6. Откат к шагу 1: намылить, смыть, повторить.
Рассмотрим пример: вам нужно переместить данные из электронной таблицы
в базу данных. Вы можете сохранить таблицу в формате CSV и использовать би-
блиотеки Python, показанные в главе 16. Или же найти модуль, который считывает
непосредственно бинарный формат электронной таблицы. Ваши пальцы знают, как
набрать строку python ‡š ‡Ž в поисковике и найти сайты наподобие Working with
Excel files in Python (KWWSZZZS\WKRQH[FHORUJ). Вы можете установить один из не-
обходимых пакетов с помощью pip и найти драйвер базы данных для Python, чтобы
выполнить последнюю часть задания. Я упоминал SQLAlchemy и непосредственные
драйверы базы данных в той же главе. Теперь вам нужно написать промежуточный
код, и именно здесь структуры данных и библиотеки Python могут сэкономить ваше
время.
Попробуем выполнить поставленную задачу, а затем решить ее снова, но уже ис-
пользуя библиотеки, которые позволяют сэкономить немного времени. Мы считаем
CSV-файл, агрегируем все числа в одном столбце, упорядочив их по уникальному
значению, и выведем результат на экран. Если бы мы решали задачу с помощью SQL,
то применили бы SELECT, JOIN и GROUP BY.
ǫȓȈȊȈǯȈȘȈȉȖȚȖȑ  

Для начала рассмотрим файл œ‘‘Ŝ •˜, который содержит следующую инфор-
мацию: тип животного, сколько раз оно укусило посетителя, количество потребо-
вавшихся швов и сумма, которую мы заплатили посетителю за то, чтобы он ничего
не говорил журналистам:
ƒ‹ƒŽř„‹–‡•ř•–‹– Ї•řŠ—•Š
„‡ƒ”řɨřɪɬřɪɥɥ
ƒ”‘•‡–řɨřɩřɩɬɥ
„‡ƒ”řɩřɫɩřɬɥɥ
‡Žřɨřɪɥřɨɥɥ
™‡ƒ•‡Žřɫřɮřɬɥ
†— řɩřɥřɨɥ

Мы хотим узнать, какое животное обходится нам дороже всего, поэтому агреги-
руем общую сумму взяток для каждого типа животного (количеством укусов и швов
пусть займется врач). Мы используем модуль •˜, который рассматривали в подраз-
деле «CSV» на с. 328, и счетчик ‘—–‡” из подраздела «Подсчитываем элементы
с помощью Counter()» на с. 233. Сохраните этот код как œ‘‘ɏ ‘—–•Ŝ’›:
‹’‘”– •˜
ˆ”‘ ‘ŽŽ‡ –‹‘•‹’‘”–‘—–‡”

‘—–•ʰ‘—–‡”ſƀ
™‹–Š‘’‡ſɐœ‘‘Ŝ •˜ɐřɐ”–ɐƀƒ•ˆ‹ś
 ‹ʰ •˜Ŝ”‡ƒ†‡”ſˆ‹ƀ
ˆ‘”—ř”‘™‹‡—‡”ƒ–‡ſ ‹ƀś
‹ˆ—ʴɥś
 ‘—–•ƃ”‘™ƃɥƄƄʫʰ‹–ſ”‘™ƃŞɨƄƀ
ˆ‘”ƒ‹ƒŽřŠ—•Š‹ ‘—–•Ŝ‹–‡•ſƀś
’”‹–ſɑʩɨɥ•ʩɨɥ•ɑʩſƒ‹ƒŽřŠ—•Šƀƀ

Мы пропустили первый ряд, поскольку в нем содержались только имена колонок.


Элемент ‘—–• — это объект типа ‘—–‡”, он управляет инициализацией суммы для
каждого типа животного, устанавливая ее равной 0. Мы также применили форма-
тирование, чтобы выровнять выводимую информацию по правому краю. Запустим
наш код:
ɛ’›–Š‘œ‘‘ɏ ‘—–•Ŝ’›
†— ɨɥ
‡Žɨɥɥ
„‡ƒ”ɯɥɥ
™‡ƒ•‡Žɬɥ
ƒ”‘•‡–ɩɬɥ

Ага! Это был медведь! Он был нашим основным подозреваемым все время, но
теперь у нас есть доказательства.
Далее воссоздадим этот пример с инструментария для обработки данных
Bubbles (KWWSEXEEOHVGDWDEUHZHU\RUJ). Вы можете установить его, введя следующую
команду:
ɛpip install bubbles
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Он требует наличия SQLAlchemy. Если у вас его нет, то вам поможет команда pip
install •“ŽƒŽ Š‡›. Так выглядит тестовая программа (назовите файл „—„„އ•ɨŜ’›),
адаптированная из документации (KWWSELWO\S\EXEEOHV):
‹’‘”–„—„„އ•

’ʰ„—„„އ•Ŝ‹’‡Ž‹‡ſƀ
’Ŝ•‘—” ‡ſ„—„„އ•Ŝ†ƒ–ƒɏ‘„Œ‡ –ſɐ •˜ɏ•‘—” ‡ɐřɐœ‘‘Ŝ •˜ɐř‹ˆ‡”ɏˆ‹‡Ž†•ʰ”—‡ƀƀ
’Ŝƒ‰‰”‡‰ƒ–‡ſɐƒ‹ƒŽɐřɐŠ—•Šɐƀ
’Ŝ’”‡––›ɏ’”‹–ſƀ

А теперь момент истины:


ɛpython [Link]
ɩɥɨɫŞɥɪŞɨɨɨɰśɫɭśɪɭřɯɥɭ  ƒŽŽ‹‰ƒ‰‰”‡‰ƒ–‡ſ”‘™•ƀ
ɩɥɨɫŞɥɪŞɨɨɨɰśɫɭśɪɭřɯɥɮ   ƒŽŽ‡†ƒ‰‰”‡‰ƒ–‡ſ”‘™•ƀ
ɩɥɨɫŞɥɪŞɨɨɨɰśɫɭśɪɭřɯɥɮ  ƒŽŽ‹‰’”‡––›ɏ’”‹–ſ”‡ ‘”†•ƀ
ʫŞŞŞŞŞŞŞŞʫŞŞŞŞŞŞŞŞʫŞŞŞŞŞŞŞŞŞŞŞŞʫ
Ŷƒ‹ƒŽŶŠ—•Šɏ•—Ŷ”‡ ‘”†ɏ ‘—–Ŷ
ʫŞŞŞŞŞŞŞŞʫŞŞŞŞŞŞŞŞʫŞŞŞŞŞŞŞŞŞŞŞŞʫ
Ŷ†— ŶɨɥŶɨŶ
Ŷ™‡ƒ•‡ŽŶɬɥŶɨŶ
Ŷ„‡ƒ”ŶɯɥɥŶɩŶ
Ŷ‡ŽŶɨɥɥŶɨŶ
Ŷƒ”‘•‡–ŶɩɬɥŶɨŶ
ʫŞŞŞŞŞŞŞŞʫŞŞŞŞŞŞŞŞʫŞŞŞŞŞŞŞŞŞŞŞŞʫ
ɩɥɨɫŞɥɪŞɨɨɨɰśɫɭśɪɭřɯɥɮ   ƒŽŽ‡†’”‡––›ɏ’”‹–ſ”‡ ‘”†•ƀ

Если вы прочитали документацию, то можете избежать вывода на экран строк


с отладочной информацией и, возможно, изменить формат таблицы.
Сравнивая два примера, вы можете заметить: пример с bubbles использовал один
вызов функции (aggregate) с целью заменить чтение и подсчет данных в формате
CSV вручную. В зависимости от того, что вам нужно, наборы инструментов для
работы с данными могут сберечь много времени.
В более реалистичном примере наш файл может содержать тысячи строк (он ста-
новится опасным), в которых можно встретить опечатки вроде bare, запятые в чис-
лах и т. д. Найти хорошие образцы практических задач, связанных с данными, и их
решений на Python я бы порекомендовал в следующих источниках:
‰Data Crunching: Solve Everyday Problems Using Java, Python, and More Грега Уилсона
(KWWSELWO\GDWDBFUXQFKLQJ) (издательство Pragmatic Bookshelf);
‰Automate the Boring Stuff Эла Свайгарта (KWWSVDXWRPDWHWKHERULQJVWXIIFRP)1 (из-
дательство No Starch).
Инструменты очистки данных могут сэкономить много времени, и Python име-
ет множество таких инструментов. Например, PETL (KWWSSHWOUHDGWKHGRFVRUJ)
позволяет выполнять извлечение и переименование рядов и колонок. В главе 22
рассматриваются особенно полезные инструменты для работы с данными: Pandas,

1
Свайгарт Э. Автоматизация рутинных задач с помощью Python. Практическое руковод-
ство для начинающих. — Киев: Диалектика, 2018.
ǫȓȈȊȈǯȈȘȈȉȖȚȖȑ  

NumPy и IPython. В дополнение к их широкой известности в научной среде они


стали популярными инструментами среди разработчиков, работающих с финансами
и данными. На конференции PyData в 2012 году компания AppData (KWWSELWO\S\ELJ
GDWD) рассматривала, как эти три и другие инструменты Python помогают обработать
15 Тбайт данных ежедневно. Это не опечатка — Python может обрабатывать очень
большие объемы реальных данных.
Вы также можете вернуться назад и взглянуть на инструменты для сериализации
и валидации данных, рассмотренные в разделе «Сериализация данных» на с. 386.

ǪȈȓȐȌȈȞȐȧȌȈȕȕȣȝ
При очистке данных вам зачастую нужно проверить следующее:
‰тип данных (целое число, число с плавающей точкой или строка);
‰диапазон возможных значений;
‰корректность значений, например рабочий номер телефона или адрес электрон-
ной почты;
‰дубликаты;
‰отсутствующие данные.
Это особенно важно при обработке веб-запросов и ответов.
Для работы с определенными данными можно использовать следующие по-
лезные пакеты Python:
‰˜ƒŽ‹†ƒ–‡ɏ‡ƒ‹Ž (KWWSVS\SLRUJSURMHFWYDOLGDWHBHPDLO);
‰’Š‘‡—„‡” (KWWSVS\SLRUJSURMHFWSKRQHQXPEHUV).
Кроме того, порекомендую полезные инструменты общего назначения:
‰˜ƒŽ‹†ƒ–‘”• (KWWSVYDOLGDWRUVUHDGWKHGRFVLR);
‰’›†ƒ–‹ (KWWSVS\GDQWLFGRFVKHOSPDQXDOLR) — для версий Python 3.6 и выше; ис-
пользует подсказки типов;
‰ƒ”•ŠƒŽŽ‘™ (KWWSVPDUVKPDOORZUHDGWKHGRFVLRHQ) — также выполняет сериали-
зацию и десериализацию;
‰‡”„‡”—• (KWWSGRFVS\WKRQFHUEHUXVRUJHQVWDEOH);
‰многие другие (KWWSVOLEUDULHVLRVHDUFK"NH\ZRUGV YDOLGDWLRQ ODQJXDJHV 3\WKRQ).

ǬȖȗȖȓȕȐȚȍȓȤȕȣȍȐșȚȖȟȕȐȒȐȐȕȜȖȘȔȈȞȐȐ
Иногда вам нужны данные, которые появляются где-то в другом месте. Рассмот-
рим некоторые источники данных из области бизнеса и правительственной ин-
формации:
‰[Link] (KWWSVZZZGDWDJRY) открывает доступ к тысячам наборов данных и ин-
струментов. Его API (KWWSVZZZGDWDJRYGHYHORSHUVDSLV) созданы на основе CKAN
(KWWSFNDQRUJ), системы управления данными Python;
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰Opening government with Python (KWWSVXQOLJKWIRXQGDWLRQFRP) — посмотрите видео-


ролики (KWWSELWO\RSHQJRYS\) и слайды (KWWSJRRJO<KV);
‰python-sunlight (KWWSELWO\S\VXQ) — библиотеки, позволяющие получить доступ
к Sunlight API (KWWSVXQOLJKWIRXQGDWLRQFRPDSL);
‰Froide (KWWSVIURLGHUHDGWKHGRFVLR) — платформа, основанная на Django, для управ-
ления свободой информационных запросов;
‰30 places to find open data on the Web (KWWSEORJYLVXDOO\GDWDVRXUFHV). Различные
полезные ссылки.

ǷȈȒȍȚȣȌȓȧȘȈȉȖȚȣșȉȐȏȕȍșȌȈȕȕȣȔȐ
șȖȚȒȘȣȚȣȔȐșȝȖȌȕȣȔȒȖȌȖȔ
‰Odoo (KWWSVZZZRGRRFRP) — обширная ERP-платформа.
‰Tryton (KWWSZZZWU\WRQRUJ) — еще одна обширная платформа.
‰Oscar (KWWSRVFDUFRPPHUFHFRP) — фреймфорк для электронной коммерции, на-
писанный на Django.
‰Grid Studio (KWWSVJULGVWXGLRLR) — основанные на Python таблицы, работают ло-
кально или в облаке.

3\WKRQȊȖȉȓȈșȚȐȜȐȕȈȕșȖȊ
С недавнего времени в финансовой индустрии развился значительный интерес
к Python. Адаптируя программное обеспечение, показанное в главе 22, а также
разрабатывая собственное, группа quants создает новое поколение финансовых
инструментов:
‰Quantitative economics (KWWSTHFRQRPLFVRUJRMVLQGH[SKS) — этот инструмент пред-
назначен для экономического моделирования с помощью большого количества
математических расчетов и Python;
‰Python for finance (KWWSZZZS\WKRQIRUILQDQFHFRP) — этот сайт представляет книгу
Derivatives Analytics with Python: Data Analytics, Models, Simulation, Calibration and
Hedging Ива Хилпиша (издательство Wiley);
‰Quantopian (KWWSVZZZTXDQWRSLDQFRP) — это интерактивный сайт, на котором вы
можете писать собственный код Python и работать с его помощью с архивными
данными об акциях;
‰PyAlgoTrade (KWWSJEHFHGJLWKXELRS\DOJRWUDGH) — еще один инструмент для тести-
рования на исторических данных, но уже для вашего собственного компьютера;
‰Quandl (KWWSZZZTXDQGOFRP) — используйте этот инструмент для поиска в мил-
лионах единиц финансовых данных;
ǫȓȈȊȈǯȈȘȈȉȖȚȖȑ  

‰Ultra-finance (KWWSVFRGHJRRJOHFRPSXOWUDILQDQFH) — библиотека, содержащая на-


бор информации об акциях, которая обновляется в реальном времени;
‰Python for Finance (KWWSELWO\S\WKRQILQDQFH)1 (издательство O’Reilly) — книга Ива Хил-
пиша, содержащая примеры финансового моделирования, написанные на Python.

ǩȍȏȖȗȈșȕȖșȚȤȉȐȏȕȍșȌȈȕȕȣȝ
Безопасность — особая забота для бизнеса. Данной теме посвящены целые книги,
поэтому я лишь упомяну несколько советов, связанных с Python.
‰В подразделе «scapy» раздела «TCP/IP» главы 17 рассматривается • ƒ’›, язык на
базе Python для экспертизы пакетов. Он используется для объяснения некоторых
крупных сетевых атак.
‰Сайт Python Security (KWWSZZZS\WKRQVHFXULW\RUJ) содержит дискуссии на тему
безопасности, детали некоторых модулей Python и вспомогательные таблицы.
‰Книга Violent Python (KWWSELWO\YLROHQWS\WKRQ) (с подзаголовком A Cookbook for
Hackers, Forensic Analysts, Penetration Testers and Security Engineers) Ти Джея
О’Коннора (издательство Syngress) — это широкий обзор Python и компьютерной
безопасности.

DzȈȘȚȣ
Карты стали полезными для многих бизнесов. Python очень хорошо рисует карты,
так что мы потратим не много времени на эту тему. Менеджеры любят графики,
и если вы можете быстро нарисовать красивую карту сайта вашей организации, то
это вам не повредит.
В ранние дни существования Интернета я посещал экспериментальный сайт по
созданию карт у Xerox. Когда появились крупные сайты, такие как Google Maps,
они стали откровением (к тому же вызывали мысль: «Почему я не подумал об этом
и не заработал миллионы?»). Теперь сервисы картографии и сервисы, основанные на
определении местоположения, практически везде, они особенно удобны в мобильных
устройствах.
Здесь пересекается множество терминов: картография, GIS (geographic information
system — географическая информационная система), GPS (Global Positioning
System — глобальная система позиционирования), анализ геопространства и многое
другое. Блог Geospatial Python (KWWSELWO\JHRVSDWLDOS\) воплощает образ системы
размером с «800-фунтовую гориллу» GDAL/OGR, GEOS и PROJ.4 (проекции)
и вспомогательные системы, представленные как обезьяны (помогающие этой го-
рилле). Многие из этих сервисов имеют интерфейсы Python. Поговорим о некоторых
из них, начиная с самых простых форматов.

1
Хилпиш И. Python для финансовых расчетов. — Киев: Диалектика, 2019.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǼȖȘȔȈȚȣ
Мир картографии имеет множество форматов: векторный (линии), растровый (изо-
бражения), метаданные (слова) и их комбинации.
Esri, первая географическая система, изобрела формат «шейп-файл» более 20 лет
назад. Файл данного формата содержит несколько файлов, включающих как мини-
мум следующую информацию:
‰Ŝ•Š’ — информацию о фигуре (вектор);
‰Ŝ•Šš — индекс формы;
‰Ŝ†„ˆ — базу данных атрибутов.
Получим шейп-файл для нашего следующего примера. Посетите страницу KWWS
ELWO\FXOWXUDOYHFWRUV. В разделе $GPLQ²6WDWHV3URYLQFHV (Admin 1 — штаты, провинции)
нажмите зеленую кнопку GRZQORDGVWDWHVDQGSURYLQFHV (Скачать штаты и провинции),
чтобы скачать архив. Затем разархивируйте файл. Вы должны увидеть такой ре-
зультат:
‡ɏɨɨɥɏƒ†‹ɏɨɏ•–ƒ–‡•ɏ’”‘˜‹ ‡•ɏ•Š’ŜŜŠ–Ž
‡ɏɨɨɥɏƒ†‹ɏɨɏ•–ƒ–‡•ɏ’”‘˜‹ ‡•ɏ•Š’Ŝ•„
‡ɏɨɨɥɏƒ†‹ɏɨɏ•–ƒ–‡•ɏ’”‘˜‹ ‡•ɏ•Š’Ŝ Ŝ–š–
‡ɏɨɨɥɏƒ†‹ɏɨɏ•–ƒ–‡•ɏ’”‘˜‹ ‡•ɏ•Š’Ŝ•„š
‡ɏɨɨɥɏƒ†‹ɏɨɏ•–ƒ–‡•ɏ’”‘˜‹ ‡•ɏ•Š’Ŝ†„ˆ
‡ɏɨɨɥɏƒ†‹ɏɨɏ•–ƒ–‡•ɏ’”‘˜‹ ‡•ɏ•Š’Ŝ•Š’
‡ɏɨɨɥɏƒ†‹ɏɨɏ•–ƒ–‡•ɏ’”‘˜‹ ‡•ɏ•Š’Ŝ’”Œ
‡ɏɨɨɥɏƒ†‹ɏɨɏ•–ƒ–‡•ɏ’”‘˜‹ ‡•ɏ•Š’Ŝ•Šš

Мы будем использовать эти файлы в наших примерах.

ǵȈȘȐșțȍȔȒȈȘȚțȕȈȖșȕȖȊȍȠȍȑȗȜȈȑȓȈ
В этом подразделе приводится очень упрощенная демонстрация чтения и отобра-
жения шейп-файла. Вы увидите, что результат неидеален, и поймете преимущества
работы с пакетами более высокого уровня, которые будут показаны ниже.
Для прочтения шейп-файла вам понадобится эта библиотека:
ɛpip install pyshp

Теперь введите текст программы, ƒ’ɨŜ’›, который я модифицировал из статьи


в блоге Geospatial Python (KWWSELWO\UDVWHUVKDSH):
†‡ˆ†‹•’Žƒ›ɏ•Šƒ’‡ˆ‹Ž‡ſƒ‡ř‹™‹†–Šʰɬɥɥř‹Š‡‹‰Š–ʰɬɥɥƀś
‹’‘”–•Šƒ’‡ˆ‹Ž‡
ˆ”‘ ‹’‘”– ƒ‰‡ř ƒ‰‡”ƒ™
”ʰ•Šƒ’‡ˆ‹Ž‡Ŝ‡ƒ†‡”ſƒ‡ƀ
Ž‡ˆ–ř„‘––‘ř”‹‰Š–ř–‘’ʰ”Ŝ„„‘š
ɤșȘȜȡȜȪȯȜțȠșȤșȡȜȳȞȔȤȦȯ
™‹†–Šʰ”‹‰Š–ŞŽ‡ˆ–
Š‡‹‰Š–ʰ–‘’ޏ„‘––‘
ǫȓȈȊȈǯȈȘȈȉȖȚȖȑ  

ɤȣȤșȢȕȤȔțȧșȠșȘȜȡȜȪȯȜțȠșȤșȡȜȳȞȔȤȦȖșȘȜȡȜȪȯȜțȠșȤșȡȜȳȜțȢȕȤȔȚșȡȜȝ
Š• ƒŽ‡ʰ‹™‹†–Šŵ™‹†–Š
˜• ƒŽ‡ʰ‹Š‡‹‰Š–ŵŠ‡‹‰Š–
‹‰ʰ ƒ‰‡Ŝ‡™ſɑ ɑřſ‹™‹†–Šř‹Š‡‹‰Š–ƀřɑ™Š‹–‡ɑƀ
†”ƒ™ʰ ƒ‰‡”ƒ™Ŝ”ƒ™ſ‹‰ƀ
ˆ‘”•Šƒ’‡‹”Ŝ•Šƒ’‡•ſƀś
’‹š‡Ž•ʰƃ
ſ‹–ſ‹™‹†–ŠŞſſ”‹‰Š–ŞšƀƋŠ• ƒŽ‡ƀƀř‹–ſſ–‘’Ş›ƀƋ˜• ƒŽ‡ƀƀ
ˆ‘”šř›‹•Šƒ’‡Ŝ’‘‹–•Ƅ
‹ˆ•Šƒ’‡Ŝ•Šƒ’‡›’‡ʰʰ•Šƒ’‡ˆ‹Ž‡Ŝ ś
†”ƒ™Ŝ’‘Ž›‰‘ſ’‹š‡Ž•ř‘—–Ž‹‡ʰɐ„Žƒ ɐƀ
‡Ž‹ˆ•Šƒ’‡Ŝ•Šƒ’‡›’‡ʰʰ•Šƒ’‡ˆ‹Ž‡Ŝ ś
†”ƒ™ŜŽ‹‡ſ’‹š‡Ž•řˆ‹ŽŽʰɐ„Žƒ ɐƀ
‹‰Ŝ•Š‘™ſƀ

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
‹’‘”–•›•
†‹•’Žƒ›ɏ•Šƒ’‡ˆ‹Ž‡ſ•›•Ŝƒ”‰˜ƃɨƄřɮɥɥřɮɥɥƀ

Эта программа считывает шейп-файл и проходит по отдельным фигурам. Я ищу


только два типа фигур: многоугольник, соединяющий последнюю точку с начальной,
и ломаную линию, которая этого не делает. Я строил свою логику на основе ориги-
нальной статьи и беглого просмотра документации pyshp, поэтому вполне уверен
в том, что знаю, как работает программа. Иногда вам просто нужно начать и затем
справляться с возникающими проблемами.
Запустим наш код. Аргументом станет базовое имя для шейп-файла, не содер-
жащее расширения:
ɛpython [Link] ne_110m_admin_1_states_provinces_shp

Вы должны увидеть что-то похожее на рис. 21.1.


Что ж, программа нарисовала карту, которая напоминает Соединенные Штаты, но:

‰между Аляской и Гавайями видим что-то вроде растрепанных кошкой ниток —


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

По поводу первого пункта: в логике программы есть ошибка, но что мне делать?
В главе 19 рассматриваются советы для разработчиков, включая информацию об
отладке, но мы можем рассмотреть и другие варианты. Я мог бы написать несколько
тестов и работать, пока не исправлю ошибку, или же использовать какую-нибудь
другую библиотеку для создания карты. Возможно, более высокоуровневое решение
поможет мне справиться со всеми тремя проблемами (лишние линии, сплющенный
вид и примитивный стиль).
Насколько я знаю, не существует пакета для работы с картами, основанного на
чистом Python. К счастью, есть более изящные пакеты; рассмотрим их.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǸȐșǷȘȍȌȊȈȘȐȚȍȓȤȕȈȧȒȈȘȚȈ

*HRSDQGDV
Пакет Geopandas (KWWSJHRSDQGDVRUJ) интегрирует в себе Matplotlib, Pandas и другие
библиотеки Python в одну платформу, которая позволяет работать с геопростран-
ственными данными.
Основной пакет устанавливается с помощью знакомой команды pip install
‰‡‘’ƒ†ƒ•, но полагается и на другие пакеты, которые вам также нужно устанавли-
вать, используя pip, если их у вас еще нет:
‰—’›;
‰’ƒ†ƒ• (версия 0.23.4 или выше);
‰shapely (интерфейс для GEOS);
ǫȓȈȊȈǯȈȘȈȉȖȚȖȑ  

‰fiona (интерфейс для GDAL);


‰’›’”‘Œ (интерфейс для PROJ);
‰•‹š.
Пакет Geopandas может читать шейп-файлы (включая файлы из предыдущего
подраздела), а также, что удобно, содержит два шейп-файла от Natural Earth: очер-
тания стран/континентов и столицы. В примере 21.1 используются оба этих файла.

ǷȘȐȔȍȘJHRSDQGDVS\
‹’‘”–‰‡‘’ƒ†ƒ•
‹’‘”–ƒ–’Ž‘–Ž‹„Ŝ’›’Ž‘–ƒ•’Ž–

™‘”ކɏˆ‹Ž‡ʰ‰‡‘’ƒ†ƒ•Ŝ†ƒ–ƒ•‡–•Ŝ‰‡–ɏ’ƒ–Šſɐƒ–—”ƒŽ‡ƒ”–ŠɏŽ‘™”‡•ɐƀ
™‘”ކʰ‰‡‘’ƒ†ƒ•Ŝ”‡ƒ†ɏˆ‹Ž‡ſ™‘”ކɏˆ‹Ž‡ƀ
‹–‹‡•ɏˆ‹Ž‡ʰ‰‡‘’ƒ†ƒ•Ŝ†ƒ–ƒ•‡–•Ŝ‰‡–ɏ’ƒ–Šſɐƒ–—”ƒŽ‡ƒ”–Šɏ ‹–‹‡•ɐƀ
‹–‹‡•ʰ‰‡‘’ƒ†ƒ•Ŝ”‡ƒ†ɏˆ‹Ž‡ſ ‹–‹‡•ɏˆ‹Ž‡ƀ
„ƒ•‡ʰ™‘”ކŜ’Ž‘–ſ ‘Ž‘”ʰɐ‘” Š‹†ɐƀ
‹–‹‡•Ŝ’Ž‘–ſƒšʰ„ƒ•‡ř ‘Ž‘”ʰɐ„Žƒ ɐřƒ”‡”•‹œ‡ʰɩƀ
’Ž–Ŝ•Š‘™ſƀ

Запустив этот пример, вы получите карту, показанную на рис. 21.2.

ǸȐșDzȈȘȚȈșȖȏȌȈȕȕȈȧșȗȖȔȖȡȤȦ*HRSDQGDV
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Я считаю пакет Geopandas наилучшей комбинацией для управления географиче-


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

ǬȘțȋȐȍȗȈȒȍȚȣȌȓȧȘȈȉȖȚȣșȒȈȘȚȈȔȐ
Перед вами набор ссылок на другое ПО для работы с картами; многие из них могут
не полностью устанавливаться с помощью pip, но для некоторых можно задейство-
вать ‘†ƒ (альтернативный установщик пакетов Python, особенно полезный для
научного ПО):
‰pyshp (KWWSVS\SLRUJSURMHFWS\VKS) — это библиотека для работы с шейп-файлами,
упомянутая выше, в подразделе «Нарисуем карту на основе шейп-файла»;
‰kartograph (KWWSNDUWRJUDSKRUJ) отрисовывает шейп-файлы в карты формата SVG
на сервере или клиенте;
‰shapely (KWWSVVKDSHO\UHDGWKHGRFVLR) решает геометрические вопросы наподобие
«Какие строения в этом городе через 50 лет окажутся в зоне наводнения?»;
‰basemap (KWWSPDWSORWOLERUJEDVHPDS) основана на Matplotlib, предназначена для
рисования карт и перекрытия их данных; к сожалению, после появления Cartopy
считается устаревшей;
‰cartopy (KWWSVVFLWRROVRUJXNFDUWRS\GRFVODWHVW) продолжает дело Basemap и решает
задачи, для которых обычно нужен пакет Geopandas;
‰folium (KWWSVS\WKRQYLVXDOL]DWLRQJLWKXELRIROLXP) работает с އƒˆŽ‡–ŜŒ•, используется
‰‡‘’ƒ†ƒ•;
‰plotly (KWWSVSORWO\S\WKRQPDSV) — еще один пакет для построения, который вклю-
чает в себя возможность работы с графиками;
‰dash (KWWSVGDVKSORWO\) использует Plotly, Flask и JavaScript для создания инте-
рактивных визуализаций, включая карты;
‰fiona (KWWSVJLWKXEFRP7REOHULW\)LRQD) оборачивает библиотеку OGR, которая ра-
ботает с шейп-файлами и другими векторными форматами;
‰Open Street Map (KWWSVRUHLOO\%-HKD) получает доступ к обширной коллекции карт
мира OpenStreetMap (KWWSVZZZRSHQVWUHHWPDSRUJ);
‰mapnik (KWWSPDSQLNRUJ) — библиотека, написанная на C++, имеющая привязку
к Python; используется для создания векторных (линии) и растровых (изобра-
жения) карт;
‰Vincent (KWWSYLQFHQWUHDGWKHGRFVRUJ) преобразуется в Vega, инструмент визуали-
зации JavaScript; см. руководство Mapping data in Python with pandas and vincent
(KWWSVRUHLOO\7E7&);
‰Python for ArcGIS (KWWSELWO\S\DUFJLV) — ссылки на ресурсы Python для коммер-
ческого продукта ArcGIS фирмы Esri;
‰Using geospatial data with Python (KWWSELWO\JHRVS\) — видеопрезентации;
ǫȓȈȊȈǯȈȘȈȉȖȚȖȑ  

‰So you’d like to make a map using Python (KWWSELWO\S\WKRQPDS) использует Pandas,
Matplotlib, shapely и другие модули Python для создания карт с расположением
памятных плит на зданиях;
‰Python Geospatial Development (KWWSELWO\S\JHRGHY)1 (издательство Packt) —
книга Эрика Вестры, содержащая примеры использования ƒ’‹ и других
инструментов;
‰Learning Geospatial Analysis with Python (KWWSELWO\OHDUQJHRS\) (издательство
Packt) — еще одна книга. Ее написал Джоэл Лохед. Он сделал обзор форматов
и библиотек, а также включил геопространственные алгоритмы;
‰geomancer (KWWSVJLWKXEFRPWKLQNLQJPDFKLQHVJHRPDQFHU) полезен для геопростран-
ственных работ, например для нахождения расстояния от некой точки до бли-
жайшего ирландского бара.
Если вам интересны карты, то попробуйте скачать и установить один из этих
пакетов и посмотреть, что вы можете сделать с его помощью. Или можете избежать
установки ПО и попытаться соединиться с API удаленного сервера самостоятель-
но — в главе 18 показывается, как соединяться с веб-серверами и декодировать
ответы JSON.

ǷȘȐȓȖȎȍȕȐȧȐȌȈȕȕȣȍ
Мы говорили о рисовании карт, но с данными о картах вы можете сделать гораздо
большее. Геокодирование преобразует адреса в географические координаты и наобо-
рот. Существует множество геокодирующих API (KWWSVRUHLOO\=TZ:) (их сравнение
вы можете увидеть на сайте KWWSELWO\IUHHJHRDSL) и библиотек Python:
‰geopy (KWWSVFRGHJRRJOHFRPSJHRS\);
‰pygeocoder (KWWSVS\SLS\WKRQRUJS\SLS\JHRFRGHU);
‰googlemaps (KWWSS\JRRJOHPDSVVRXUFHIRUJHQHW).
Если вы авторизуетесь с помощью Google или другого источника, чтобы полу-
чить ключ для API, то сможете получить доступ к другим сервисам, выполняющим,
например, пошаговое прокладывание маршрутов путешествий или локальный
поиск.
Вот несколько ресурсов, касающихся отображения данных:
‰KWWSZZZFHQVXVJRYJHRPDSVGDWD — обзор файлов карт U.S. Census Bureau;
‰KWWSZZZFHQVXVJRYJHRPDSVGDWDGDWDWLJHUKWPO — множество географических
и демографических карт;
‰KWWSZLNLRSHQVWUHHWPDSRUJZLNL3RWHQWLDOB'DWDVRXUFHV — мировые ресурсы;
‰KWWSZZZQDWXUDOHDUWKGDWDFRP — векторные и растровые данные карт в трех мас-
штабах.

1
Вестра Э. Разработка геоприложений на языке Python. — М.: ДМК Пресс, 2017.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Нам следует упомянуть здесь Data Science Toolkit (KWWSZZZGDWDVFLHQFHWRRONLWRUJ).


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

ǿȐȚȈȑȚȍȌȈȓȍȍ
Мы отправимся на научную ярмарку и посмотрим все экспонаты, связанные
с Python.

ǻȗȘȈȎȕȍȕȐȧ
21.1. Установите Geopandas и запустите пример 21.1. Попробуйте поизменять цвета
и размеры меток.
ƋƓƈƊƈ
3\WKRQȊȕȈțȒȍ

Во времена ее владения сила пара


Стала величайшей на суше и воде,
И теперь все полагаются
На последние достижения науки1.

Джеймс Макинтайр. Ода к юбилею королевы, 1887

В последние годы в основном из-за ПО, показанного в этой главе, Python стал очень
популярен среди ученых. Если вы и сами ученый или студент, то, возможно, пользо-
вались такими инструментами, как MatLab и R, или традиционными языками, на-
пример Java, C или C++. Сейчас вы увидите, что Python стал отличной платформой
для научного анализа и публикации результатов.

ǴȈȚȍȔȈȚȐȒȈȐșȚȈȚȐșȚȐȒȈ
ȊșȚȈȕȌȈȘȚȕȖȑȉȐȉȓȐȖȚȍȒȍ
Для начала вернемся к стандартной библиотеке и рассмотрим ряд особенностей
и модулей, которые мы проигнорировали.

ǴȈȚȍȔȈȚȐȟȍșȒȐȍȜțȕȒȞȐȐ
Python имеет множество математических функций в стандартной библиотеке math
(KWWSVRUHLOO\6+3). Просто введите ‹’‘”– ƒ–Š, чтобы получить к ним доступ из
своих программ.
Она содержит такие константы, как pi и e:
ʴʴʴ‹’‘”–ƒ–Š
ʴʴʴƒ–ŠŜ’‹
ʴʴʴɪŜɨɫɨɬɰɩɭɬɪɬɯɰɮɰɪ
ʴʴʴƒ–ŠŜ‡
ɩŜɮɨɯɩɯɨɯɩɯɫɬɰɥɫɬ

1
Оригинальная цитата: In her reign the power of steam On land and sea became supreme,
And all now have strong reliance In fresh victories of science. — Примеч. пер.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

В основном код состоит из функций, поэтому рассмотрим наиболее полезные


из них.
Функция ˆƒ„•ſƀ возвращает абсолютное значение своего аргумента:
ʴʴʴƒ–ŠŜˆƒ„•ſɰɯŜɭƀ
ɰɯŜɭ
ʴʴʴƒ–ŠŜˆƒ„•ſŞɩɮɨŜɨƀ
ɩɮɨŜɨ

Получаем округление вниз (ˆŽ‘‘”ſƀ) и вверх ( ‡‹Žſƀ) некоторого числа:


ʴʴʴƒ–ŠŜˆŽ‘‘”ſɰɯŜɭƀ
ɰɯ
ʴʴʴƒ–ŠŜˆŽ‘‘”ſŞɩɮɨŜɨƀ
Şɩɮɩ
ʴʴʴƒ–ŠŜ ‡‹ŽſɰɯŜɭƀ
99
ʴʴʴƒ–ŠŜ ‡‹ŽſŞɩɮɨŜɨƀ
Şɩɮɨ

Высчитываем факториал (в математике это выглядит как n!) с помощью функ-


ции ˆƒ –‘”‹ƒŽſƀ:
ʴʴʴƒ–ŠŜˆƒ –‘”‹ƒŽſɥƀ
ɨ
ʴʴʴƒ–ŠŜˆƒ –‘”‹ƒŽſɨƀ
ɨ
ʴʴʴƒ–ŠŜˆƒ –‘”‹ƒŽſɩƀ
ɩ
ʴʴʴƒ–ŠŜˆƒ –‘”‹ƒŽſɪƀ
6
ʴʴʴƒ–ŠŜˆƒ –‘”‹ƒŽſɨɥƀ
ɪɭɩɯɯɥɥ

Получаем натуральный логарифм аргумента на основании e с помощью функции


Ž‘‰ſƀ:
ʴʴʴƒ–ŠŜŽ‘‰ſɨŜɥƀ
ɥŜɥ
ʴʴʴƒ–ŠŜŽ‘‰ſƒ–ŠŜ‡ƀ
ɨŜɥ

Если вы хотите задать другое основание логарифма, то передайте его как второй
аргумент:
ʴʴʴƒ–ŠŜŽ‘‰ſɯřɩƀ
ɪŜɥ

Функция ’‘™ſƀ возвращает противоположный результат, возводя число в сте-


пень:
ʴʴʴƒ–ŠŜ’‘™ſɩřɪƀ
ɯŜɥ
ǫȓȈȊȈ3\WKRQȊȕȈțȒȍ  

Python имеет также встроенный оператор экспоненты **, делающий то же самое,


но этот оператор не преобразует автоматически результат к числу с плавающей
точкой, если основание и степень были целыми числами:
ʴʴʴɩƋƋɪ
ɯ
ʴʴʴɩŜɥƋƋɪ
ɯŜɥ

Получаем квадратный корень с помощью функции •“”–ſƀ:


ʴʴʴƒ–ŠŜ•“”–ſɨɥɥŜɥƀ
ɨɥŜɥ

Не пытайтесь обмануть эту функцию, она уже все это видела:


ʴʴʴƒ–ŠŜ•“”–ſŞɨɥɥŜɥƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
ƒŽ—‡””‘”śƒ–І‘ƒ‹‡””‘”

Здесь имеются также обычные тригонометрические функции, я просто приведу


их названия: •‹ſƀ, ‘•ſƀ, –ƒſƀ, ƒ•‹ſƀ, ƒ ‘•ſƀ, ƒ–ƒſƀ и ƒ–ƒɩſƀ. Если вы помните
теорему Пифагора (или хотя бы можете повторить ее быстро три раза, не начав
плеваться), то библиотека ƒ–Š вдобавок предоставит вам функцию Š›’‘–ſƀ, которая
рассчитывает гипотенузу на основании длины двух катетов:
ʴʴʴšʰɪŜɥ
ʴʴʴ›ʰɫŜɥ
ʴʴʴƒ–ŠŜŠ›’‘–ſšř›ƀ
ɬŜɥ

Если вы не доверяете таким функциям, то можете сделать все самостоятельно:


ʴʴʴƒ–ŠŜ•“”–ſšƋšʫ›Ƌ›ƀ
ɬŜɥ
ʴʴʴƒ–ŠŜ•“”–ſšƋƋɩʫ›ƋƋɩƀ
ɬŜɥ

Последний набор функций преобразует угловые координаты:


ʴʴʴƒ–ŠŜ”ƒ†‹ƒ•ſɨɯɥŜɥƀ
ɪŜɨɫɨɬɰɩɭɬɪɬɯɰɮɰɪ
ʴʴʴƒ–ŠŜ†‡‰”‡‡•ſƒ–ŠŜ’‹ƀ
ɨɯɥŜɥ

ǸȈȉȖȚȈșȒȖȔȗȓȍȒșȕȣȔȐȟȐșȓȈȔȐ
Комплексные числа полностью поддерживаются основой языка Python в традици-
онной нотации с мнимой и действительной частями:
ʴʴʴɤȘșȝȥȦȖȜȦșȟȰȡȢșȫȜȥȟȢ
ŜŜŜɬ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ɬ
ʴʴʴɤȠȡȜȠȢșȫȜȥȟȢ
ŜŜŜɯŒ
ɯŒ
ʴʴʴɤȠȡȜȠȢșȫȜȥȟȢ
ŜŜŜɪʫɩŒ
ſɪʫɩŒƀ

Поскольку мнимое число i (в Python оно записывается как ɨŒ) определено как
квадратный корень из –1, мы можем выполнить следующее:
ʴʴʴɨŒƋɨŒ
ſŞɨʫɥŒƀ
ʴʴʴſɮʫɨŒƀƋɨŒ
ſŞɨʫɮŒƀ

Некоторые математические функции для комплексных чисел содержатся в стан-


дартном модуле ƒ–Š (KWWSVRUHLOO\(=4).

ǸȈșșȟȐȚȣȊȈȍȔȚȖȟȕȖȍȏȕȈȟȍȕȐȍȟȐșȍȓ
șȗȓȈȊȈȦȡȍȑȚȖȟȒȖȑșȗȖȔȖȡȤȦȔȖȌțȓȧGHFLPDO
Числа с плавающей точкой в вычислительной технике не похожи на настоящие
числа, которые мы изучали в школе:
ʴʴʴšʰɨɥŜɥŵɪŜɥ
ʴʴʴš
ɪŜɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɬ

Эй, что это за пятерка в конце? На ее месте должна быть тройка. Так происходит
потому, что количество битов в регистрах процессора ограничено и числа, которые
не являются степенями двойки, не могут быть выражены точно.
С помощью модуля †‡ ‹ƒŽ (KWWSVRUHLOO\REP5) вы можете записывать числа
с желаемым уровнем точности. Это особенно важно для расчетов денежных сумм.
Сумма в валюте Соединенных Штатов не может быть меньше одного цента (сотая
часть доллара), поэтому при подсчете количества долларов и центов нам нужно
быть предельно точными. Если мы попробуем представить доллары и центы как
значения с плавающей точкой, такие как 19,99 или 0,06, то потеряем некоторую часть
точности в последних битах еще до начала вычислений. Как с этим справиться?
Легко. Нужно использовать модуль †‡ ‹ƒŽ:
ʴʴʴˆ”‘†‡ ‹ƒŽ‹’‘”–‡ ‹ƒŽ
ʴʴʴ’”‹ ‡ʰ‡ ‹ƒŽſɐɨɰŜɰɰɐƀ
ʴʴʴ–ƒšʰ‡ ‹ƒŽſɐɥŜɥɭɐƀ
ʴʴʴ–‘–ƒŽʰ’”‹ ‡ʫſ’”‹ ‡Ƌ–ƒšƀ
ʴʴʴ–‘–ƒŽ
‡ ‹ƒŽſɐɩɨŜɨɯɰɫɐƀ

Мы записали цену и налог как строковые значения, чтобы сохранить их точность.


При вычислении переменной total мы обработали все значащие части цента, но
хотим получить его ближайшее целое значение:
ǫȓȈȊȈ3\WKRQȊȕȈțȒȍ  

ʴʴʴ’‡›ʰ‡ ‹ƒŽſɐɥŜɥɨɐƀ
ʴʴʴ–‘–ƒŽŜ“—ƒ–‹œ‡ſ’‡›ƀ
‡ ‹ƒŽſɐɩɨŜɨɰɐƀ

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


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

ǪȣȗȖȓȕȧȍȔȊȣȟȐșȓȍȕȐȧȌȓȧȘȈȞȐȖȕȈȓȤȕȣȝȟȐșȍȓ
șȗȖȔȖȡȤȦȔȖȌțȓȧIUDFWLRQV
Вы можете представлять числа как числитель, разделенный на знаменатель, с по-
мощью модуля стандартной библиотеки Python ˆ”ƒ –‹‘• (KWWSVRUHLOO\OJ).
Рассмотрим пример простой операции умножения 1/3 на 2/3:
ʴʴʴˆ”‘ˆ”ƒ –‹‘•‹’‘”– ”ƒ –‹‘
ʴʴʴ ”ƒ –‹‘ſɨřɪƀƋ ”ƒ –‹‘ſɩřɪƀ
”ƒ –‹‘ſɩřɰƀ

Аргументы с плавающей точкой могут быть неточными, поэтому вы можете ис-


пользовать модуль ‡ ‹ƒŽ вместе с модулем ”ƒ –‹‘:
ʴʴʴ ”ƒ –‹‘ſɨŜɥŵɪŜɥƀ
”ƒ –‹‘ſɭɥɥɫɮɰɰɬɥɪɨɭɥɭɭɨřɨɯɥɨɫɪɰɯɬɥɰɫɯɨɰɯɫƀ
ʴʴʴ ”ƒ –‹‘ſ‡ ‹ƒŽſɐɨŜɥɐƀŵ‡ ‹ƒŽſɐɪŜɥɐƀƀ
”ƒ –‹‘ſɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪɪřɨɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥɥƀ

Получим наибольший общий делитель для двух чисел с помощью функции ‰ †:


ʴʴʴ‹’‘”–ˆ”ƒ –‹‘•
ʴʴʴˆ”ƒ –‹‘•Ŝ‰ †ſɩɫřɨɭƀ
ɯ

ǰșȗȖȓȤȏțȍȔ3DFNHG6HTXHQFHV
șȗȖȔȖȡȤȦȔȖȌțȓȧDUUD\
В Python список больше похож на связанный список, а не на массив. Если вы
хотите получить одномерную последовательность элементов одинакового типа,
то применяйте тип array (KWWSVRUHLOO\9HM38). Переменные этого типа используют
меньше места и поддерживают многие методы работы со списками. Создайте массив
с помощью команды вида array(ȞȢȘ ȦȜȣȔř ȜȡȜȪȜȔȟȜțȔȦȢȤƀ. Код типа указывает на
тип данных (такой как int или float), а опциональный ȜȡȜȪȜȔȟȜțȔȦȢȤ содержит
исходные значения, которые можно передать как список, строку или итерируемое
значение.
Я никогда не использовал этот пакет для решения реальных задач. Это низко-
уровневая структура данных, полезная для представления чего-то наподобие изо-
бражений. Если для выполнения числовых подсчетов вам на самом деле нужен мас-
сив, особенно имеющий больше одного измерения, то лучше задействовать NumPy,
о котором мы поговорим чуть позже.
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǶȉȘȈȉȈȚȣȊȈȍȔȗȘȖșȚțȦșȚȈȚȐșȚȐȒț
șȗȖȔȖȡȤȦȔȖȌțȓȧVWDWLVWLFV
Начиная с версии Python 3.4, •–ƒ–‹•–‹ • (KWWSVRUHLOO\'(/Q0) — стандартный модуль.
Он содержит традиционные функции: среднее, медиану, режим, стандартное откло-
нение, распределение и т. д. Входными аргументами являются последовательности
(списки или кортежи) или итераторы любого числового типа данных: int, float,
†‡ ‹ƒŽ и ˆ”ƒ –‹‘. Одна из функций, ‘†‡, также принимает в качестве аргументов
строки. Для Python существует множество других статистических функций, доступ-
ных в пакетах, таких как SciPy и Pandas, которые мы рассмотрим далее в этой главе.

ǷȍȘȍȔȕȖȎȍȕȐȍȔȈȚȘȐȞ
Начиная с Python 3.5, вы увидите символ ɒ, который делает необычные вещи. Он все
еще может использоваться для декораторов, но будет применяться также и для пере-
множения матриц (KWWSVRUHLOO\IDNR'). Если вы работаете со старой версией Python,
то вам следует задействовать NumPy.

3\WKRQȌȓȧȕȈțȒȐ
В оставшейся части этой главы рассматриваются сторонние пакеты Python для
науки и математики. Несмотря на то что вы можете установить их индивидуально,
следует рассмотреть их одновременное скачивание в качестве части научного дис-
трибутива Python. Рассмотрим основные варианты.
‰Anaconda (KWWSVZZZDQDFRQGDFRP) — это бесплатный пакет, имеющий множе-
ство самых свежих возможностей. Он поддерживает Python 2 и 3 и не вредит
установленной у вас версии Python.
‰Enthought Canopy (KWWSVDVVHWVHQWKRXJKWFRPGRZQORDGV) — доступна как бесплатная,
так и коммерческая версии.
‰Python(x, y) (KWWSVS\WKRQ[\JLWKXELR) — этот релиз подходит только для Windows.
‰Pyzo (KWWSZZZS\]RRUJ) — этот пакет основан на некоторых инструментах пакета
Anaconda, а также других.
Я рекомендую установить пакет Anaconda. Он большой, и все представленное
в этой главе содержится в нем. Примеры остальной части главы подразумевают,
что вы установили необходимые пакеты либо отдельно, либо как часть Anaconda.

1XP3\
NumPy (KWWSZZZQXPS\RUJ) — это одна из основных причин популярности Python
среди ученых (KWWSZZZQXPS\RUJ). Вы слышали, что динамические языки, такие
как Python, зачастую медленнее компилирующих языков наподобие С или даже
ǫȓȈȊȈ3\WKRQȊȕȈțȒȍ  

других интерпретируемых языков, например Java. NumPy был написан для предо-
ставления доступа к быстрым многомерным массивам по аналогии с научными
языками, такими как FORTRAN. Вы получаете скорость С и дружелюбную к раз-
работчикам природу Python.
Если вы скачали один из научных дистрибутивов Python, то у вас уже есть
NumPy. В противном случае следуйте инструкциям на странице скачивания NumPy
(KWWSVRUHLOO\+F==L).
Чтобы начать работу с NumPy, вы должны понять устройство основной струк-
туры данных, многомерного массива †ƒ””ƒ› (от N-dimensional array — «N-мерный
массив») или просто array. В отличие от списков и кортежей в Python, все элементы
должны иметь одинаковый тип. NumPy называет количество измерений массива его
рангом. Одномерный массив похож на ряд значений, двумерный — на таблицу со
строками и столбцами, а трехмерный — на кубик Рубика. Длина измерений может
не быть одинаковой.

ǴȈșșȐȊȣDUUD\Ȋ1XP3\ȐDUUD\Ȋ3\WKRQ²ȕȍȖȌȕȖȐȚȖȎȍǬȈȓȍȍȊȥȚȖȑȋȓȈȊȍ
ȧȉțȌțȘȈȉȖȚȈȚȤȚȖȓȤȒȖșȔȈșșȐȊȈȔȐ1XP3\

Но зачем нам нужны массивы?


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

ǹȖȏȌȈȍȔȔȈșșȐȊșȗȖȔȖȡȤȦȜțȕȒȞȐȐDUUD\
Вы можете создать массив из обычного списка или кортежа:
ʴʴʴ„ʰ’Ŝƒ””ƒ›ſƃɩřɫřɭřɯƄƀ
ʴʴʴ„
ƒ””ƒ›ſƃɩřɫřɭřɯƄƀ

Атрибут †‹ возвращает ранг массива:


ʴʴʴ„Ŝ†‹
ɨ

Общее число значений можно получить с помощью атрибута •‹œ‡:


ʴʴʴ„Ŝ•‹œ‡
ɫ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Количество значений каждого ранга возвращает атрибут shape:


ʴʴʴ„Ŝ•Šƒ’‡
ſɫřƀ

ǹȖȏȌȈȍȔȔȈșșȐȊ
șȗȖȔȖȡȤȦȜțȕȒȞȐȐDUDQJH
Метод ƒ”ƒ‰‡ſƀNumPy похож на стандартный метод ”ƒ‰‡ſƀ Python. Если вы вы-
зовете метод ƒ”ƒ‰‡ſƀ, передав ему один целочисленный аргумент —, то он вернет
†ƒ””ƒ› от ɥ до —Şɨ:
ʴʴʴ‹’‘”–—’›ƒ•’
ʴʴʴƒʰ’Ŝƒ”ƒ‰‡ſɨɥƀ
ʴʴʴƒ
ƒ””ƒ›ſƃɥřɨřɩřɪřɫřɬřɭřɮřɯřɰƄƀ
ʴʴʴƒŜ†‹
ɨ
ʴʴʴƒŜ•Šƒ’‡
ſɨɥřƀ
ʴʴʴƒŜ•‹œ‡
ɨɥ

С помощью двух значений он создаст массив от первого элемента до последнего


минус один:
ʴʴʴƒʰ’Ŝƒ”ƒ‰‡ſɮřɨɨƀ
ʴʴʴƒ
ƒ””ƒ›ſƃɮřɯřɰřɨɥƄƀ

Вы также можете передать как третий параметр размер шага, который будет ис-
пользован вместо единицы:
ʴʴʴƒʰ’Ŝƒ”ƒ‰‡ſɮřɨɨřɩƀ
ʴʴʴƒ
ƒ””ƒ›ſƃɮřɰƄƀ

До сих пор мы показывали примеры лишь с целыми числами, но метод ƒ””ƒ‰‡ſƀ


работает и с числами с плавающей точкой:
ʴʴʴˆʰ’Ŝƒ”ƒ‰‡ſɩŜɥřɰŜɯřɥŜɪƀ
ʴʴʴˆ
ƒ””ƒ›ſƃɩŜřɩŜɪřɩŜɭřɩŜɰřɪŜɩřɪŜɬřɪŜɯřɫŜɨřɫŜɫřɫŜɮřɬŜř
ɬŜɪřɬŜɭřɬŜɰřɭŜɩřɭŜɬřɭŜɯřɮŜɨřɮŜɫřɮŜɮřɯŜřɯŜɪř
ɯŜɭřɯŜɰřɰŜɩřɰŜɬřɰŜɯƄƀ

И последний прием: аргумент †–›’‡ диктует функции ƒ””ƒ‰‡ſƀ, какой тип зна-
чения следует создать:
ʴʴʴ‰ʰ’Ŝƒ”ƒ‰‡ſɨɥřɫřŞɨŜɬř†–›’‡ʰ’ŜˆŽ‘ƒ–ƀ
ʴʴʴ‰
ƒ””ƒ›ſƃɨɥŜřɯŜɬřɮŜřɬŜɬƄƀ
ǫȓȈȊȈ3\WKRQȊȕȈțȒȍ  

ǹȖȏȌȈȍȔȔȈșșȐȊ
șȗȖȔȖȡȤȦȜțȕȒȞȐȑ]HURV RQHV ȐUDQGRP
Метод œ‡”‘•ſƀ возвращает массив, все значения которого равны ɥ. В эту функцию
вам нужно передать аргумент, содержащий желаемую форму массива. Так создается
одномерный массив:
ʴʴʴƒʰ’Ŝœ‡”‘•ſſɪřƀƀ
ʴʴʴƒ
ƒ””ƒ›ſƃɥŜřɥŜřɥŜƄƀ
ʴʴʴƒŜ†‹
ɨ
ʴʴʴƒŜ•Šƒ’‡
ſɪřƀ
ʴʴʴƒŜ•‹œ‡
ɪ

Этот массив имеет ранг 2:


ʴʴʴ„ʰ’Ŝœ‡”‘•ſſɩřɫƀƀ
ʴʴʴ„
ƒ””ƒ›ſƃƃɥŜřɥŜřɥŜřɥŜƄř
ƃɥŜřɥŜřɥŜřɥŜƄƄƀ
ʴʴʴ„Ŝ†‹
ɩ
ʴʴʴ„Ŝ•Šƒ’‡
ſɩřɫƀ
ʴʴʴ„Ŝ•‹œ‡
ɯ

Другой особой функцией, заполняющей массив одинаковыми значениями,


является ‘‡•ſƀ:
ʴʴʴ‹’‘”–—’›ƒ•’
ʴʴʴʰ’Ŝ‘‡•ſſɪřɬƀƀ
ʴʴʴ
ƒ””ƒ›ſƃƃɨŜřɨŜřɨŜřɨŜřɨŜƄř
ƃɨŜřɨŜřɨŜřɨŜřɨŜƄř
ƃɨŜřɨŜřɨŜřɨŜřɨŜƄƄƀ

Последняя функция создает массив и заполняет его случайными значениями из


промежутка от 0,0 до 1,0:
ʴʴʴʰ’Ŝ”ƒ†‘Ŝ”ƒ†‘ſſɪřɬƀƀ
ʴʴʴ

ƒ””ƒ›ſƃƃɨŜɰɩɫɨɬɭɰɰ‡ŞɥɨřɫŜɫɪɨɪɨɫɥɫ‡ŞɥɨřɮŜɰɰɩɩɭɮɮɪ‡Şɥɨř
ɨŜɨɫɪɥɨɰɫɩ‡ŞɥɨřɩŜɯɬɪɯɪɫɪɥ‡ŞɥɫƄř
ƃɭŜɬɪɮɥɬɮɫɰ‡ŞɥɨřɮŜɫɯɥɪɫɬɬɰ‡ŞɥɨřɫŜɫɰɫɭɪɩɫɨ‡Şɥɨř
ɫŜɯɮɰɥɭɰɨɬ‡ŞɥɨřɰŜɪɫɪɫɨɨɨɯ‡ŞɥɨƄř
ƃɰŜɫɮɬɮɬɬɭɩ‡ŞɥɨřɩŜɩɨɨɬɩɬɯɪ‡ŞɥɨřɩŜɫɰɥɪɨɩɥɰ‡Şɥɨř
ɪŜɫɭɨɰɥɰɭɨ‡ŞɥɨřɯŜɰɫɯɫɩɭɮɭ‡ŞɥɨƄƄƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

ǰȏȔȍȕȧȍȔȜȖȘȔțȔȈșșȐȊȈ
șȗȖȔȖȡȤȦȔȍȚȖȌȈUHVKDSH
До этого момента массив не особо отличался от списка или кортежа. Одно из их раз-
личий — возможность изменять его форму с помощью функции ”‡•Šƒ’‡ſƀ:
ʴʴʴƒʰ’Ŝƒ”ƒ‰‡ſɨɥƀ
ʴʴʴƒ
ƒ””ƒ›ſƃɥřɨřɩřɪřɫřɬřɭřɮřɯřɰƄƀ
ʴʴʴƒʰƒŜ”‡•Šƒ’‡ſɩřɬƀ
ʴʴʴƒ
ƒ””ƒ›ſƃƃɥřɨřɩřɪřɫƄř
ƃɬřɭřɮřɯřɰƄƄƀ
ʴʴʴƒŜ†‹
ɩ
ʴʴʴƒŜ•Šƒ’‡
ſɩřɬƀ
ʴʴʴƒŜ•‹œ‡
ɨɥ

Вы можете изменять форму массива разными способами:


ʴʴʴƒʰƒŜ”‡•Šƒ’‡ſɬřɩƀ
ʴʴʴƒ
ƒ””ƒ›ſƃƃɥřɨƄř
ƃɩřɪƄř
ƃɫřɬƄř
ƃɭřɮƄř
ƃɯřɰƄƄƀ
ʴʴʴƒŜ†‹
ɩ
ʴʴʴƒŜ•Šƒ’‡
ſɬřɩƀ
ʴʴʴƒŜ•‹œ‡
ɨɥ

Присваиваем кортеж, указывающий параметры формы, атрибуту shape:


ʴʴʴƒŜ•Šƒ’‡ʰſɩřɬƀ
ʴʴʴƒ
ƒ””ƒ›ſƃƃɥřɨřɩřɪřɫƄř
ƃɬřɭřɮřɯřɰƄƄƀ

Единственное ограничение — произведение рангов должно быть равным коли-


честву значений (в нашем случае 10):
ʴʴʴƒʰƒŜ”‡•Šƒ’‡ſɪřɫƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
ƒŽ—‡””‘”ś–‘–ƒŽ•‹œ‡‘ˆ‡™ƒ””ƒ›—•–„‡— Šƒ‰‡†
ǫȓȈȊȈ3\WKRQȊȕȈțȒȍ  

ǷȖȓțȟȈȍȔȥȓȍȔȍȕȚșȗȖȔȖȡȤȦȒȖȕșȚȘțȒȞȐȐ>@
Одномерный массив работает как список:
ʴʴʴƒʰ’Ŝƒ”ƒ‰‡ſɨɥƀ
ʴʴʴƒƃɮƄ
7
ʴʴʴƒƃŞɨƄ
9

Но если массив имеет другую форму, то используйте индексы, разделенные за-


пятыми, которые заключены в квадратные скобки:
ʴʴʴƒŜ•Šƒ’‡ʰſɩřɬƀ
ʴʴʴƒ
arra›ſƃƃɥřɨřɩřɪřɫƄř
ƃɬřɭřɮřɯřɰƄƄƀ
ʴʴʴƒƃɨřɩƄ
7

Это отличается от двумерного списка, в котором индексы лежат в разных парах


квадратных скобок:
ʴʴʴŽʰƃƃɥřɨřɩřɪřɫƄřƃɬřɭřɮřɯřɰƄƄ
ʴʴʴŽ
ƃƃɥřɨřɩřɪřɫƄřƃɬřɭřɮřɯřɰƄƄ
ʴʴʴŽƃɨřɩƄ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
›’‡””‘”śŽ‹•–‹†‹ ‡•—•–„‡‹–‡‰‡”•ř‘––—’އ
ʴʴʴŽƃɨƄƃɩƄ
7

Еще один момент: разбиение работает, но опять же только внутри множества,


заключенного в один набор квадратных скобок. Снова создадим привычный про-
верочный массив:
ʴʴʴƒʰ’Ŝƒ”ƒ‰‡ſɨɥƀ
ʴʴʴƒʰƒŜ”‡•Šƒ’‡ſɩřɬƀ
ʴʴʴƒ
ƒ””ƒ›ſƃƃɥřɨřɩřɪřɫƄř
ƃɬřɭřɮřɯřɰƄƄƀ

Используйте разбиение, чтобы получить первый ряд — элементы, начиная со


смещения ɩ, до конца:
ʴʴʴƒƃɥřɩśƄ
ƒ””ƒ›ſƃɩřɪřɫƄƀ

Теперь получим последний ряд — все элементы вплоть до третьего с конца:


ʴʴʴƒƃŞɨřśɪƄ
ƒ””ƒ›ſƃɬřɭřɮƄƀ
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

Вы также можете присвоить значение более чем одному элементу с помощью


разбиения. Следующее выражение присваивает значение ɨɥɥɥ столбцам (смеще-
ниям) ɩ и ɪ каждого ряда:
ʴʴʴƒƃśřɩśɫƄʰɨɥɥɥ
ʴʴʴƒ
ƒ””ƒ›ſƃƃɥřɨřɨɥɥɥřɨɥɥɥřɫƄř
ƃɬřɭřɨɥɥɥřɨɥɥɥřɰƄƄƀ

ǴȈȚȍȔȈȚȐȒȈȔȈșșȐȊȖȊ
Создание и изменение формы массивов так нас увлекли, что мы почти забыли
сделать с ними нечто более полезное. Для начала мы задействуем переопреде-
ленный в NumPy оператор умножения (*), чтобы умножить все значения массива
за раз:
ʴʴʴˆ”‘—’›‹’‘”–Ƌ
ʴʴʴƒʰƒ”ƒ‰‡ſɫƀ
ʴʴʴƒ
ƒ””ƒ›ſƃɥřɨřɩřɪƄƀ
ʴʴʴƒƋʰɪ
ʴʴʴƒ
ƒ””ƒ›ſƃɥřɪřɭřɰƄƀ

Если вы пытались умножить каждый элемент обычного списка Python на число,


то вам бы понадобились цикл или включение:
ʴʴʴ’Žƒ‹ɏŽ‹•–ʰŽ‹•–ſ”ƒ‰‡ſɫƀƀ
ʴʴʴ’Žƒ‹ɏŽ‹•–
ƃɥřɨřɩřɪƄ
ʴʴʴ’Žƒ‹ɏŽ‹•–ʰƃ—Ƌɪˆ‘”—‹’Žƒ‹ɏŽ‹•–Ƅ
ʴʴʴ’Žƒ‹ɏŽ‹•–
ƃɥřɪřɭřɰƄ

Такое поведение применимо и к сложению, вычитанию, делению и другим функ-


циям библиотеки NumPy. Например, вы можете инициализировать все элементы
массива любым значением с помощью функции œ‡”‘•ſƀ и оператора сложения ʫ:
ʴʴʴˆ”‘—’›‹’‘”–Ƌ
ʴʴʴƒʰœ‡”‘•ſſɩřɬƀƀʫɨɮŜɥ
ʴʴʴƒ
ƒ””ƒ›ſƃƃɨɮŜřɨɮŜřɨɮŜřɨɮŜřɨɮŜƄř
ƃɨɮŜřɨɮŜřɨɮŜřɨɮŜřɨɮŜƄƄƀ

dzȐȕȍȑȕȈȧȈȓȋȍȉȘȈ
NumPy содержит множество функций линейной алгебры. Например, определим
такую систему линейных уравнений:
ɫšʫɬ›ʰɩɥ
šʫɩ›ʰɨɪ
ǫȓȈȊȈ3\WKRQȊȕȈțȒȍ  

Как найти ȩ и ȧ? Создадим два массива:


‰коэффициенты (множители для ȩ и ȧ);
‰зависимые переменные (правая часть уравнения).
ʴʴʴ‹’‘”–—’›ƒ•’
ʴʴʴ ‘‡ˆˆ‹ ‹‡–•ʰ’Ŝƒ””ƒ›ſƃƃɫřɬƄřƃɨřɩƄƄƀ
ʴʴʴ†‡’‡†‡–•ʰ’Ŝƒ””ƒ›ſƃɩɥřɨɪƄƀ

Теперь используем функцию •‘Ž˜‡ſƀ модуля linalg:


ʴʴʴƒ•™‡”•ʰ’ŜŽ‹ƒŽ‰Ŝ•‘Ž˜‡ſ ‘‡ˆˆ‹ ‹‡–•ř†‡’‡†‡–•ƀ
ʴʴʴƒ•™‡”•
ƒ””ƒ›ſƃŞɯŜɪɪɪɪɪɪɪɪřɨɥŜɭɭɭɭɭɭɭɮƄƀ

В результате получим, что š примерно равен ŷɯŜɪ, а ȧ примерно равен ɨɥŜɭ.


Являются ли эти числа решениями уравнения?
ʴʴʴɫƋƒ•™‡”•ƃɥƄʫɬƋƒ•™‡”•ƃɨƄ
ɩɥŜɥ
ʴʴʴɨƋƒ•™‡”•ƃɥƄʫɩƋƒ•™‡”•ƃɨƄ
ɨɪŜɥ

Так и есть. Чтобы напечатать меньше текста, вы также можете дать NumPy ука-
зание найти скалярное произведение массивов:
ʴʴʴ’”‘†— –ʰ’Ŝ†‘–ſ ‘‡ˆˆ‹ ‹‡–•řƒ•™‡”•ƀ
ʴʴʴ’”‘†— –
ƒ””ƒ›ſƃɩɥŜřɨɪŜƄƀ

Если решение верно, то значения массива ’”‘†— – должны быть близки к значе-
ниям массива †‡’‡†‡–•. Функция ƒŽŽ Ž‘•‡ſƀ позволяет проверить, являются ли
массивы хотя бы приблизительно равными (они могут быть не полностью равными
из-за округления чисел с плавающей точкой):
ʴʴʴ’ŜƒŽŽ Ž‘•‡ſ’”‘†— –ř†‡’‡†‡–•ƀ
”—‡

NumPy также имеет модули для работы с многочленами, преобразованиями


Фурье, статистикой и распределением вероятностей.

ǩȐȉȓȐȖȚȍȒȈ6FL3\
Библиотека SciPy (KWWSZZZVFLS\RUJ) создана на основе NumPy и имеет даже боль-
ше математических и статистических функций. Релиз SciPy (KWWSVRUHLOO\<Y*)
содержит NumPy, SciPy, Pandas (ее мы рассмотрим позже в этой главе) и другие
библиотеки.
SciPy содержит множество модулей, включая те, которые выполняют следующие
задачи:
‰оптимизацию;
‰ведение статистики;
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰интерполяцию;
‰линейную регрессию;
‰интеграцию;
‰обработку изображений;
‰обработку сигналов.
Если вы уже работали с другими научными инструментами для компьютера, то
обнаружите, что Python, NumPy и SciPy охватывают области, с которыми работает
также коммерческий MATLAB (KWWSVRUHLOO\M2302) или приложение с открытым
исходным кодом R (KWWSZZZUSURMHFWRUJ).

ǩȐȉȓȐȖȚȍȒȈ[Link]
Как и предыдущая библиотека, SciKit (KWWSVVFLNLWVDSSVSRWFRP) — это группа науч-
ных пакетов, построенная на основе SciPy. SciKit-Learn (KWWSVVFLNLWOHDUQRUJ) — это
пакет, который специализируется на машинном обучении: поддерживает моделиро-
вание, классификацию, кластеризацию и разнообразные алгоритмы.

3DQGDV
С недавнего времени распространено употребление словосочетания «наука о дан-
ных». Я слышал определения «статистика, собираемая на Mac» или «статистика, со-
бираемая в Сан-Франциско». Как бы вы ни определили науку о данных, инструмен-
ты, о которых я говорил ранее, — NumPy, SciPy и собственно Pandas, вынесенный
в тему этого подраздела, — компоненты растущего популярного инструментария,
работающего с данными. (Mac и Сан-Франциско опциональны.)
Pandas (KWWSSDQGDVS\GDWDRUJ) — это новый пакет для интерактивного анализа
данных. Он особенно полезен для манипулирования данными реального мира с по-
мощью комбинирования матричной математики NumPy и возможности обработки
таблиц и реляционных баз данных. В книге Python for Data Analysis: Data Wrangling
with Pandas, NumPy and IPython Уэса Маккини1 (издательство O’Reilly) рассматри-
вается выпас данных с помощью NumPy, Python и Pandas.
NumPy ориентирован на традиционные научные вычисления, которые, как пра-
вило, манипулируют многомерными множествами данных одного типа, обычно
числами с плавающей точкой. Pandas больше похож на редактор базы данных, об-
рабатывающий несколько типов данных в группе. В некоторых языках такие группы
называются записями или структурами. Pandas определяет базовую структуру
данных, называемую ƒ–ƒ ”ƒ‡. Она представляет собой упорядоченную коллек-
цию граф с именами и типами и напоминает таблицу, именованный кортеж или
вложенный словарь в Python. Ее предназначение заключается в упрощении работы
с любыми данными, которые можно встретить не только в науке, но и в бизнесе.

1
Маккини У. Python и анализ данных. — М.: ДМК-Пресс, 2015.
ǫȓȈȊȈ3\WKRQȊȕȈțȒȍ  

Фактически Pandas разрабатывался для работы с финансовыми данными, наиболее


распространенной альтернативой для которых является электронная таблица.
Pandas — это ETL-инструмент для реальных данных — с отсутствующими значе-
ниями, странными форматами, странными измерениями — всех типов. Вы можете
разделить, объединить, заполнить, сконвертировать, изменить форму, разбить
данные, а также скачать и сохранить файлы. Он интегрируется с инструментами,
которые мы только что обсудили: NumPy, SciPy, iPython — для подсчета статистики,
подгонки данных под модель, рисования диаграмм, публикации и т. д.
Большинство ученых хотят выполнять свою работу, не тратя месяцы на то, чтобы
стать экспертами в эзотерических языках программирования или приложениях.
Python помогает им быстрее стать более продуктивными.

3\WKRQȐȕȈțȟȕȣȍȖȉȓȈșȚȐ
Мы рассматривали инструменты Python, которые можно использовать практи-
чески в любой области науки. Но как насчет программного обеспечения и до-
кументации, нацеленных на конкретные научные области? Рассмотрим примеры
использования Python для решения определенных задач и несколько узконаправ-
ленных библиотек.
Общие:
‰вычисления Python в науке и инженерном деле (KWWSELWO\S\FRPSVFL);
‰интенсивный курс Python для ученых (KWWSELWO\S\IRUVFL).
Физика:
‰физические вычисления (KWWSELWO\FRPSSK\VS\);
‰Astropy (KWWSVZZZDVWURS\RUJ);
‰SunPy (KWWSVVXQS\RUJ) (анализ данных, поступающих с Солнца);
‰MetPy (KWWSVXQLGDWDJLWKXELR0HW3\) (анализ метеорологических данных);
‰Py-ART (KWWSVDUPGRHJLWKXELRS\DUW) (погодный радар);
‰Community Intercomparison Suite (KWWSZZZFLVWRROVQHW) (атмосферные науки);
‰Freud (KWWSVIUHXGUHDGWKHGRFVLR) (анализ траектории);
‰Platon (KWWSVSODWRQUHDGWKHGRFVLR) (атмосферы экзопланет);
‰PSI4 (KWWSSVLFRGHRUJ) (квантовая химия);
‰OpenQuake Engine (KWWSVJLWKXEFRPJHPRTHQJLQH);
‰yt (KWWSV\WSURMHFWRUJ) (волюметрический анализ данных).
Биология и медицина:
‰Biopython (KWWSVELRS\WKRQRUJ);
‰Python для биологов (KWWSS\WKRQIRUELRORJLVWVFRP);
‰Введение в прикладную биоинформатику (KWWSUHDGLDERUJ);
  ǿȈșȚȤ,, ‡ 3\WKRQȕȈȗȘȈȒȚȐȒȍ

‰Нейровизуализация с помощью Python (KWWSQLS\RUJ);


‰MNE (KWWSVZZZPDUWLQRVRUJPQH) (визуализация нейрофизиологических данных);
‰PyMedPhys (KWWSVS\PHGSK\VFRP);
‰Nengo (KWWSVZZZQHQJRDL) (симулятор нейронов).
Проводятся следующие международные конференции по Python и научным
данным:
‰PyData (KWWSS\GDWDRUJ);
‰SciPy (KWWSFRQIHUHQFHVFLS\RUJ);
‰EuroSciPy (KWWSVZZZHXURVFLS\RUJ).

ǿȐȚȈȑȚȍȌȈȓȍȍ
Мы достигли конца наблюдаемой вселенной Python, за исключением приложений
из мультивселенной.

ǻȗȘȈȎȕȍȕȐȧ
22.1. Установите Pandas. Получите CSV-файл в примере 16.1. Запустите программу
из примера 16.2. Поэкспериментируйте с командами Pandas.
ǷȘȐȓȖȎȍȕȐȧ
ƗƘƐƓƖƎƍƕƐƍƈ
ǨȗȗȈȘȈȚȕȖȍȐȗȘȖȋȘȈȔȔȕȖȍ
ȖȉȍșȗȍȟȍȕȐȍȌȓȧȕȈȟȐȕȈȦȡȐȝ
ȗȘȖȋȘȈȔȔȐșȚȖȊ

Некоторые вещи понятны на интуитивном уровне. Что-то мы видим в природе, что-


то изобрел человек — например, колесо или пиццу.
В другие вещи нужно просто поверить. Как телевидение преобразует невидимые
колебания в воздухе в звук и движущиеся изображения?
Компьютер попадает во вторую категорию. Как добиться того, чтобы машина
поняла и выполнила напечатанное вами?
Когда я учился программированию, было трудно найти ответы на какие-то про-
стые вопросы. Например, в некоторых книгах память компьютера объясняется через
аналогию с библиотечной книжной полкой. Мне казалось: если вы читаете данные
из памяти, то в рамках аналогии берете книгу с полки. Означает ли это, что книга
удаляется из памяти? На самом деле нет. Это больше похоже на получение копии
книги с полки.
В данном приложении приводится краткий обзор аппаратного и программного
обеспечения компьютера, если вы относительно недавно начали программировать.
Я попробую объяснить то, что в будущем станет очевидным, но сейчас эта инфор-
мация может стать хорошей отправной точкой.

ǨȗȗȈȘȈȚȕȖȍȖȉȍșȗȍȟȍȕȐȍ
DzȖȔȗȤȦȚȍȘȣȗȍȡȍȘȕȣȝȓȦȌȍȑ
Когда пещерные люди Ог и Тог возвращались с охоты, они подходили к своим куч-
кам камней и клали в каждую из них по одному камню за каждого убитого мамонта.
Но эти кучи годились, только чтобы похвастаться тем, что у одного из них камней
больше, чем у другого.
Далекие потомки Ога (Тог был растоптан мамонтом, когда клал очередной ка-
мень) научились считать, писать и пользоваться абаком. Но, чтобы перейти от этих
инструментов к концепции компьютера, потребуется задействовать воображение
и технологические достижения. Первая необходимая технология — электричество.
ǷȘȐȓȖȎȍȕȐȍǨǨȗȗȈȘȈȚȕȖȍȐȗȘȖȋȘȈȔȔȕȖȍȖȉȍșȗȍȟȍȕȐȍ  

ȅȓȍȒȚȘȐȟȍșȚȊȖ
Бен Франклин считал, что электричество — это поток некой невидимой жидкости
из места с большим количеством жидкости (положительного) в место с меньшим
количеством (отрицательное). Он был прав, но перепутал термины. Электроны
путешествуют от «отрицательного» места в «положительное», но они были откры-
ты гораздо позже — менять терминологию оказалось слишком поздно. Поэтому
с тех пор нам нужно помнить, что электроны движутся в одну сторону, а ток течет
в другую.
Все мы знакомы с такими природными электрическими феноменами, как стати-
ческое электричество или молнии. После того как люди открыли способ отправить
электроны по проводам для создания электрических цепей, мы еще на один шаг
приблизились к созданию компьютеров.
Раньше я думал, что электрический ток в проводе вызывается проворными
электронами, которые нарезают круги по всей дистанции. На самом деле это не так.
Электроны перемещаются от одного атома к другому. Они ведут себя как шарико-
подшипники в трубке (или шарики тапиоки в соломинке). Добавленный с одного
конца шарик толкает соседа. Так происходит до тех пор, пока шарик с противопо-
ложного конца не вытолкнется. Как правило, электроны перемещаются медленно
(скорость перемещения по проводу составляет примерно три дюйма в час), однако
это практически мгновенное столкновение очень быстро распространяет электро-
магнитную волну: ее скорость составляет от 50 до 99 % скорости света в зависимости
от проводника.

ǰȏȖȉȘȍȚȍȕȐȧ
Нам все еще нужно следующее:
‰способ запоминать какие-то данные;
‰способ что-то сделать с теми данными, которые мы запомнили.
Одной из концепций памяти был выключатель — предмет, который либо вклю-
чен, либо выключен, при этом он сохраняет свое состояние до тех пор, пока что-то
не переключит его в другое состояние. Электрический выключатель работает, от-
крывая и закрывая цепь, позволяя электронам течь по ней или блокируя их. Мы по-
стоянно используем выключатели, чтобы управлять светом и другими электриче-
скими устройствами. Нужен был способ управлять самим выключателем с помощью
электричества.
Самые первые компьютеры (и телевизоры) использовали для этих целей ваку-
умные трубки, но те были довольно большими и часто перегорали. Ключевым изо-
бретением, приведшим к появлению современных компьютеров, явился транзистор:
маленький, эффективный и надежный. Финальным аккордом стало значительное
уменьшение размеров транзисторов и объединение их в интегральные схемы.
С течением лет компьютеры становились быстрее и дешевели по мере того, как
их размеры уменьшались. Сигналы перемещаются быстрее, когда компоненты на-
ходятся рядом друг с другом.
  ǷȘȐȓȖȎȍȕȐȧ

Однако существует предел тому, насколько маленьким можно сделать транзи-


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

ǰȌȍȈȓȤȕȣȑȒȖȔȗȤȦȚȍȘ
Реальные компьютеры имеют множество сложных особенностей. Сконцентрируемся
на самых необходимых компонентах.
Интегральная плата содержит центральный процессор, память и провода, со-
единяющие их друг с другом и другими устройствами.

ǷȘȖȞȍșșȖȘ
ЦП (центральный процессор), или чип, выполняет собственно вычисления:
‰математические задачи вроде сложения;
‰сравнение значений.

ǷȈȔȧȚȤȐȒȥȠ
ОЗУ (оперативное запоминающее устройство) занимается «запоминанием». Оно ра-
ботает быстро, но энергозависимо (данные теряются, если выключается питание).
ЦП становятся еще быстрее, чем память, поэтому разработчики компьютеров
добавляют кэши: небольшие и более быстрые участки памяти, располагающиеся
между процессором и основной памятью. Пытаясь считать байты из памяти, ваш ЦП
сначала обращается к ближайшему кэшу (он называется L1), затем к следующему
(L2) и, наконец, к основной памяти.

ǽȘȈȕȍȕȐȍ
Поскольку основная память теряет данные, нам также нужно энергонезависимое
хранилище. Такие устройства дешевле, чем память, и хранят гораздо больше данных,
но и работают медленнее.
Традиционный метод хранения — магнитные диски (или жесткие диски — hard
drives, HDD) с перемещающимися головками, которые отвечают за чтение и запись,
как виниловые пластинки и стилус.
Гибридная технология называется SSD (Solid State Drive — твердотельный на-
копитель). Он изготавливается из полупроводников, как и ОЗУ, но при этом энер-
гонезависим, как магнитные диски. Цена и скорость работы выше, чем у HDD, но
ниже, чем у ОЗУ.
ǷȘȐȓȖȎȍȕȐȍǨǨȗȗȈȘȈȚȕȖȍȐȗȘȖȋȘȈȔȔȕȖȍȖȉȍșȗȍȟȍȕȐȍ  

ǪȊȖȌȌȈȕȕȣȝ
Как вы помещаете данные в компьютер? Для людей основные варианты — это кла-
виатуры, мыши и сенсорные экраны.

ǪȣȊȖȌȌȈȕȕȣȝ
Как правило, люди видят данные с помощью экранов и принтеров.

ǶȚȕȖșȐȚȍȓȤȕȖȍȊȘȍȔȧȌȖșȚțȗȈ
Время, которое требуется для записи и получения данных из этих компонентов,
может значительно различаться. Это оказывает большое практическое влия-
ние. Например, ПО должно работать в памяти и получать оттуда данные, но также
должно надежно сохранять их в энергонезависимых устройствах, таких как диски.
Проблема заключается в том, что диски в тысячи раз медленнее, а сеть — и того
больше. Это значит, что программисты тратят много времени на выбор наилучшего
компромиссного решения между скоростью и стоимостью.
В статье Computer Latency at a Human Scale (KWWSVRUHLOO\*T') Дэвид Джеп-
песен сравнивает устройства. Я перенес его изыскания и другие исследования
в табл. А.1. Последние столбцы — соотношение, относительное время (ЦП — одна
секунда) и относительное расстояние (ЦП — один дюйм) — помогут лучше понять
эту таблицу.
ǺȈȉȓȐȞȈ$ǶȚȕȖșȐȚȍȓȤȕȖȍȊȘȍȔȧȌȖșȚțȗȈ

ǸȈșȗȖȓȖȎȍȕȐȍ ǪȘȍȔȧ ǹȖȖȚȕȖȠȍȕȐȍ ǶȚȕȖșȐȚȍȓȤȕȖȍ ǶȚȕȖșȐȚȍȓȤȕȖȍ


ȊȘȍȔȧ ȘȈșșȚȖȧȕȐȍ
ЦП 0,4 нс 1 1с 1 дюйм
Кэш L1 0,9 нс 2 2с 2 дюйма
Кэш L2 2,8 нс 7 7с 7 дюймов
Кэш L3 28 нс 70 1 мин 6 футов
ОЗУ 100 нс 250 4 мин 20 футов
SSD 100 мкс 250 000 3 дня 4 мили
Магнитный диск 10 мс 25 000 000 9 месяцев 400 миль
Интернет: SFĺNY 65 мс 162 500 000 5 лет 2500 миль

Хорошо, что выполнение инструкции процессора на самом деле занимает меньше


наносекунды, поскольку в противном случае за то время, которое потребовалось бы
для обращения к диску несколько раз, у вас мог бы родиться ребенок. Время отклика
диска и сети гораздо больше, чем для ЦП и ОЗУ, поэтому полезно выполнять в па-
мяти максимально много работы. И поскольку процессор сам по себе быстрее, чем
ОЗУ, лучше иметь последовательные данные, чтобы байты можно было отправить
в более быстрые (и менее объемные) кэши, расположенные ближе к ЦП.
  ǷȘȐȓȖȎȍȕȐȧ

ǷȘȖȋȘȈȔȔȕȖȍȖȉȍșȗȍȟȍȕȐȍ
Как же управлять всем этим оборудованием? Для начала нужны инструкции (коман-
ды, которые указывают процессору, что делать) и данные (входные и выходные па-
раметры инструкций). В компьютерах с запоминаемой программой данными можно
считать все, что упрощает процесс проектирования. Но как представить инструкции
и данные? Что, если они сохраняются в одном месте, а выполняются в другом?
Дальние родственники пещерного человека Ога очень хотели бы узнать это.

ǪȕȈȟȈȓȍȉȣȓȉȐȚ
Вернемся к идее выключателя — чего-то, что сопровождает одно из двух значений.
Он может быть либо выключен, либо включен, иметь либо высокое, либо низкое
напряжение, быть положительным или отрицательным — он получает значение,
не забывает его и может предоставить любому, кто запросит это значение. Инте-
гральные схемы дали нам способ интегрировать и соединить миллиарды маленьких
переключателей в маленькие чипы.
Если переключатель может иметь всего два значения, то его можно использовать
для того, чтобы представить бит, или бинарную цифру. Ее значения можно расцени-
вать как ɥ и ɨ, да и нет, true и false или любым другим удобным для нас способом.
Однако биты слишком малы, чтобы представить какое-либо значение, помимо ɥ
и ɨ. Как нам убедить биты представлять более крупные объекты?
Чтобы получить ответ, взгляните на свои пальцы. Мы используем всего десять
цифр (от 0 до 9) в повседневной жизни, а числа больше 9 получаются благодаря
позиционной записи. Если я добавлю 1 к числу 38, то 8 станет 9 и мы получим значе-
ние 39. Если я добавлю еще 1, то 9 превратится в 0, а 1 перенесется влево, увеличивая
3 до 4, что даст нам результат, равный 40. Крайнее правое число — это «колонка
единиц», то, что слева от него, — «колонка десятков» и т. д., по мере продвижения
влево выполняется умножение на 10. С помощью трех десятичных чисел вы можете
представить тысячу (10 * 10 * 10) чисел от ɥɥɥ до 999.
Мы можем использовать позиционную запись и для битов, объединяя их в более
крупные коллекции. Байт имеет 8 бит и может представлять 28 (256) возможных
комбинаций. Вы можете использовать байт для сохранения, например, небольших
чисел от ɥ до ɩɬɬ (в позиционной записи нужно оставить место для нуля).
Байт выглядит как последовательность из 8 бит, каждый из которых имеет либо
значение ɥ (или «выкл.», или false), либо значение ɨ (или «вкл.», или true). Самый
правый бит — наименее значимый, а самый левый — наиболее значимый.

ǴȈȠȐȕȕȣȑȧȏȣȒ
ЦП каждого компьютера разработан с набором инструкций, представленных ма-
сками битов (они еще называются кодами операций), которые он может понимать.
Каждый код операции выполняет определенную функцию; ее входные значения
находятся в одном месте, а выходные — в другом. В процессоре есть специальные
внутренние локации, называемые регистрами, в которых хранятся коды операций
и значения.
ǷȘȐȓȖȎȍȕȐȍǨǨȗȗȈȘȈȚȕȖȍȐȗȘȖȋȘȈȔȔȕȖȍȖȉȍșȗȍȟȍȕȐȍ  

Воспользуемся упрощенным компьютером, который работает только с байтами


и имеет четыре регистра размером 1 байт, которые называются , ,  и . Предпо-
ложим следующее:
‰код операции команды помещается в регистр Ǡ;
‰команда получает входные значения из регистров  и ;
‰команда сохраняет результат в регистре .
(Сложение 2 байт может вызвать переполнение регистра, но в рамках данного
примера мы это проигнорируем.)
Предположим, что:
‰в регистре  содержится код операции сложения двух целых чисел: десятичная ɨ
(бинарное представление — ɥɥɥɥɥɥɥɨ);
‰в регистре  содержится десятичное значение ɬ (бинарное представление —
ɥɥɥɥɥɨɥɨ);
‰в регистре  содержится десятичное значение ɪ (бинарное представление —
ɥɥɥɥɥɥɨɨ).
ЦП видит, что в регистре Ǡ появилась инструкция. Он декодирует и запускает ее,
читая значения из регистров Ǣ и DZ и передавая их во внутренние цепи, которые могут
выполнять сложение. При получении результата мы должны увидеть десятичное
значение ɯ (бинарное представление — ɥɥɥɥɨɥɥɥ) в регистре .
Процессор выполняет сложение и другие математические функции, исполь-
зуя регистры похожим способом. Он декодирует код операции и перенаправляет
управление конкретным цепям внутри ЦП. Он также может сравнивать объекты,
например, «Больше ли значение регистра Ǣ, чем значение регистра DZ?» Кроме того,
немаловажно, что он получает значения из памяти в процессоре и сохраняет зна-
чения из него в памяти.
Компьютер сохраняет программы (инструкции на машинном языке и данные)
в памяти и обрабатывает передачу инструкций и данных в ЦП и из него.

ǨșșȍȔȉȓȍȘ
На машинном языке программировать сложно. Вам нужно идеально указывать
каждый бит, что занимает очень много времени. Поэтому люди придумали чуть
более читаемый уровень языков, которые называются ассемблерными языками или
просто ассемблерами. Для каждого варианта процессора существует свой ассемблер.
Такие языки позволяют использовать имена переменных, чтобы определить поток
инструкций и данные.

ǪȣșȖȒȖțȘȖȊȕȍȊȣȍȧȏȣȒȐ
Чтобы освоить ассемблер, требуется приложить немало усилий, поэтому люди
разработали более высокоуровневые языки, которые им было бы проще использо-
вать. Такие языки транслируются в ассемблер программой, которая называется
компилятором, или же запускаются непосредственно с помощью интерпретатора.
  ǷȘȐȓȖȎȍȕȐȧ

Одними из самых старых подобных языков являются FORTRAN, LISP и С — их


дизайн и предполагаемое использование значительно различаются, но объединяет
эти языки их место в компьютерной архитектуре.
Для реальных задач, как правило, выделяют определенные «стеки» ПО:
‰Мейнфрейм — IBM, COBOL, FORTRAN и др.;
‰Microsoft — Windows, ASP, C#, SQL Server;
‰JVM — Java, Scala, Groovy;
‰системы с открытым исходным кодом — Linux, языки (Python, PHP, Perl, C,
C++, Go), базы данных (MySQL, PostgreSQL), веб (apache, nginx).
Программисты обычно остаются в одном из этих миров, используя языки и ин-
струменты внутри него. Некоторые технологии, такие как TCP/IP и веб, позволяют
этим стекам взаимодействовать.

ǶȗȍȘȈȞȐȖȕȕȣȍșȐșȚȍȔȣ
Каждая инновация построена на других новшествах, появившихся до нее, и обычно
мы не знаем (или нам неважно), как работают более низкие уровни. Инструменты
строят инструменты для создания еще большего количества инструментов, и мы
принимаем это как должное.
Рассмотрим основные операционные системы:
‰Windows (Microsoft) — коммерческая, много версий;
‰macOS (Apple) — коммерческая;
‰Linux — открытый исходный код;
‰Unix — много коммерческих версий, в основном замененных на Linux.
Операционная система состоит из следующих компонентов:
‰ядро — планирует выполнение программ и управляет ими, а также вводом/вы-
водом;
‰драйверы устройств — используются ядром для получения доступа к ОЗУ, диску
и другим устройствам;
‰библиотеки — файлы исходного кода и бинарные файлы, используемые разра-
ботчиками;
‰приложения — отдельные программы.
Один компьютер может поддерживать больше одной операционной системы,
но за один раз запускается только одна. Процесс запуска ОС называется начальной
загрузкой (booting1), перезапуск — перезагрузкой (rebooting). Эти термины появи-
лись даже в области маркетинга фильмов — студии «перезагружают» предыдущие

1
Это отсылает к выражению «тянуть себя за шнурки ботинок» (lifting yourself by your own
bootstraps), что выглядит так же невероятно, как и компьютер.
ǷȘȐȓȖȎȍȕȐȍǨǨȗȗȈȘȈȚȕȖȍȐȗȘȖȋȘȈȔȔȕȖȍȖȉȍșȗȍȟȍȕȐȍ  

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


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

ǪȐȘȚțȈȓȤȕȣȍȔȈȠȐȕȣ
Операционная система — по сути, большая программа, поэтому в конечном счете
кто-то придумал способ запустить чужие операционные системы как виртуальные
машины (гостевые программы) на своих хост-машинах. Вы можете установить на
свой компьютер Microsoft Windows, а затем в то же время запустить Linux на вирту-
альной машине, не покупая второй компьютер или не выполняя мультисистемную
загрузку.

DzȖȕȚȍȑȕȍȘȣ
Более свежая идея — это контейнер. Контейнер — способ запускать множество опе-
рационных систем одновременно до тех пор, пока у них одинаковое ядро. Идея была
популяризована командой разработчиков Docker (KWWSVZZZGRFNHUFRP) — они взя-
ли малоизвестные особенности ядра Linux и добавили к ним полезные возможности
по управлению. Их аналогия по отправке контейнеров (которая революционизиро-
вала отправку и сэкономила нам много денег) была прозрачной и привлекательной.
Выложив код в открытый доступ, команда разработчиков Docker добилась того, что
контейнеры быстро приняла вся компьютерная отрасль.
Google и другие облачные провайдеры добавляли поддержку ядра Linux годами
и использовали контейнеры в своих дата-центрах. Контейнеры используют меньше
ресурсов, чем виртуальные машины, что позволяет упаковывать больше программ
в одну коробку физического компьютера.

ǸȈșȗȘȍȌȍȓȍȕȕȣȍȊȣȟȐșȓȍȕȐȧȐșȍȚȐ
Когда бизнес только начал применять ПК, нужно было найти способ заставить ком-
пьютеры общаться друг с другом, а также с другими устройствами, например прин-
терами. Изначально использовалось проприетарное сетевое ПО, такое как Novell, но
в конечном счете его заменил стек протоколов TCP/IP, поскольку Интернет заметно
развился во второй половине 1990-х. Microsoft позаимствовала стек TCP/IP из бес-
платного варианта Unix, которая называется BSD1.
Одним из эффектов интернет-бума стал спрос на серверы: машины и ПО, кото-
рые позволяют запустить все сервисы для работы с вебом, чатами и электронной
почтой. Старый стиль сисадмина (системного администрирования) состоял в том,

1
В некоторых файлах Microsoft вы можете найти записи об авторских правах, принадле-
жащих Университету Калифорнии.
  ǷȘȐȓȖȎȍȕȐȧ

чтобы устанавливать все программное обеспечение и оборудование и управлять


им вручную. Спустя некоторое время стало понятно, что требуется автоматизация.
В 2006 году Билл Бейкер из компании Microsoft придумал аналогию «домашние
животные против крупного рогатого скота» (pets versus cattle) для управления
серверами, и с тех пор она стала мемом в нашей отрасли (иногда ее формулируют
как pets versus livestock) (табл. A.2).
ǺȈȉȓȐȞȈ$ǬȖȔȈȠȕȐȍȎȐȊȖȚȕȣȍȗȘȖȚȐȊșȒȖȚȈ

ǬȖȔȈȠȕȐȍȎȐȊȖȚȕȣȍ ǹȒȖȚ
Именуются индивидуально Нумеруются автоматически
Требуется индивидуальный подход Стандартизированы
Восстанавливаются при сбоях Заменяются при сбоях

Вы можете встретить наследника «сисадмина» — термин DevOps (development


and operations — «разработка и использование»). Он связан с набором приемов,
призванных поддержать быстрые изменения в сервисах, не вызвав в них перегру-
зок. Облачные сервисы могут быть очень крупными и сложными, и даже у крупных
компаний, таких как Amazon или Google, время от времени случаются сбои.

ǶȉȓȈȒȖ
Люди много лет создавали компьютерные кластеры, используя разные технологии.
Одной из более ранних концепций был Beowulf-кластер: идентичные компьютеры
для массовой обработки данных (от фирмы Dell или аналогов вместо рабочих стан-
ций от Sun или HP), связанные локальной сетью.
Термин облачные вычисления означает использование компьютеров в дата-цен-
трах для выполнения вычислений и хранения данных — однако не только для тех
компаний, которым принадлежат эти ресурсы бэкенда. Сервисы предоставляются
всем, а стоимость зависит от времени работы ЦП, занятого объема дисков и т. д.
Компания Amazon и ее AWS (Amazon Web Services) — самый известный облачный
сервис, но Azure (Microsoft) и Google Cloud также довольно велики.
На самом деле эти облака представляют собой пустые машины, виртуальные
машины и контейнеры — все они считаются скотом, а не домашними животными.

.XEHUQHWHV
Все компании, которым нужно управлять крупными кластерами компьютеров, рас-
положенных в нескольких дата-центрах, — например, Google, Amazon и Facebook —
создали или позаимствовали решения, которые позволяют этим компаниям мас-
штабироваться.
‰Развертывание. Как вы вводите в строй новое оборудование и программное обе-
спечение? Как вы заменяете его в случае сбоя?
‰Конфигурация. Как должны работать эти системы? Им нужны такие вещи, как
имена и адреса других компьютеров, пароли и настройки безопасности.
ǷȘȐȓȖȎȍȕȐȍǨǨȗȗȈȘȈȚȕȖȍȐȗȘȖȋȘȈȔȔȕȖȍȖȉȍșȗȍȟȍȕȐȍ  

‰Оркестрация. Как управлять всеми этими компьютерами, виртуальными маши-


нами и контейнерами? Можно ли выполнить масштабирование, чтобы соответ-
ствовать уменьшению или увеличению нагрузки?
‰Обнаружение сервисов. Как узнать, кто что делает и где находится?
Некоторые конкурирующие решения были созданы командой разработчиков
Docker и другими. Но за последние несколько лет стало ясно, что эту битву вы-
игрывает Kubernetes (KWWSNXEHUQHWHVLR).
Компания Google разработала крупные внутренние фреймворки для менеджмен-
та под кодовыми именами Borg и Omega. Когда сотрудники компании предложили
открыть исходный код этих «бриллиантов», руководство на некоторое время задума-
лось, но затем все же решилось. Google выпустила Kubernetes версии 1.0 в 2015 году,
и с тех пор его экосистема и влияние постоянно растут.
ƗƘƐƓƖƎƍƕƐƍƉ
ǻșȚȈȕȖȊȒȈ3\WKRQ

Большинство примеров этой книги были написаны и протестированы для Python 3.7,
последней стабильной версии на момент ее написания. Страница What’s New in
Python (KWWSVGRFVS\WKRQRUJZKDWVQHZ) представляет информацию о том, что было
добавлено в каждой версии. Существует множество исходных кодов Python и боль-
шое количество способов установить новую версию. В данном приложении я опишу
несколько из них.
‰Стандартный установщик загружает Python с сайта S\WKRQRUJ и добавляет вспо-
могательные программы, такие как pip и virtualenv.
‰Если ваша работа связана с наукой, то вам лучше подойдет версия Python, объ-
единенная с научными пакетами из Anaconda, — в таком случае вам нужно будет
использовать установщик ‘†ƒ вместо pip.
Windows не содержит Python, а в macOS, Linux и Unix, как правило, содержатся
старые версии. Пока они не наверстают упущенное, вам нужно будет установить
Python 3 самостоятельно.

ǷȘȖȊȍȘȤȚȍșȊȖȦȊȍȘșȐȦ3\WKRQ
В консоли или окне терминала введите команду python Ş:
ɛpython -V
›–Š‘ɪŜɮŜɩ

В зависимости от вашей операционной системы, если у вас нет Python или ОС


не может его найти, вы увидите сообщение об ошибке, например FRPPDQG QRW
IRXQG.
Если у вас есть Python версии 2.х, то вы можете захотеть установить Python 3 —
либо для всей системы, либо только для себя в virtualenv (см. подраздел «virtualenv»
на с. 434 или раздел «Установка virtualenv» данного приложения ниже). В этом
приложении я покажу, как установить Python 3 для всей системы.
ǷȘȐȓȖȎȍȕȐȍǩǻșȚȈȕȖȊȒȈ3\WKRQ  

ǻșȚȈȕȖȊȒȈșȚȈȕȌȈȘȚȕȖȑȊȍȘșȐȐ3\WKRQ
Перейдите в браузере на официальную страницу скачивания Python ( KWWSV
ZZZS\WKRQRUJGRZQORDGV). Она попробует определить вашу операционную систему
и предоставить подходящие вам варианты. Если она ошибется, то вы можете ис-
пользовать следующие ссылки:
‰версии Python для Windows (KWWSVZZZS\WKRQRUJGRZQORDGVZLQGRZV);
‰версии Python для macOS (KWWSVZZZS\WKRQRUJGRZQORDGVPDFRV[);
‰исходные коды Python (Linux и Unix) (KWWSVZZZS\WKRQRUJGRZQORDGVVRXUFH).
Вы увидите страницу, похожую на ту, что показана на рис. Б.1.

ǸȐșǩǷȘȐȔȍȘșȚȘȈȕȐȞȣȏȈȋȘțȏȒȐ

Нажав желтую кнопку 'RZQORDG3\WKRQ (Скачать Python 3.7.3), вы скачаете


эту версию для своей ОС. Если вы хотите сначала немного узнать об этой версии,
  ǷȘȐȓȖȎȍȕȐȧ

то нажмите синюю ссылку 3\WKRQ в первом столбце таблицы снизу, под строкой
5HOHDVHYHUVLRQ. Так вы попадете на страницу информации, похожую на ту, что по-
казана на рис. Б.2.

ǸȐșǩǹȚȘȈȕȐȞȈȗȖȌȘȖȉȕȖșȚȍȑȏȈȋȘțȏȒȐ

Вам нужно прокрутить страницу вниз, чтобы увидеть ссылки для скачивания
(рис. Б.3).

PDF26
Нажмите ссылку PDF26ELWELWLQVWDOOHU (KWWSVRUHLOO\O*), чтобы скачать файл
с расширением Ŝ’‰ для Mac. Дважды щелкните на нем, чтобы увидеть начальное
диалоговое окно (рис. Б.4).
Нажмите кнопку &RQWLQXH (Продолжить). Вы увидите последовательность других
диалоговых окон.
ǷȘȐȓȖȎȍȕȐȍǩǻșȚȈȕȖȊȒȈ3\WKRQ  

ǸȐșǩǵȐȎȕȧȧȟȈșȚȤșȚȘȈȕȐȞȣȗȘȍȌȓȈȋȈȦȡȈȧșȒȈȟȈȚȤ3\WKRQ

ǸȐșǩǷȍȘȊȣȑȥȒȘȈȕțșȚȈȕȖȊȖȟȕȖȋȖȌȐȈȓȖȋȈȌȓȧ0DF
  ǷȘȐȓȖȎȍȕȐȧ

Когда все будет готово, вы увидите диалог, показанный на рис. Б.5.

ǸȐșǩǬȍȊȧȚȣȑȥȒȘȈȕțșȚȈȕȖȊȖȟȕȖȋȖȌȐȈȓȖȋȈȌȓȧ0DF

Python 3 будет установлен в каталог XVUORFDOELQS\WKRQ, оставляя нетронутой


существующую версию Python 2 на вашем компьютере.

:LQGRZV
ОС Windows никогда не включала в себя Python, но с недавних пор упростила его
установку. Обновление Windows 10 от мая 2019 года (KWWSVRUHLOO\*$EI) включает
в себя файлы ’›–Š‘Ŝ‡š‡ и ’›–Š‘ɪŜ‡š‡. Это не интерпретаторы Python, а ссылки
на новую страницу в Microsoft Store, посвященную Python 3.7 (KWWSVRUHLOO\/N\BK).
Вы можете использовать эту ссылку, чтобы скачать и установить Python так же, как
вы это делаете для другого ПО.
Или же вы можете скачать и установить Python с официального сайта:
‰Windows x86 MSI installer (32-bit) (KWWSELWO\ZLQ[);
‰Windows x86-64 MSI installer (64-bit) (KWWSELWO\ZLQ[).
Чтобы определить, какая версия Windows установлена у вас (32- или 64-битная),
сделайте следующее:
‰нажмите кнопку ǷțșȒ;
‰щелкните правой кнопкой мыши на пункте ǴȖȑȒȖȔȗȤȦȚȍȘ;
‰выберите пункт меню ǹȊȖȑșȚȊȈ и найдите битовое значение.
Щелкните на соответствующем установщике (файл с расширением Ŝ•‹). После
того как он будет скачан, нажмите его дважды и следуйте инструкциям.
ǷȘȐȓȖȎȍȕȐȍǩǻșȚȈȕȖȊȒȈ3\WKRQ  

/LQX[ȐȓȐ8QL[
Пользователи Linux и Unix могут выбрать формат сжатия файлов исходного кода:
‰сжатие с помощью XZ (KWWSELWO\[]WDUEDOO);
‰сжатие с помощью Gzipped (KWWSELWO\J]LSWDUEDOO).
Скачайте любой из этих архивов. Разархивируйте его с помощью tar š (для
файла с расширением Ŝšœ) или tar šœ (для файла с расширением Ŝ–‰œ), а затем за-
пустите полученный сценарий оболочки.

ǻșȚȈȕȖȊȒȈȔȍȕȍȌȎȍȘȈȗȈȒȍȚȖȊSLS
Если вы вышли за пределы стандартной установки Python, то два инструмента
практически бесценны для разработки на Python: это pip и virtualenv.
Пакет pip — это самый популярный способ установить сторонние (нестандарт-
ные) пакеты Python. Несколько раздражало то, что такой полезный инструмент
не являлся частью стандартного Python и его приходилось скачивать и устанав-
ливать самостоятельно. Как говорил мой друг, это жестокий, пугающий ритуал.
Хорошая новость заключается в том, что, начиная с версии 3.4, pip — стандартная
часть Python.
Если у вас установлен Python 3, но под рукой только версия pip для Python 2, то
получить версию для Python 3 под Linux или macOS можно так:
ɛcurl -O [Link]
ɛsudo python3 distribute_setup.py
ɛcurl -O [Link]
ɛsudo python3 [Link]

Это установит ’‹’ŞɪŜɪ в каталог bin вашей версии Python 3. Далее для установки
сторонних пакетов вы можете использовать ’‹’ŞɪŜɪ вместо версии для Python 2.

ǻșȚȈȕȖȊȒȈYLUWXDOHQY
Программа virtualenv зачастую применяется вместе с pip и представляет собой
способ установить пакеты Python в определенный каталог (папку), чтобы избежать
пересечений с пакетами Python, уже существующими в системе. Это позволяет ис-
пользовать любые пакеты Python, даже если у вас нет разрешения изменять суще-
ствующие установленные пакеты.
Ниже представлена пара хороших руководств по pip и virtualenv:
‰A Non-Magical Introduction to Pip and Virtualenv for Python Beginners (KWWSELWO\
MPSLSYOHQY);
‰The Hitchhiker’s Guide to Packaging: Pip (KWWSELWO\KKJSSLS).
  ǷȘȐȓȖȎȍȕȐȧ

ǬȘțȋȐȍșȗȖșȖȉȣȘȈȉȖȚȣșȗȈȒȍȚȈȔȐ
Как вы уже видели, техники упаковки пакетов в Python различаются, и ни одна из
них не может решить сразу все задачи. PyPA (KWWSVZZZS\SDLR) (Python Packaging
Authority) — это группа добровольцев (не являющаяся частью официальной группы
по разработке ядра Python), которая работает над тем, чтобы упростить взаимодей-
ствие с пакетами Python. Группа написала руководство Python Packaging User’s
Guide (KWWSVSDFNDJLQJS\WKRQRUJ), где рассматриваются известные проблемы и их
решения.
Самые популярные инструменты — pip и virtualenv, я использовал их на протя-
жении всей этой книги. Если они не могут вам помочь или же вы хотите попробовать
что-то новое, то вот несколько альтернатив:
‰pipenv (KWWSVSLSHQYUHDGWKHGRFVLR) объединяет в себе pip и virtualenv, а также
включает и другие возможности. Обратите внимание на критику, которой он
подвергался (KWWSVRUHLOO\14S+), и обсуждение (KWWSVRUHLOO\SV:D);
‰poetry (KWWSVSRHWU\HXVWDFHLR) — это конкурент, который решает некоторые про-
блемы pipenv.
Но самой главной альтернативой, особенно если речь идет о научных или рабо-
тающих с большими данными приложениях, является ‘†ƒ. Вы можете получить
ее как часть дистрибутива Anaconda, о котором я поговорю далее, или же отдельно
(см. раздел «Устанавливаем Anaconda» ниже).

ǻșȚȈȕȈȊȓȐȊȈȍȔ$QDFRQGD
Anaconda (KWWSVGRFVDQDFRQGDFRPDQDFRQGD) — это всеобъемлющий установщик с ак-
центом на науку. Последняя версия, Anaconda3, включает в себя Python 3.7 и его
стандартную библиотеку, а также язык R для приложений, посвященных науке
о данных. Среди других плюсов — библиотеки, о которых мы говорили ранее в этой
книге: beautifulsoup4, Flask, ipython, Matplotlib, nose, numpy, Pandas, pillow, pip, scipy,
tables, zmq и множество других. Anaconda содержит кросс-платформенную программу
установки, которая называется ‘†ƒ, мы рассмотрим ее в следующем пункте.
Чтобы установить Anaconda 3, посетите страницу скачивания (KWWSVZZZDQD
FRQGDFRPGLVWULEXWLRQ) версий Python 3. Нажмите соответствующую ссылку для вашей
платформы (номера версий изменились с момента написания данного текста, но вы
сможете в этом разобраться):
‰установщик для macOS установит все в каталог ƒƒ ‘†ƒ, расположенный под
вашим домашним каталогом;
‰для Windows два раза щелкните на файле с расширением Ŝ‡š‡ после того, как
он скачается;
‰для Linux выберите 32- или 64-битную версию. После скачивания запустите его
(это большой сценарий оболочки).
ǷȘȐȓȖȎȍȕȐȍǩǻșȚȈȕȖȊȒȈ3\WKRQ  

ǻȉȍȌȐȚȍșȤȟȚȖȐȔȧșȒȈȟȐȊȈȍȔȖȋȖȊȈȔȐȜȈȑȓȈȕȈȟȐȕȈȍȚșȧȕȈ$QDFRQGDǭșȓȐȖȕȖ
ȕȈȟȐȕȈȍȚșȧș$QDFRQGDȚȖȥȚȖȊȍȘșȐȧȌȓȧ3\WKRQ

Anaconda устанавливает содержимое в собственный каталог (он называется


ƒƒ ‘†ƒ и располагается в домашнем каталоге). Это значит, что он не будет мешать
другим версиям Python, установленным на ваш компьютер. Кроме того, вам не нуж-
но особое разрешение (иметь имя, такое как ƒ†‹ или root), чтобы его установить.
Сейчас Anaconda содержит более 1500 пакетов с открытым исходным кодом.
Посетите страницу документации установщика (KWWSVGRFVDQDFRQGDFRPDQDFRQGD
SDFNDJHVSNJGRFV) и нажмите ссылку для вашей платформы и версии Python.
После установки Anaconda 3 вы можете увидеть, что Санта положил в ваш ком-
пьютер, введя команду ‘†ƒ list.
Менеджер пакетов conda. Недавно разработчики Anaconda создали ‘†ƒ (KWWSV
GRFVFRQGDLR), чтобы решить проблемы, которые возникали с pip и другими инстру-
ментами. pip — это менеджер пакетов для Python, а ‘†ƒ работает с любыми языка-
ми программирования и ПО. Этому пакету также не нужно ничего типа virtualenv,
чтобы содержать отдельно разные пакеты.
Если вы уже установили дистрибутив Anaconda, то у вас уже есть програм-
ма ‘†ƒ. В противном случае можете установить Python 3 и ‘†ƒ со страницы
miniconda (KWWSVGRFVFRQGDLRHQODWHVWPLQLFRQGDKWPO). Как и в случае с Anaconda, убе-
дитесь, что файл, который вы скачиваете, начинается с Miniconda3, а не с Miniconda
(это версия для Python 2).
Пакет ‘†ƒ работает вместе с pip. Несмотря на то что он имеет собственный
публичный репозиторий пакетов (KWWSVDQDFRQGDRUJDQDFRQGDUHSR), такие команды,
как ‘†ƒ •‡ƒ” Š, также выполняют поиск в репозитории PyPi (KWWSS\SLS\WKRQRUJ).
Если у вас возникают проблемы с pip, то ‘†ƒ может стать хорошей альтерна-
тивой.
ƗƘƐƓƖƎƍƕƐƍƊ
ǵȍȟȚȖșȖȊȍȘȠȍȕȕȖȐȕȖȍDV\QF

Первые два приложения предназначались для начинающих программистов, а это


пригодится тем, кто уже несколько продвинулся в данной области.
Как и большинство других языков программирования, Python был синхронным.
Его код запускался последовательно по одной строке за раз, сверху вниз. Когда вы
вызываете функцию, Python перескакивает в ее код, и вызывающая сторона ждет,
пока функция не закончит выполняться, прежде чем возобновить то, что делалось
ранее.
Ваш ЦП может совершать только одну операцию за раз, поэтому синхронное вы-
полнение целесообразно. Но оказывается, зачастую программы не выполняют свой
код, а ждут чего-то наподобие получения данных из файла или отклика сетевого
сервиса. Процесс похож на то, как мы открываем окно браузера и ждем загрузки
сайта. Если бы в наших силах было избежать этого «активного ожидания», то мы
могли бы сократить общее время выполнения наших программ. Это также называ-
ется улучшением пропускной способности.
В главе 15 вы видели: при желании воспользоваться конкурентностью вам
следует использовать процессы, потоки или сторонние решения, такие как gevent
или –™‹•–‡†. Но сейчас появляется все больше асинхронных ответов, созданных на
основе Python и сторонних решений. Они сосуществуют вместе с синхронным ко-
дом Python, но, как предупреждали охотники за привидениями, вы не можете пере-
крещивать потоки. Я покажу, как можно избежать эктоплазматических сторонних
эффектов.

ǹȖȗȘȖȋȘȈȔȔȣȐȞȐȒȓȣșȖȉȣȚȐȑ
В версию Python 3.4 был добавлен асинхронный модуль ƒ•› ‹‘. Затем в версию
Python 3.5 были добавлены ключевые слова ƒ•› и await. Все это позволяет реа-
лизовать следующие новые концепции:
‰сопрограммы — это функции, которые приостанавливаются в разных точках;
‰цикл событий — цикл, в котором планируется запуск сопрограмм, а также они
выполняются.
ǷȘȐȓȖȎȍȕȐȍǪǵȍȟȚȖșȖȊȍȘȠȍȕȕȖȐȕȖȍDV\QF  

Это позволяет писать асинхронный код, выглядящий как обычный, синхронный,


к которому мы привыкли. В противном случае следует использовать один из мето-
дов, описанных в главах 15 и 17, они подытожены ниже, в разделе «async против…»
данного приложения.
Многозадачность — это то, что ваша операционная система делает с вашими про-
цессами. Она решает, какое действие справедливо, кто занимает процессор, когда
выполнять ввод/вывод данных и т. д. Цикл событий, однако, предоставляет воз-
можность кооперативной многозадачности, при которой сопрограммы указывают,
когда готовы стартовать и останавливаться. Они работают в одном потоке, поэтому
вы не столкнетесь с потенциальными проблемами, описанными в подразделе «По-
токи» на с. 311.
Сопрограмма определяется с помощью ключевого слова ƒ•› , которое помеща-
ется перед †‡ˆ. Она вызывается следующим образом:
‰путем размещения ключевого слова await перед ее именем в коде, что поместит
сопрограмму в существующий цикл обработки событий. Вы можете сделать это
только внутри другой сопрограммы;
‰можно также использовать конструкцию ƒ•› ‹‘Ŝ”—ſƀ, которая явно запускает
цикл обработки событий;
‰помимо этого, можно воспользоваться вызовами ƒ•› ‹‘Ŝ ”‡ƒ–‡ɏ–ƒ•ſƀ или
ƒ•› ‹‘Ŝ‡•—”‡ɏˆ—–—”‡ſƀ.

В этом примере показаны первые два метода вызова сопрограмм:


ʴʴʴ‹’‘”–ƒ•› ‹‘
ʴʴʴ
ʴʴʴƒ•› †‡ˆ™‹ ‡†ſƀś
ŜŜŜ’”‹–ſɑ—””‡†‡”řɑƀ
ŜŜŜƒ™ƒ‹–ƒ•› ‹‘Ŝ•އ‡’ſɩƀ
ŜŜŜ’”‹–ſɑ‘”‘–Š›Šɑƀ
ŜŜŜ
ʴʴʴƒ•› ‹‘Ŝ”—ſ™‹ ‡†ſƀƀ
—””‡†‡”ř
‘”‘–Š›Š

В процессе выполнения программы произошла драматичная пауза длиной


2 секунды, которую вы не можете увидеть на печатной странице. Докажу, что я не
жульничал (подробности работы модуля –‹‡‹– см. в главе 19):
ʴʴʴˆ”‘–‹‡‹–‹’‘”––‹‡‹–
ʴʴʴ–‹‡‹–ſɑƒ•› ‹‘Ŝ”—ſ™‹ ‡†ſƀƀɑř‰Ž‘„ƒŽ•ʰ‰Ž‘„ƒŽ•ſƀř—„‡”ʰɨƀ
—””‡†‡”ř
‘”‘–Š›Š
ɩŜɥɥɬɮɥɨɬɮɫɰɰɯɰɭɭ

Вызов ƒ•› ‹‘Ŝ•އ‡’ſɩƀ сам по себе — сопрограмма, которую мы использовали


в качестве примера некой времязатратной операции, такой как вызов API.
Строка ƒ•› ‹‘Ŝ”—ſ™‹ ‡†ſƀƀ — это способ запуска сопрограммы из синхрон-
ного кода Python (на верхнем уровне программы).
  ǷȘȐȓȖȎȍȕȐȧ

Отличие от стандартного синхронного вызова (с использованием –‹‡Ŝ•އ‡’ſƀ)


заключается в том, что вызывающая сторона метода ™‹ ‡†ſƀ не блокируется на
2 секунды, пока работает метод.
Третий способ запустить сопрограмму — создать задачу и использовать ключевое
слово await. Этот подход показан в следующем примере наряду с двумя предыду-
щими методами:
ʴʴʴ‹’‘”–ƒ•› ‹‘
ʴʴʴ
ʴʴʴƒ•› †‡ˆ•ƒ›ſ’Š”ƒ•‡ř•‡ ‘†•ƀś
ŜŜŜ’”‹–ſ’Š”ƒ•‡ƀ
ŜŜŜƒ™ƒ‹–ƒ•› ‹‘Ŝ•އ‡’ſ•‡ ‘†•ƀ
ŜŜŜ
ʴʴʴƒ•› †‡ˆ™‹ ‡†ſƀś
ŜŜŜ–ƒ•ɏɨʰƒ•› ‹‘Ŝ ”‡ƒ–‡ɏ–ƒ•ſ•ƒ›ſɑ—””‡†‡”řɑřɩƀƀ
ŜŜŜ–ƒ•ɏɩʰƒ•› ‹‘Ŝ ”‡ƒ–‡ɏ–ƒ•ſ•ƒ›ſɑ‘”‘–Š›Šɑřɥƀƀ
ŜŜŜƒ™ƒ‹––ƒ•ɏɨ
ŜŜŜƒ™ƒ‹––ƒ•ɏɩ
ŜŜŜ
ʴʴʴƒ•› ‹‘Ŝ”—ſ™‹ ‡†ſƀƀ
—””‡†‡”ř
‘”‘–Š›Š

Запустив данный код, вы увидите: между выводом на экран двух строк нет
задержки. Это произошло потому, что у нас есть две отдельные задачи. Первая —
–ƒ•ɏɨ — приостановилась на 2 секунды после вывода слова —””‡†‡”, но это не по-
влияло на вторую — –ƒ•ɏɩ.
Ключевое слово await аналогично ключевому слову ›‹‡Ž† в генераторах, но
вместо того, чтобы возвращать значение, оно помечает место, где цикл обработки
событий может приостановиться, если нужно.
В документации (KWWSVRUHLOO\&IBKG) содержится гораздо больше информации.
Синхронный и асинхронный код могут сосуществовать в одной программе. Главное —
помнить о необходимости указывать ключевое слово ƒ•› перед †‡ˆ при объявлении
функции и ключевое слово await перед вызовом асинхронной функции.
Для дополнительной информации см.:
‰список (KWWSVRUHLOO\9M\') ссылок на ПО, использующее ƒ•› ‹‘;
‰код (KWWSVRUHLOO\Q)9[) веб-сканера, применяющего ƒ•› ‹‘.
Альтернативы asyncio. Несмотря на то что модуль ƒ•› ‹‘ входит в стандарт-
ный пакет Python, вы можете использовать ключевые слова ƒ•› и await без него.
Сопрограммы и цикл обработки событий не зависят друг от друга. Дизайн модуля
ƒ•› ‹‘ иногда подвергается критике (KWWSVRUHLOO\Q)9[), и на этом фоне появились
сторонние альтернативы:
‰ —”‹‘ (KWWSVFXULRUHDGWKHGRFVLR);
‰trio (KWWSVWULRUHDGWKHGRFVLR).
Рассмотрим реальный пример, использующий trio и ƒ•• (KWWSVDVNVUHDGWKH
GRFVLR) (асинхронный веб-фреймворк, созданный на основе requests API). В при-
ǷȘȐȓȖȎȍȕȐȍǪǵȍȟȚȖșȖȊȍȘȠȍȕȕȖȐȕȖȍDV\QF  

мере В.1 показывается веб-сканер, который использует конкурентность с помощью


trio и ƒ••, он был создан на основе ответа на stackoverflow (KWWSVRUHLOO\&E,16).
Чтобы запустить этот пример, сначала установите trio и ƒ•• с помощью pip
install.

ǷȘȐȔȍȘǪWULRBDVNVBVLWHVS\
‹’‘”––‹‡

‹’‘”–ƒ••
‹’‘”––”‹‘

ƒ••Ŝ‹‹–ſɑ–”‹‘ɑƀ

—”Ž•ʰƃ
ɐŠ––’•śŵŵ„‘”‡†‘–Ї”ƒ’›Ŝ ‘ŵ„ƒ†Ş–ƒš‹†‡”›ŵɐř
ɐŠ––’śŵŵ™™™Ŝ„ƒ†–ƒš‹†‡”›Ŝ ‘ŵɐř
ɐŠ––’•śŵŵ ”ƒ’’›–ƒš‹†‡”›Ŝ ‘ŵɐř
ɐŠ––’•śŵŵ™™™Ŝ”ƒ‡”Ŝ ‘ŵŽ‹•–ŵ„ƒ†Ş–ƒš‹†‡”›Ş’‹ –—”‡•ŵƒ•ŠŽ‡›Ş”‡‹‰ɐř
Ƅ

ƒ•› †‡ˆ‰‡–ɏ‘‡ſ—”Žř–ɨƀś
”ʰƒ™ƒ‹–ƒ••Ŝ‰‡–ſ—”Žƀ
–ɩʰ–‹‡Ŝ–‹‡ſƀ
’”‹–ſˆɑƇſ–ɩŞ–ɨƀśŜɥɫƈɎ–Ƈއſ”Ŝ ‘–‡–ƀƈɎ–Ƈ—”Žƈɑƀ

ƒ•› †‡ˆ‰‡–ɏ•‹–‡•ſ•‹–‡•ƀś
–ɨʰ–‹‡Ŝ–‹‡ſƀ
ƒ•› ™‹–Š–”‹‘Ŝ‘’‡ɏ—”•‡”›ſƀƒ•—”•‡”›ś
ˆ‘”—”Ž‹•‹–‡•ś
—”•‡”›Ŝ•–ƒ”–ɏ•‘‘ſ‰‡–ɏ‘‡ř—”Žř–ɨƀ

‹ˆɏɏƒ‡ɏɏʰʰɑɏɏƒ‹ɏɏɑś
’”‹–ſɑ•‡ ‘†•Ɏ–„›–‡•Ɏ–—”Žɑƀ
–”‹‘Ŝ”—ſ‰‡–ɏ•‹–‡•ř—”Ž•ƀ

Вот что я получил:


ɛpython trio_asks_sites.py
•‡ ‘†•„›–‡•—”Ž
ɥŜɨɩɯɮɬɮɪɬŠ––’•śŵŵ„‘”‡†‘–Ї”ƒ’›Ŝ ‘ŵ„ƒ†Ş–ƒš‹†‡”›ŵ
ɥŜɩɨɪɫɨɫɭɥɯɩŠ––’•śŵŵ™™™Ŝ”ƒ‡”Ŝ ‘ŵŽ‹•–ŵ„ƒ†Ş–ƒš‹†‡”›Ş’‹ –—”‡•ŵƒ•ŠŽ‡›Ş”‡‹‰
ɥŜɩɨɬɨɨɥɩɰŠ––’śŵŵ™™™Ŝ„ƒ†–ƒš‹†‡”›Ŝ ‘ŵ
ɥŜɪɯɨɪɬɩɪɯɬŠ––’•śŵŵ ”ƒ’’›–ƒš‹†‡”›Ŝ ‘ŵ

Вы увидите, что trio вызывает не ƒ•› ‹‘Ŝ”—ſƀ, а собственный метод –”‹‘Ŝ‘’‡ɏ


—”•‡”›ſƀ. Если вам интересно, то можете прочесть эссе (KWWSVRUHLOO\\SU) и обсу-
ждение (KWWSVRUHLOO\35D) решений, связанных с дизайном trio.
Новый пакет, который называется AnyIO (KWWSVDQ\LRUHDGWKHGRFVLRHQODWHVW),
предоставляет единый интерфейс к ƒ•› ‹‘, —”‹‘ и trio.
В будущем можно ожидать появления новых асинхронных подходов как в стан-
дартном Python, так и в сторонних библиотеках.
  ǷȘȐȓȖȎȍȕȐȧ

DV\QFȗȘȖȚȐȊ«
Как вы уже видели на протяжении этой книги, реализовать конкурентность можно
с помощью множества приемов. Чем async отличается от них, а в чем похож?
‰Процессы. Это хорошее решение, если вы хотите использовать все ядра ЦП на
вашей машине или даже несколько машин. Однако процессы довольно тяжелые,
на их запуск требуется некоторое время, а для коммуникации между процессами
следует применить сериализацию.
‰Потоки. Несмотря на то что потоки разрабатывались как «легковесная» альтер-
натива процессам, каждый поток занимает большой объем памяти. Сопрограммы
гораздо легче, чем потоки; вы можете создать сотни тысяч сопрограмм на машине,
которая может поддерживать всего несколько тысяч потоков.
‰«Зеленые» потоки. Такие «зеленые» потоки, как gevent, работают хорошо и вы-
глядят очень похоже на синхронный код, но требуют выполнять «обезьяний
патч» стандартных функций Python, например библиотек сокетов.
‰Функции обратного вызова. Такие библиотеки, как –™‹•–‡†, полагаются на функ-
ции обратного вызова: они вызываются, когда происходит определенное событие.
Это знакомо программистам, работающим с GUI и JavaScript.
‰Очереди. Как правило, являются крупномасштабным решением, когда вашим
данным или процессам требуется больше одной машины.

ǨșȐȕȝȘȖȕȕȣȍȜȘȍȑȔȊȖȘȒȐȐșȍȘȊȍȘȣ
Асинхронность появилась в Python недавно, и разработчикам требуется время для
создания асинхронных версий таких фреймворков, как Flask.
Стандарт ASGI (KWWSVDVJLUHDGWKHGRFVLR) — это асинхронная версия WSGI, более
подробно обсуждается здесь: KWWSVRUHLOO\%Q(;7.
Ниже представлены некоторые веб-серверы, работающие по принципу ASGI:
‰Š›’‡” ‘” (KWWSVSJMRQHVJLWODELRK\SHUFRUQ);
‰•ƒ‹ (KWWSVVDQLFUHDGWKHGRFVLR);
‰—˜‹ ‘” (KWWSVZZZXYLFRUQRUJ).
А вот некоторые асинхронные веб-фреймворки:
‰aiohttp (KWWSVDLRKWWSUHDGWKHGRFVLR) — клиент и сервер;
‰ƒ’‹ɏŠ‘—” (KWWSVS\WKRQKRVWHGRUJDSLBKRXU);
‰ƒ•• (KWWSVDVNVUHDGWKHGRFVLR) — похож на requests;
‰„Žƒ •Ї‡’ (KWWSVJLWKXEFRP5REHUWR3UHYDWR%ODFN6KHHS);
‰„‘ ƒ†‹ŽŽ‘ (KWWSVJLWKXEFRPERFDGLOORSURMHFWERFDGLOOR);
‰ Šƒ‡Ž• (KWWSVFKDQQHOVUHDGWKHGRFVLR);
‰fastapi (KWWSVIDVWDSLWLDQJRORFRP) — использует аннотации типов;
ǷȘȐȓȖȎȍȕȐȍǪǵȍȟȚȖșȖȊȍȘȠȍȕȕȖȐȕȖȍDV\QF  

‰—ˆˆ‹ (KWWSVPXIILQUHDGWKHGRFVLR);
‰quart (KWWSVJLWODEFRPSJMRQHVTXDUW);
‰”‡•’‘†‡” (KWWSVS\WKRQUHVSRQGHURUJ);
‰•ƒ‹ (KWWSVVDQLFUHDGWKHGRFVLR);
‰starlette (KWWSVZZZVWDUOHWWHLR);
‰–‘”ƒ†‘ (KWWSVZZZWRUQDGRZHERUJ);
‰vibora (KWWSVYLERUDLR).
И наконец, несколько асинхронных интерфейсов к базам данных:
‰ƒ‹‘›•“Ž (KWWSVDLRP\VTOUHDGWKHGRFVLR);
‰ƒ‹‘”‡†‹• (KWWSVDLRUHGLVUHDGWKHGRFVLR);
‰ƒ•› ’‰ (KWWSVJLWKXEFRPPDJLFVWDFNDV\QFSJ).
ƗƘƐƓƖƎƍƕƐƍƋ
ǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ

3\WKRQșȟȍȔȍȋȖȍȌȧȚ
1.1. Если вы еще не установили Python 3, сделайте это сейчас. Прочтите приложе-
ние Б, чтобы узнать детали.
1.2. Запустите интерактивный интерпретатор Python 3. Детали опять же вы найдете
в приложении Б. Интерпретатор должен вывести несколько строк о себе, а за-
тем строку, начинающуюся с символов ʴʴʴ. Перед вами приглашение для ввода
команд Python.

Вот так это выглядит на моем Mac:


ɛ’›–Š‘
›–Š‘ɪŜɮŜɪſ˜ɪŜɮŜɪś‡ˆɫ‡ ɭ‡†ɨɩřƒ”ɩɬɩɥɨɰřɨɭśɪɰśɥɥƀ
ƃ ɫŜɩŜɨſ’’އ  Ŝ„—‹Ž†ɬɭɭɭƀſ†‘–ɪƀƄ‘†ƒ”™‹
›’‡ɑЇޒɑřɑ ‘’›”‹‰Š–ɑřɑ ”‡†‹–•ɑ‘”ɑŽ‹ ‡•‡ɑˆ‘”‘”‡‹ˆ‘”ƒ–‹‘Ŝ
ʴʴʴ

1.3. Немного поэкспериментируйте с интерпретатором. Используйте его как кальку-


лятор и наберите ɯ * 9. Нажмите клавишу (QWHU, чтобы увидеть результат. Python
должен вывести ɮɩ.

ʴʴʴɯƋɰ
ɮɩ

1.4. Теперь введите число ɫɮ и нажмите клавишу (QWHU. Появилось ли число ɫɮ в сле-
дующей строке?

ʴʴʴɫɮ
ɫɮ

1.5. Теперь введите ’”‹–ſɫɮƀ и нажмите клавишу (QWHU. Появилось ли снова чис-
ло ɫɮ в следующей строке?

ʴʴʴ’”‹–ſɫɮƀ
ɫɮ
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ǺȐȗȣȌȈȕȕȣȝȏȕȈȟȍȕȐȧ
ȗȍȘȍȔȍȕȕȣȍȐȐȔȍȕȈ
2.1. Присвойте целочисленное значение 99 переменной ’”‹ ‡ и выведите ее на
экран.

ʴʴʴ’”‹ ‡ʰɰɰ
ʴʴʴ’”‹–ſ’”‹ ‡ƀ
99
ʴʴʴ

2.2. Какого типа значение ɬ?

ʴʴʴ–›’‡ſɬƀ
ʳ Žƒ••ɐ‹–ɐʴ

2.3. Какого типа значение ɩŜɥ?

ʴʴʴ–›’‡ſɩŜɥƀ
ʳ Žƒ••ɐˆŽ‘ƒ–ɐʴ

2.4. Какого типа выражение ɬ ʫ ɩŜɥ?

ʴʴʴ–›’‡ſɬʫɩŜɥƀ
ʳ Žƒ••ɐˆŽ‘ƒ–ɐʴ

ǿȐșȓȈ
3.1. Сколько секунд в часе? Используйте интерактивный интерпретатор как кальку-
лятор и умножьте количество секунд в минуте (60) на количество минут в часе
(тоже 60).

ʴʴʴɭɥƋɭɥ
ɪɭɥɥ

3.2. Присвойте результат вычисления предыдущего задания (секунды в часе) пере-


менной, которая называется •‡ ‘†•ɏ’‡”ɏŠ‘—”.

ʴʴʴ•‡ ‘†•ɏ’‡”ɏŠ‘—”ʰɭɥƋɭɥ
ʴʴʴ•‡ ‘†•ɏ’‡”ɏŠ‘—”
ɪɭɥɥ
  ǷȘȐȓȖȎȍȕȐȧ

3.3. Сколько секунд в сутках? Используйте переменную •‡ ‘†•ɏ’‡”ɏŠ‘—”.

ʴʴʴ•‡ ‘†•ɏ’‡”ɏŠ‘—”Ƌɩɫ
ɯɭɫɥɥ

3.4. Снова посчитайте количество секунд в сутках, но на этот раз сохраните резуль-
тат в переменной •‡ ‘†•ɏ’‡”ɏ†ƒ›.

ʴʴʴ•‡ ‘†•ɏ’‡”ɏ†ƒ›ʰ•‡ ‘†•ɏ’‡”ɏŠ‘—”Ƌɩɫ


ʴʴʴ•‡ ‘†•ɏ’‡”ɏ†ƒ›
ɯɭɫɥɥ

3.5. Разделите значение переменной •‡ ‘†•ɏ’‡”ɏ†ƒ› на значение переменной


•‡ ‘†•ɏ’‡”ɏŠ‘—”, используя деление с плавающей точкой (ŵ).

ʴʴʴ•‡ ‘†•ɏ’‡”ɏ†ƒ›ŵ•‡ ‘†•ɏ’‡”ɏŠ‘—”


ɩɫŜɥ

3.6. Разделите значение переменной •‡ ‘†•ɏ’‡”ɏ†ƒ› на значение переменной


•‡ ‘†•ɏ’‡”ɏŠ‘—”, используя целочисленное деление (ŵŵ). Совпадает ли получен-
ный результат с ответом из предыдущего пункта без учета символов Ŝɥ в конце?

ʴʴʴ•‡ ‘†•ɏ’‡”ɏ†ƒ›ŵŵ•‡ ‘†•ɏ’‡”ɏŠ‘—”


ɩɫ

ǪȣȉȐȘȈȍȔșȗȖȔȖȡȤȦLI
4.1. Выберите число от 1 до 10 и присвойте его переменной •‡ ”‡–. Выберите еще
одно число от 1 до 10 и присвойте его переменной guess. Далее напишите услов-
ные проверки (if, else и elif), чтобы вывести строку ɐ–‘‘ Ž‘™ɐ, если значение
переменной guess меньше 7, ɐ–‘‘ Š‹‰Šɐ, если оно больше 7, и ɐŒ—•– ”‹‰Š–ɐ, если
равно •‡ ”‡–.

Выбрали ли вы для переменной •‡ ”‡– значение 7? Готов поспорить, так сделали мно-
гие, поскольку в числе 7 есть нечто волшебное.
•‡ ”‡–ʰɮ
‰—‡••ʰɬ
‹ˆ‰—‡••ʳ•‡ ”‡–ś
’”‹–ſɐ–‘‘Ž‘™ɐƀ
‡Ž‹ˆ‰—‡••ʴ•‡ ”‡–ś
’”‹–ſɐ–‘‘Š‹‰Šɐƀ
‡Ž•‡ś
’”‹–ſɐŒ—•–”‹‰Š–ɐƀ

Запустите эту программу, и вы увидите следующее:


–‘‘Ž‘™
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

4.2. Присвойте значения ”—‡ или ƒŽ•‡ переменным •ƒŽŽ и green. Напишите не-
сколько утверждений if/else, которые выведут на экран информацию о том,
соответствуют ли заданным условиям следующие растения: вишня, горошек,
арбуз, тыква.

ʴʴʴ•ƒŽŽʰ ƒŽ•‡
ʴʴʴ‰”‡‡ʰ”—‡
ʴʴʴ‹ˆ•ƒŽŽś
ŜŜŜ‹ˆ‰”‡‡ś
ŜŜŜ’”‹–ſɑ’‡ƒɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ Ї””›ɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ‹ˆ‰”‡‡ś
ŜŜŜ’”‹–ſɑ™ƒ–‡”‡Ž‘ɑƀ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ’—’‹ɑƀ
ŜŜŜ
ƒ–‡”‡Ž‘

ǺȍȒșȚȖȊȣȍșȚȘȖȒȐ
5.1. Напишите с заглавной буквы слово, которое начинается с буквы m:

ʴʴʴ•‘‰ʰɑɑɑЇƒ‡‡Ž‰”ƒ„•›‘—”ƒ”ř
ŜŜŜ†‹– ƒ—•‡•‰”‡ƒ–Šƒ”ř
ŜŜŜŠƒ–ɐ•ރ‘”ƒ›Šɑɑɑ

Не забудьте о пробеле, стоящем перед буквой :


ʴʴʴ•‘‰ʰɑɑɑЇƒ‡‡Ž‰”ƒ„•›‘—”ƒ”ř
ŜŜŜ†‹– ƒ—•‡•‰”‡ƒ–Šƒ”ř
ŜŜŜŠƒ–ɐ•ރ‘”ƒ›Šɑɑɑ
ʴʴʴ•‘‰ʰ•‘‰Ŝ”‡’Žƒ ‡ſɑɑřɑɑƀ
ʴʴʴ’”‹–ſ•‘‰ƀ
Їƒ‡‡Ž‰”ƒ„•›‘—”ƒ”ř
†‹– ƒ—•‡•‰”‡ƒ–Šƒ”ř
Šƒ–ɐ•ރ‘”ƒ›Š

5.2. Выведите на экран все вопросы из списка, а также правильные ответы в таком
виде:
Q: вопрос
A: ответ
ʴʴʴ“—‡•–‹‘•ʰƃ
ŜŜŜɑ‡†‘ɐ–•‡”˜‡•–”‹‰•ƒ”‘—†Ї”‡Ŝ”‡›‘—ƒ•–”‹‰ţɑř
ŜŜŜɑŠƒ–‹••ƒ‹†‘ ƒ–Ї”ɐ•ƒ›‹–Їˆ‘”‡•–ţɑř
ŜŜŜɑŠƒ–ƒ‡•–Ї•‘—†ɐ‹•Š‘‘ŠƒŠŠɐţɑ
ŜŜŜƄ
ʴʴʴƒ•™‡”•ʰƃ
  ǷȘȐȓȖȎȍȕȐȧ

ŜŜŜɑ‡š’Ž‘†‹‰•Ї‡’Ŝɑř
ŜŜŜɑ‘ř ɐƒˆ”ƒ›‡†‘–Ŝɑř
ŜŜŜɑɐ‘’Šɐ‰‘‡•–Ї™‡ƒ•‡ŽŜɑ
ŜŜŜƄ

Вы могли бы вывести на экран все вопросы и ответы множеством способов. Попробуем


использовать «бутерброд из кортежей» (конструкция, в которой в кортежах хранятся
кортежи) с целью их сгруппировать, а затем распакуем кортежи, чтобы получить значе-
ния для вывода на экран:
“—‡•–‹‘•ʰƃ
ɑ‡†‘ɐ–•‡”˜‡•–”‹‰•ƒ”‘—†Ї”‡Ŝ”‡›‘—ƒ•–”‹‰ţɑř
ɑŠƒ–‹••ƒ‹†‘ ƒ–Ї”ɐ•ƒ›‹–Їˆ‘”‡•–ţɑř
ɑŠƒ–ƒ‡•–Ї•‘—†ɐ‹•Š‘‘ŠƒŠŠɐţɑ
Ƅ
ƒ•™‡”•ʰƃ
ɑ‡š’Ž‘†‹‰•Ї‡’Ŝɑř
ɑ‘ř ɐƒˆ”ƒ›‡†‘–Ŝɑř
ɑɐ‘’Šɐ‰‘‡•–Ї™‡ƒ•‡ŽŜɑ
Ƅ

“ɏƒʰſſɥřɨƀřſɨřɩƀřſɩřɥƀƀ
ˆ‘”“řƒ‹“ɏƒś
’”‹–ſɑśɑř“—‡•–‹‘•ƃ“Ƅƀ
’”‹–ſɑśɑřƒ•™‡”•ƃƒƄƀ
’”‹–ſƀ

Результат:
ɛpython [Link]
ś‡†‘ɐ–•‡”˜‡•–”‹‰•ƒ”‘—†Ї”‡Ŝ”‡›‘—ƒ•–”‹‰ţ
ś‘ř ɐƒˆ”ƒ›‡†‘–Ŝ

śŠƒ–‹••ƒ‹†‘ ƒ–Ї”ɐ•ƒ›‹–Їˆ‘”‡•–ţ
śɐ‘’Šɐ‰‘‡•–Ї™‡ƒ•‡ŽŜ

śŠƒ–ƒ‡•–Ї•‘—†ɐ‹•Š‘‘ŠƒŠŠɐţ
ś‡š’Ž‘†‹‰•Ї‡’Ŝ

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


матирования. Подставьте в него такие строки: ɐ”‘ƒ•– „‡‡ˆɐ, ɐŠƒɐ, ɐЇƒ†ɐ,
и ɐ Žƒɐ:
›‹––› ƒ–Ž‹‡•ʩ•ř
›‹––› ƒ–Ž‹‡•ʩ•ř
›‹––› ƒ–ˆ‡ŽŽ‘Š‹•ʩ•
†‘™–Š‹•Їɐ•ƒʩ•Ŝ

ʴʴʴ’‘‡ʰɐɐɐ
ŜŜŜ›‹––› ƒ–Ž‹‡•ʩ•ř
ŜŜŜ›‹––› ƒ–Ž‹‡•ʩ•ř
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ŜŜŜ›‹––› ƒ–ˆ‡ŽŽ‘Š‹•ʩ•
ŜŜŜ†‘™–Š‹•Їɐ•ƒʩ•Ŝ
ŜŜŜɐɐɐ
ʴʴʴƒ”‰•ʰſɐ”‘ƒ•–„‡‡ˆɐřɐŠƒɐřɐЇƒ†ɐřɐ Žƒɐƀ
ʴʴʴ’”‹–ſ’‘‡ʩƒ”‰•ƀ

›‹––› ƒ–Ž‹‡•”‘ƒ•–„‡‡ˆř
›‹––› ƒ–Ž‹‡•Šƒř
›‹––› ƒ–ˆ‡ŽŽ‘Š‹•Їƒ†
†‘™–Š‹•Їɐ•ƒ ŽƒŜ

5.4. Напишите письмо с использованием нового стиля форматирования. Сохраните


предложенную строку в переменной letter (она понадобится вам в упражне-
нии ниже):
‡ƒ”Ƈ•ƒŽ—–ƒ–‹‘ƈƇƒ‡ƈř

Šƒ›‘—ˆ‘”›‘—”އ––‡”Ŝ‡ƒ”‡•‘””›–Šƒ–‘—”Ƈ’”‘†— –ƈ
Ƈ˜‡”„‡†ƈ‹›‘—”Ƈ”‘‘ƈŜއƒ•‡‘–‡–Šƒ–‹–•Š‘—ކ‡˜‡”
„‡—•‡†‹ƒƇ”‘‘ƈř‡•’‡ ‹ƒŽŽ›‡ƒ”ƒ›Ƈƒ‹ƒŽ•ƈŜ

‡†—•›‘—””‡ ‡‹’–ƒ†Ƈƒ‘—–ƈˆ‘”•Š‹’’‹‰ƒ†Šƒ†Ž‹‰Ŝ
‡™‹ŽŽ•‡†›‘—ƒ‘–Ї”Ƈ’”‘†— –ƈ–Šƒ–ř‹‘—”–‡•–•ř
‹•Ƈ’‡” ‡–ƈʩއ••Ž‹‡Ž›–‘Šƒ˜‡Ƈ˜‡”„‡†ƈŜ

Šƒ›‘—ˆ‘”›‘—”•—’’‘”–Ŝ

‹ ‡”‡Ž›ř
Ƈ•’‘‡•ƒƈ
ƇŒ‘„ɏ–‹–އƈ

ʴʴʴއ––‡”ʰɐɐɐ
ŜŜŜ‡ƒ”Ƈ•ƒŽ—–ƒ–‹‘ƈƇƒ‡ƈř
ŜŜŜ
ŜŜŜŠƒ›‘—ˆ‘”›‘—”އ––‡”Ŝ‡ƒ”‡•‘””›–Šƒ–‘—”Ƈ’”‘†— –ƈ
ŜŜŜƇ˜‡”„‡†ƈ‹›‘—”Ƈ”‘‘ƈŜއƒ•‡‘–‡–Šƒ–‹–•Š‘—ކ‡˜‡”
ŜŜŜ„‡—•‡†‹ƒƇ”‘‘ƈř‡•’‡ ‹ƒŽŽ›‡ƒ”ƒ›Ƈƒ‹ƒŽ•ƈŜ
ŜŜŜ
ŜŜŜ‡†—•›‘—””‡ ‡‹’–ƒ†Ƈƒ‘—–ƈˆ‘”•Š‹’’‹‰ƒ†Šƒ†Ž‹‰Ŝ
ŜŜŜ‡™‹ŽŽ•‡†›‘—ƒ‘–Ї”Ƈ’”‘†— –ƈ–Šƒ–ř‹‘—”–‡•–•ř
ŜŜŜ‹•Ƈ’‡” ‡–ƈʩއ••Ž‹‡Ž›–‘Šƒ˜‡Ƈ˜‡”„‡†ƈŜ
ŜŜŜ
ŜŜŜŠƒ›‘—ˆ‘”›‘—”•—’’‘”–Ŝ
ŜŜŜ
ŜŜŜ‹ ‡”‡Ž›ř
ŜŜŜƇ•’‘‡•ƒƈ
ŜŜŜƇŒ‘„ɏ–‹–އƈ
ŜŜŜɐɐɐ
  ǷȘȐȓȖȎȍȕȐȧ

5.5. Присвойте значения переменным ɐ•ƒŽ—–ƒ–‹‘ɐ, ɐƒ‡ɐ, ɐ’”‘†— –ɐ, ɐ˜‡”„‡†ɐ (глагол
в прошедшем времени), ɐ”‘‘ɐ, ɐƒ‹ƒŽ•ɐ, ɐ’‡” ‡–ɐ, ɐ•’‘‡•ƒɐ и ɐŒ‘„ɏ–‹–އɐ.
С помощью функции Ž‡––‡”Ŝˆ‘”ƒ–ſƀвыведите на экран значение переменной
letter, в которую подставлены эти значения.

ʴʴʴ’”‹–ſ
ŜŜŜއ––‡”Ŝˆ‘”ƒ–ſ•ƒŽ—–ƒ–‹‘ʰɐ„ƒ••ƒ†‘”ɐř
ŜŜŜƒ‡ʰɐ‹„„އ”ɐř
ŜŜŜ’”‘†— –ʰɐ’—††‹‰ɐř
ŜŜŜ˜‡”„‡†ʰɐ‡˜ƒ’‘”ƒ–‡†ɐř
ŜŜŜ”‘‘ʰɐ‰ƒœ‡„‘ɐř
ŜŜŜƒ‹ƒŽ•ʰɐ‘ –‘–Š‘”’‡•ɐř
ŜŜŜƒ‘—–ʰɐɛɨŜɰɰɐř
ŜŜŜ’‡” ‡–ʰɯɯř
ŜŜŜ•’‘‡•ƒʰɐŠ‹”އ› —‰‡•–‡ɐř
ŜŜŜŒ‘„ɏ–‹–އʰɐ  ƒ–‡Š‹• ‘„ɐƀ
ŜŜŜƀ

‡ƒ”„ƒ••ƒ†‘”‹„„އ”ř

Šƒ›‘—ˆ‘”›‘—”އ––‡”Ŝ‡ƒ”‡•‘””›–Šƒ–‘—”’—††‹‰
‡˜ƒ’‘”ƒ–‡†‹›‘—”‰ƒœ‡„‘Ŝއƒ•‡‘–‡–Šƒ–‹–•Š‘—ކ‡˜‡”
„‡—•‡†‹ƒ‰ƒœ‡„‘ř‡•’‡ ‹ƒŽŽ›‡ƒ”ƒ›‘ –‘–Š‘”’‡•Ŝ

‡†—•›‘—””‡ ‡‹’–ƒ†ɛɨŜɰɰˆ‘”•Š‹’’‹‰ƒ†Šƒ†Ž‹‰Ŝ
‡™‹ŽŽ•‡†›‘—ƒ‘–Ї”’—††‹‰–Šƒ–ř‹‘—”–‡•–•ř
‹•ɯɯʩއ••Ž‹‡Ž›–‘Šƒ˜‡‡˜ƒ’‘”ƒ–‡†Ŝ

Šƒ›‘—ˆ‘”›‘—”•—’’‘”–Ŝ

‹ ‡”‡Ž›ř
Š‹”އ› —‰‡•–‡
 ƒ–‡Š‹• ‘„

5.6. После проведения публичных опросов с целью выбора имени появились: ан-
глийская подводная лодка Boaty McBoatface, австралийская беговая лошадь
Horsey McHorseface и шведский поезд Trainy McTrainface. Используйте фор-
матирование с символом ʩ для того, чтобы вывести на экран победившие имена
для утки, тыквы и шпица (пример Д.1).

ǷȘȐȔȍȘǬPFQDPHVS\
ƒ‡•ʰƃɑ†— ɑřɑ‰‘—”†ɑřɑ•’‹–œɑƄ
ˆ‘”ƒ‡‹ƒ‡•ś
 ƒ’ɏƒ‡ʰƒ‡Ŝ ƒ’‹–ƒŽ‹œ‡ſƀ
’”‹–ſɑʩ•› ʩ•ˆƒ ‡ɑʩſ ƒ’ɏƒ‡ř ƒ’ɏƒ‡ƀƀ

—–’—–ś

— › — ˆƒ ‡


 ‘—”†› ‘—”†ˆƒ ‡
’‹–œ› ’‹–œˆƒ ‡
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

5.7. Сделайте то же самое с помощью функции ˆ‘”ƒ–ſƀ (пример Д.2).

ǷȘȐȔȍȘǬPFQDPHVS\
ƒ‡•ʰƃɑ†— ɑřɑ‰‘—”†ɑřɑ•’‹–œɑƄ
ˆ‘”ƒ‡‹ƒ‡•ś
 ƒ’ɏƒ‡ʰƒ‡Ŝ ƒ’‹–ƒŽ‹œ‡ſƀ
’”‹–ſɑƇƈ› Ƈƈˆƒ ‡ɑŜˆ‘”ƒ–ſ ƒ’ɏƒ‡ř ƒ’ɏƒ‡ƀƀ

5.8. А теперь еще раз с использованием f-строк (пример Д.3).

ǷȘȐȔȍȘǬPFQDPHVS\
ƒ‡•ʰƃɑ†— ɑřɑ‰‘—”†ɑřɑ•’‹–œɑƄ
ˆ‘”ƒ‡‹ƒ‡•ś
 ƒ’ɏƒ‡ʰƒ‡Ŝ ƒ’‹–ƒŽ‹œ‡ſƀ
’”‹–ſˆɑƇ ƒ’ɏƒ‡ƈ› Ƈ ƒ’ɏƒ‡ƈˆƒ ‡ɑƀ

ǹȖȏȌȈȍȔȞȐȒȓȣșȗȖȔȖȡȤȦȒȓȦȟȍȊȣȝ
șȓȖȊZKLOHȐIRU
6.1. Используйте цикл for, чтобы вывести на экран значения списка ƃɪř ɩř ɨř ɥƄ.

ʴʴʴˆ‘”˜ƒŽ—‡‹ƃɪřɩřɨřɥƄś
ŜŜŜ’”‹–ſ˜ƒŽ—‡ƀ
ŜŜŜ
ɪ
ɩ
ɨ
ɥ

6.2. Присвойте значение 7 переменной ‰—‡••ɏ‡ и значение ɨ переменной —„‡”. На-


пишите цикл while, который сравнивает переменные —„‡” и ‰—‡••ɏ‡. Выведите
строку ɐ–‘‘ Ž‘™ɐ, если значение переменной —„‡” меньше значения переменной
‰—‡••ɏ‡. Если значение переменной —„‡” равно значению переменной ‰—‡••ɏ‡,
выведите строку ɐˆ‘—† ‹–Šɐ и выйдите из цикла. Если значение переменной
—„‡” больше значения переменной ‰—‡••ɏ‡, выведите строку ɐ‘‘’•ɐ и выйдите
из цикла. Увеличьте значение переменной —„‡” на выходе из цикла.

‰—‡••ɏ‡ʰɮ
—„‡”ʰɨ
™Š‹Ž‡”—‡ś
‹ˆ—„‡”ʳ‰—‡••ɏ‡ś
’”‹–ſɐ–‘‘Ž‘™ɐƀ
‡Ž‹ˆ—„‡”ʰʰ‰—‡••ɏ‡ś
’”‹–ſɐˆ‘—†‹–Šɐƀ
„”‡ƒ
‡Ž‹ˆ—„‡”ʴ‰—‡••ɏ‡ś
’”‹–ſɐ‘‘’•ɐƀ
„”‡ƒ
—„‡”ʫʰɨ
  ǷȘȐȓȖȎȍȕȐȧ

Если вы сделали все правильно, то увидите следующие строки.

–‘‘Ž‘™
–‘‘Ž‘™
–‘‘Ž‘™
–‘‘Ž‘™
–‘‘Ž‘™
–‘‘Ž‘™
ˆ‘—†‹–Š

Обратите внимание: строка elif —„‡” ʴ ‰—‡••ɏ‡ś могла содержать обычный оператор
‡Ž•‡ś в связи с тем, что если значение —„‡” не меньше и не равно значению ‰—‡••ɏ‡,
то оно должно быть больше. По крайней мере в этой Вселенной.

6.3. Присвойте значение ɬ переменной ‰—‡••ɏ‡ . Используйте цикл for , чтобы


проитерировать с помощью переменной —„‡” по диапазону ”ƒ‰‡ſɨɥƀ. Если
значение переменной —„‡” меньше, чем значение ‰—‡••ɏ‡, выведите на экран
сообщение ɐ–‘‘ Ž‘™ɐ. Если оно равно значению ‰—‡••ɏ‡ — выведите сообщение
ˆ‘—† ‹–Š, а затем выйдите из цикла. Если значение переменной —„‡” больше,
чем ‰—‡••ɏ‡, выведите на экран сообщение ɐ‘‘’•ɐ и выйдите из цикла.

ʴʴʴ‰—‡••ɏ‡ʰɬ
ʴʴʴˆ‘”—„‡”‹”ƒ‰‡ſɨɥƀś
ŜŜŜ‹ˆ—„‡”ʳ‰—‡••ɏ‡ś
ŜŜŜ’”‹–ſɑ–‘‘Ž‘™ɑƀ
ŜŜŜ‡Ž‹ˆ—„‡”ʰʰ‰—‡••ɏ‡ś
ŜŜŜ’”‹–ſɑˆ‘—†‹–Šɑƀ
ŜŜŜ„”‡ƒ
ŜŜŜ‡Ž•‡ś
ŜŜŜ’”‹–ſɑ‘‘’•ɑƀ
ŜŜŜ„”‡ƒ
ŜŜŜ
–‘‘Ž‘™
–‘‘Ž‘™
–‘‘Ž‘™
–‘‘Ž‘™
–‘‘Ž‘™
ˆ‘—†‹–Š

DzȖȘȚȍȎȐȐșȗȐșȒȐ
7.1. Создайте список ›‡ƒ”•ɏŽ‹•–, содержащий год, в который вы родились, и каждый
последующий год вплоть до вашего пятого дня рождения. Например, если вы
родились в 1980 году, то список будет выглядеть так: ›‡ƒ”•ɏŽ‹•– ʰ ƃɨɰɯɥř ɨɰɯɨř
ɨɰɯɩř ɨɰɯɪř ɨɰɯɫř ɨɰɯɬƄ.

Если вы родились в 1980-м, то вам нужно ввести следующее:


ʴʴʴ›‡ƒ”•ɏŽ‹•–ʰƃɨɰɯɥřɨɰɯɨřɨɰɯɩřɨɰɯɪřɨɰɯɫřɨɰɯɬƄ
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

7.2. В какой год из списка ›‡ƒ”•ɏŽ‹•– был ваш третий день рождения? Учтите,
в первый год вам было 0 лет.

Вам нужно смещение ɪ. Поэтому, если вы родились в 1980-м:


ʴʴʴ›‡ƒ”•ɏŽ‹•–ƃɪƄ
ɨɰɯɪ

7.3. В какой год из списка ›‡ƒ”•ɏŽ‹•– вам было больше всего лет?

Вам нужно получить последний год, поэтому используйте смещение Şɨ. Вы также може-
те использовать смещение ɬ, поскольку знаете, что в этом списке всего шесть элементов.
Однако смещение Şɨ позволяет получить последний элемент из списка любой длины.
Для тех, кто родился в 1980 году:
ʴʴʴ›‡ƒ”•ɏŽ‹•–ƃŞɨƄ
ɨɰɯɬ

7.4. Создайте список things, содержащий три элемента: ɑ‘œœƒ”‡ŽŽƒɑ, ɑ ‹†‡”‡ŽŽƒɑ,


ɑ•ƒŽ‘‡ŽŽƒɑ.

ʴʴʴ–Š‹‰•ʰƃɑ‘œœƒ”‡ŽŽƒɑřɑ ‹†‡”‡ŽŽƒɑřɑ•ƒŽ‘‡ŽŽƒɑƄ
ʴʴʴ–Š‹‰•
ƃɐ‘œœƒ”‡ŽŽƒɐřɐ ‹†‡”‡ŽŽƒɐřɐ•ƒŽ‘‡ŽŽƒɐƄ

7.5. Напишите с большой буквы тот элемент списка things, который означает чело-
века, а затем выведите список. Изменился ли элемент списка?

Эта строка записывает слово с прописной буквы, но не меняет его в списке:


ʴʴʴ–Š‹‰•ƃɨƄŜ ƒ’‹–ƒŽ‹œ‡ſƀ
ɐ‹†‡”‡ŽŽƒɐ
ʴʴʴ–Š‹‰•
ƃɐ‘œœƒ”‡ŽŽƒɐřɐ ‹†‡”‡ŽŽƒɐřɐ•ƒŽ‘‡ŽŽƒɐƄ

Если вы хотите изменить его в списке, вам нужно присвоить его снова:
ʴʴʴ–Š‹‰•ƃɨƄʰ–Š‹‰•ƃɨƄŜ ƒ’‹–ƒŽ‹œ‡ſƀ
ʴʴʴ–Š‹‰•
ƃɐ‘œœƒ”‡ŽŽƒɐřɐ‹†‡”‡ŽŽƒɐřɐ•ƒŽ‘‡ŽŽƒɐƄ

7.6. Переведите сырный элемент списка things в верхний регистр целиком и вы-
ведите список.

ʴʴʴ–Š‹‰•ƃɥƄʰ–Š‹‰•ƃɥƄŜ—’’‡”ſƀ
ʴʴʴ–Š‹‰•
ƃɐɐřɐ‹†‡”‡ŽŽƒɐřɐ•ƒŽ‘‡ŽŽƒɐƄ
  ǷȘȐȓȖȎȍȕȐȧ

7.7. Удалите из списка things заболевание, получите Нобелевскую премию и затем


выведите список на экран.

Это удалит элемент по значению:


ʴʴʴ–Š‹‰•Ŝ”‡‘˜‡ſɑ•ƒŽ‘‡ŽŽƒɑƀ
ʴʴʴ–Š‹‰•
ƃɐɐřɐ‹†‡”‡ŽŽƒɐƄ

Поскольку элемент находится на последнем месте в списке, следующая строка тоже


сработает:
ʴʴʴ†‡Ž–Š‹‰•ƃŞɨƄ

Элемент также можно удалить, указав смещение от начала:


ʴʴʴ†‡Ž–Š‹‰•ƃɩƄ

7.8. Создайте список с элементами ɑ ”‘— Š‘ɑ , ɑŠ‹ ‘ɑ и ɑ ƒ”’‘ɑ ; назовите его
surprise.

ʴʴʴ•—”’”‹•‡ʰƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ


ʴʴʴ•—”’”‹•‡
ƃɐ ”‘— Š‘ɐřɐŠ‹ ‘ɐřɐ ƒ”’‘ɐƄ

7.9. Напишите последний элемент списка surprise со строчной буквы, затем вы-
ведите эту строку в обратном порядке и с прописной буквы.

ʴʴʴ•—”’”‹•‡ƃŞɨƄʰ•—”’”‹•‡ƃŞɨƄŜŽ‘™‡”ſƀ
ʴʴʴ•—”’”‹•‡ƃŞɨƄʰ•—”’”‹•‡ƃŞɨƄƃśśŞɨƄ
ʴʴʴ•—”’”‹•‡ƃŞɨƄŜ ƒ’‹–ƒŽ‹œ‡ſƀ
ɐ’”ƒŠɐ

7.10. Используйте списковое включение, чтобы создать список с именем even, в ко-
тором будут содержаться четные числа в промежутке ”ƒ‰‡ſɨɥƀ.

ʴʴʴ‡˜‡ʰƃ—„‡”ˆ‘”—„‡”‹”ƒ‰‡ſɨɥƀ‹ˆ—„‡”ʩɩʰʰɥƄ
ʴʴʴ‡˜‡
ƃɥřɩřɫřɭřɯƄ

7.11. Попробуйте создать генератор рифм для прыжков через скакалку. Нужно вы-
вести на экран последовательность двухстрочных рифм. Начните программу
с этого фрагмента:
•–ƒ”–ɨʰƃɑˆ‡‡ɑřɑˆ‹‡ɑřɑˆ‘‡ɑƄ
”Š›‡•ʰƃ
ſɑˆŽ‘’ɑřɑ‰‡–ƒ‘’ɑƀř
ſɑˆ‘’‡ɑřɑ–—”–Ї”‘’‡ɑƀř
ſɑˆƒɑřɑ‰‡–›‘—”ƒɑƀř
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ſɑˆ—†‰‡ɑřɑ ƒŽŽ–ЇŒ—†‰‡ɑƀř
ſɑˆƒ–ɑřɑ’‡––Ї ƒ–ɑƀř
ſɑˆ‘‰ɑřɑ™ƒŽ–Ї†‘‰ɑƀř
ſɑˆ—ɑřɑ•ƒ›™‡ɐ”‡†‘‡ɑƀř
Ƅ
•–ƒ”–ɩʰɑ‘‡‘‡„‡––‡”ɑ

Затем следуйте инструкциям.


Для каждого кортежа ſˆ‹”•–ř •‡ ‘†ƀ в списке ”Š›‡•:
‰для первой строки:
y выведите на экран каждую строку списка •–ƒ”–ɨ, записав их с большой
буквы, за которыми следует восклицательный знак и пробел;
y выведите на экран значение переменной first, также записав его с боль-
шой буквы, за которым следует восклицательный знак;
‰для второй строки:
y выведите на экран значение переменной •–ƒ”–ɩ и пробел;
y выведите на экран значение переменной •‡ ‘† и точку.

•–ƒ”–ɨʰƃɑˆ‡‡ɑřɑˆ‹‡ɑřɑˆ‘‡ɑƄ
”Š›‡•ʰƃ
ſɑˆŽ‘’ɑřɑ‰‡–ƒ‘’ɑƀř
ſɑˆ‘’‡ɑřɑ–—”–Ї”‘’‡ɑƀř
ſɑˆƒɑřɑ‰‡–›‘—”ƒɑƀř
ſɑˆ—†‰‡ɑřɑ ƒŽŽ–ЇŒ—†‰‡ɑƀř
ſɑˆƒ–ɑřɑ’‡––Ї ƒ–ɑƀř
ſɑˆ‘‰ɑřɑ’‡––Ї†‘‰ɑƀř
ſɑˆ—ɑřɑ•ƒ›™‡ɐ”‡†‘‡ɑƀř
Ƅ
•–ƒ”–ɩʰɑ‘‡‘‡„‡––‡”ɑ
•–ƒ”–ɨɏ ƒ’•ʰɑɑŜŒ‘‹ſƃ™‘”†Ŝ ƒ’‹–ƒŽ‹œ‡ſƀʫɑŠɑˆ‘”™‘”†‹•–ƒ”–ɨƄƀ
ˆ‘”ˆ‹”•–ř•‡ ‘†‹”Š›‡•ś
’”‹–ſˆɑƇ•–ƒ”–ɨɏ ƒ’•ƈƇˆ‹”•–Ŝ ƒ’‹–ƒŽ‹œ‡ſƀƈŠɑƀ
’”‹–ſˆɑƇ•–ƒ”–ɩƈƇ•‡ ‘†ƈŜɑƀ

Результат:
‡‡Š ‹‡Š ‘‡Š Ž‘’Š
‘‡‘‡„‡––‡”‰‡–ƒ‘’Ŝ
‡‡Š ‹‡Š ‘‡Š ‘’‡Š
‘‡‘‡„‡––‡”–—”–Ї”‘’‡Ŝ
‡‡Š ‹‡Š ‘‡Š ƒŠ
‘‡‘‡„‡––‡”‰‡–›‘—”ƒŜ
‡‡Š ‹‡Š ‘‡Š —†‰‡Š
‘‡‘‡„‡––‡” ƒŽŽ–ЇŒ—†‰‡Ŝ
‡‡Š ‹‡Š ‘‡Š ƒ–Š
‘‡‘‡„‡––‡”’‡––Ї ƒ–Ŝ
‡‡Š ‹‡Š ‘‡Š ‘‰Š
‘‡‘‡„‡––‡”™ƒŽ–Ї†‘‰Ŝ
‡‡Š ‹‡Š ‘‡Š —Š
‘‡‘‡„‡––‡”•ƒ›™‡ɐ”‡†‘‡Ŝ
  ǷȘȐȓȖȎȍȕȐȧ

ǹȓȖȊȈȘȐȐȔȕȖȎȍșȚȊȈ
8.1. Создайте англо-французский словарь с названием ‡ɩˆ и выведите его на экран.
Вот ваши первые слова: †‘‰ŵ Š‹‡, ƒ–ŵ Šƒ– и ™ƒŽ”—•ŵ‘”•‡.

ʴʴʴ‡ɩˆʰƇɐ†‘‰ɐśɐ Š‹‡ɐřɐ ƒ–ɐśɐ Šƒ–ɐřɐ™ƒŽ”—•ɐśɐ‘”•‡ɐƈ


ʴʴʴ‡ɩˆ
Ƈɐ ƒ–ɐśɐ Šƒ–ɐřɐ™ƒŽ”—•ɐśɐ‘”•‡ɐřɐ†‘‰ɐśɐ Š‹‡ɐƈ

8.2. Используя словарь ‡ɩˆ, выведите французский вариант слова walrus.

ʴʴʴ‡ɩˆƃɐ™ƒŽ”—•ɐƄ
ɐ‘”•‡ɐ

8.3. Создайте французско-английский словарь ˆɩ‡ на основе словаря ‡ɩˆ. Используй-


те метод ‹–‡•.

ʴʴʴˆɩ‡ʰƇƈ
ʴʴʴˆ‘”‡‰Ž‹•Šřˆ”‡ Š‹‡ɩˆŜ‹–‡•ſƀś
ˆɩ‡ƃˆ”‡ ŠƄʰ‡‰Ž‹•Š
ʴʴʴˆɩ‡
Ƈɐ‘”•‡ɐśɐ™ƒŽ”—•ɐřɐ Š‹‡ɐśɐ†‘‰ɐřɐ Šƒ–ɐśɐ ƒ–ɐƈ

8.4. Используя словарь ˆɩ‡, выведите английский вариант слова Š‹‡.

ʴʴʴˆɩ‡ƃɐ Š‹‡ɐƄ
ɐ†‘‰ɐ

8.5. Выведите на экран множество английских слов из ключей словаря ‡ɩˆ.

ʴʴʴ•‡–ſ‡ɩˆŜ‡›•ſƀƀ
Ƈɐ ƒ–ɐřɐ™ƒŽ”—•ɐřɐ†‘‰ɐƈ

8.6. Создайте многоуровневый словарь life. Используйте следующие строки для


ключей верхнего уровня: ɐƒ‹ƒŽ•ɐ, ɐ’Žƒ–•ɐ и ɐ‘–Ї”ɐ. Сделайте так, чтобы ключ
ɐƒ‹ƒŽ•ɐ ссылался на другой словарь, имеющий ключи ɐ ƒ–•ɐ, ɐ‘ –‘’‹ɐ и ɐ‡—•ɐ.
Сделайте так, чтобы ключ ɐ ƒ–•ɐ ссылался на список строк со значениями ɐ ‡”‹ɐ,
ɐ ”—’›ɐ и ɐ— ›ɐ. Остальные ключи должны ссылаться на пустые словари.

Это довольно трудный пример, так что если вы заглянули сюда, то ничего особо страш-
ного не случилось:
ʴʴʴŽ‹ˆ‡ʰƇ
ŜŜŜɐƒ‹ƒŽ•ɐśƇ
ŜŜŜɐ ƒ–•ɐśƃ
ŜŜŜɐ ‡”‹ɐřɐ ”—’›ɐřɐ— ›ɐ
ŜŜŜƄř
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ŜŜŜɐ‘ –‘’‹ɐśƇƈř
ŜŜŜɐ‡—•ɐśƇƈ
ŜŜŜƈř
ŜŜŜɐ’Žƒ–•ɐśƇƈř
ŜŜŜɐ‘–Ї”ɐśƇƈ
ŜŜŜƈ
ʴʴʴ

8.7. Выведите на экран высокоуровневые ключи словаря life.

ʴʴʴ’”‹–ſŽ‹ˆ‡Ŝ‡›•ſƀƀ
†‹ –ɏ‡›•ſƃɐƒ‹ƒŽ•ɐřɐ‘–Ї”ɐřɐ’Žƒ–•ɐƄƀ

Python 3 содержит функционал для работы с ключами словарей. Чтобы вывести их как
список, используйте следующую строку:
ʴʴʴ’”‹–ſŽ‹•–ſŽ‹ˆ‡Ŝ‡›•ſƀƀƀ
ƃɐƒ‹ƒŽ•ɐřɐ‘–Ї”ɐřɐ’Žƒ–•ɐƄ

Вы можете использовать пробелы, чтобы сделать ваш код более читабельным:


ʴʴʴ’”‹–ſŽ‹•–ſŽ‹ˆ‡Ŝ‡›•ſƀƀƀ
ƃɐƒ‹ƒŽ•ɐřɐ‘–Ї”ɐřɐ’Žƒ–•ɐƄ

8.8. Выведите на экран ключи Ž‹ˆ‡ƃɐƒ‹ƒŽ•ɐƄ.

ʴʴʴ’”‹–ſŽ‹ˆ‡ƃɐƒ‹ƒŽ•ɐƄŜ‡›•ſƀƀ
†‹ –ɏ‡›•ſƃɐ ƒ–•ɐřɐ‘ –‘’‹ɐřɐ‡—•ɐƄƀ

8.9. Выведите значения Ž‹ˆ‡ƃɐƒ‹ƒŽ•ɐƄƃɐ ƒ–•ɐƄ.

ʴʴʴ’”‹–ſŽ‹ˆ‡ƃɐƒ‹ƒŽ•ɐƄƃɐ ƒ–•ɐƄƀ
ƃɐ ‡”‹ɐřɐ ”—’›ɐřɐ— ›ɐƄ

8.10. Используйте генератор словаря, чтобы создать словарь squares. Используйте


”ƒ‰‡ſɨɥƀ, чтобы получить ключи. В качестве значений используйте возведен-
ное в квадрат значение каждого ключа.

ʴʴʴ•“—ƒ”‡•ʰƇ‡›ś‡›Ƌ‡›ˆ‘”‡›‹”ƒ‰‡ſɨɥƀƈ
ʴʴʴ•“—ƒ”‡•
Ƈɥśɥřɨśɨřɩśɫřɪśɰřɫśɨɭřɬśɩɬřɭśɪɭřɮśɫɰřɯśɭɫřɰśɯɨƈ

8.11. Используйте генератор множества, чтобы создать множество ‘†† из нечетных


чисел диапазона ”ƒ‰‡ſɨɥƀ.

ʴʴʴ‘††ʰƇ—„‡”ˆ‘”—„‡”‹”ƒ‰‡ſɨɥƀ‹ˆ—„‡”ʩɩʰʰɨƈ
ʴʴʴ‘††
Ƈɨřɪřɬřɮřɰƈ
  ǷȘȐȓȖȎȍȕȐȧ

8.12. Используйте включение генератора, чтобы вернуть строку ɐ ‘–ɐ и числа из


диапазона ”ƒ‰‡ſɨɥƀ. Итерируйте по этой конструкции с помощью цикла for.

ʴʴʴˆ‘”–Š‹‰‹ſɐ ‘–ʩ•ɐʩ—„‡”ˆ‘”—„‡”‹”ƒ‰‡ſɨɥƀƀś
ŜŜŜ’”‹–ſ–Š‹‰ƀ
ŜŜŜ
‘–ɥ
‘–ɨ
‘–ɩ
‘–ɪ
‘–ɫ
‘–ɬ
‘–ɭ
‘–ɮ
‘–ɯ
‘–ɰ

8.13. Используйте функцию œ‹’ſƀ , чтобы создать словарь из кортежа ключей


(ɐ‘’–‹‹•–ɐ, ɐ’‡••‹‹•–ɐ, ɐ–”‘ŽŽɐ) и кортежа значений (ɐЇ glass is half ˆ—ŽŽɐ,
ɐЇ glass is half ‡’–›ɐ, ɐ ‘™ †‹† you get a ‰Žƒ••ţ’).

ʴʴʴ‡›•ʰſɐ‘’–‹‹•–ɐřɐ’‡••‹‹•–ɐřɐ–”‘ŽŽɐƀ
ʴʴʴ˜ƒŽ—‡•ʰſɐЇ‰Žƒ••‹•ŠƒŽˆˆ—ŽŽɐř
ŜŜŜɐЇ‰Žƒ••‹•ŠƒŽˆ‡’–›ɐř
ŜŜŜɐ ‘™†‹†›‘—‰‡–ƒ‰Žƒ••ţɐƀ
ʴʴʴ†‹ –ſœ‹’ſ‡›•ř˜ƒŽ—‡•ƀƀ
Ƈɐ‘’–‹‹•–ɐśɐЇ‰Žƒ••‹•ŠƒŽˆˆ—ŽŽɐř
ɐ’‡••‹‹•–ɐśɐЇ‰Žƒ••‹•ŠƒŽˆ‡’–›ɐř
ɐ–”‘ŽŽɐśɐ ‘™†‹†›‘—‰‡–ƒ‰Žƒ••ţɐƈ

8.14. Используйте функцию œ‹’ſƀ, чтобы создать словарь с именем ‘˜‹‡•, в котором
объединены списки titles ʰ ƃɐ”‡ƒ–—”‡ of ƒ„‹–ɐř ɐ”‡™‡Ž ƒ–‡ɐř ɐŠƒ”•  a
Žƒ‡ɐƄ и plots ʰ ƃɐ nun turns into a ‘•–‡”ɐř ɐ Šƒ—–‡† yarn •Š‘’ɐř ɐЇ 
your ‡š‹–•ɐƄ.

ʴʴʴ–‹–އ•ʰƃɐ”‡ƒ–—”‡‘ˆ ƒ„‹–ɐř
ŜŜŜɐ”‡™‡Ž ƒ–‡ɐř
ŜŜŜɐŠƒ”•ƒŽƒ‡ɐƄ
ʴʴʴ’Ž‘–•ʰƃɐ—–—”•‹–‘ƒ‘•–‡”ɐř
ŜŜŜɐŠƒ—–‡†›ƒ”•Š‘’ɐř
ŜŜŜɐЇ ›‘—”‡š‹–•ɐƄ
ʴʴʴ‘˜‹‡•ʰ†‹ –ſœ‹’ſ–‹–އ•ř’Ž‘–•ƀƀ
ʴʴʴ‘˜‹‡•
Ƈɐ”‡ƒ–—”‡‘ˆ ƒ„‹–ɐśɐ—–—”•‹–‘ƒ‘•–‡”ɐř
ɐ”‡™‡Ž ƒ–‡ɐśɐŠƒ—–‡†›ƒ”•Š‘’ɐř
ɐŠƒ”•ƒŽƒ‡ɐśɐЇ ›‘—”‡š‹–•ɐƈ
ʴʴʴ
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ǼțȕȒȞȐȐ
9.1. Определите функцию ‰‘‘†, которая возвращает следующий список: ƃɐ ƒ””›',
ɐ‘ɐ, ɐ ‡”‹‘‡ɐƄ.

ʴʴʴ†‡ˆ‰‘‘†ſƀś
ŜŜŜ”‡–—”ƃɐ ƒ””›ɐřɐ‘ɐřɐ ‡”‹‘‡ɐƄ
ŜŜŜ
ʴʴʴ‰‘‘†ſƀ
ƃɐ ƒ””›ɐřɐ‘ɐřɐ ‡”‹‘‡ɐƄ

9.2. Определите функцию генератора ‰‡–ɏ‘††•, которая возвращает нечетные числа


из диапазона ”ƒ‰‡ſɨɥƀ. Используйте цикл for, чтобы найти и вывести третье
возвращенное значение.

ʴʴʴ†‡ˆ‰‡–ɏ‘††•ſƀś
ŜŜŜˆ‘”—„‡”‹”ƒ‰‡ſɨřɨɥřɩƀś
ŜŜŜ›‹‡Ž†—„‡”
ŜŜŜ
ʴʴʴ ‘—–ʰɨ
ʴʴʴˆ‘”—„‡”‹‰‡–ɏ‘††•ſƀś
ŜŜŜ‹ˆ ‘—–ʰʰɪś
ŜŜŜ’”‹–ſɑЇ–Š‹”†‘††—„‡”‹•ɑř—„‡”ƀ
ŜŜŜ„”‡ƒ
ŜŜŜ ‘—–ʫʰɨ
ŜŜŜ

Третье нечетное число равно ɬ.

9.3. Определите декоратор test, который выводит строку ɐ•–ƒ”–ɐ при вызове функ-
ции и строку ɐ‡†ɐ, когда функция завершает свою работу.

ʴʴʴ†‡ˆ–‡•–ſˆ— ƀś
ŜŜŜ†‡ˆ‡™ɏˆ— ſƋƒ”‰•řƋƋ™ƒ”‰•ƀś
ŜŜŜ’”‹–ſɐ•–ƒ”–ɐƀ
ŜŜŜ”‡•—Ž–ʰˆ— ſƋƒ”‰•řƋƋ™ƒ”‰•ƀ
ŜŜŜ’”‹–ſɐ‡†ɐƀ
ŜŜŜ”‡–—””‡•—Ž–
ŜŜŜ”‡–—”‡™ɏˆ—
ŜŜŜ
ʴʴʴ
ʴʴʴɒ–‡•–
ŜŜŜ†‡ˆ‰”‡‡–‹‰ſƀś
ŜŜŜ’”‹–ſɑ ”‡‡–‹‰•řƒ”–ŠŽ‹‰ɑƀ
ŜŜŜ
ʴʴʴ‰”‡‡–‹‰ſƀ
start
”‡‡–‹‰•řƒ”–ŠŽ‹‰
‡†
  ǷȘȐȓȖȎȍȕȐȧ

9.4. Определите исключение ‘’•š ‡’–‹‘. Сгенерируйте его и посмотрите, что


произойдет. Затем напишите код, позволяющий поймать это исключение и вы-
вести строку ɐƒ—‰Š– an ‘‘’•ɐ.

ʴʴʴ Žƒ••‘’•š ‡’–‹‘ſš ‡’–‹‘ƀś


ŜŜŜ’ƒ••
ŜŜŜ
ʴʴʴ”ƒ‹•‡‘’•š ‡’–‹‘ſƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
ɏɏƒ‹ɏɏŜ‘’•š ‡’–‹‘
ʴʴʴ
ʴʴʴ–”›ś
ŜŜŜ”ƒ‹•‡‘’•š ‡’–‹‘
ŜŜŜ‡š ‡’–‘’•š ‡’–‹‘ś
ŜŜŜ’”‹–ſɐƒ—‰Š–ƒ‘‘’•ɐƀ
ŜŜŜ
ƒ—‰Š–ƒ‘‘’•

ǶȑȖȑȖȑȖȉȢȍȒȚȣȐȒȓȈșșȣ
10.1. Создайте класс Š‹‰, не имеющий содержимого, и выведите его на экран.
Затем создайте объект ‡šƒ’އ этого класса и также выведите его. Совпада-
ют ли выведенные значения?

ʴʴʴ Žƒ••Š‹‰ś
ŜŜŜ’ƒ••
ŜŜŜ
ʴʴʴ’”‹–ſŠ‹‰ƀ
ʳ Žƒ••ɐɏɏƒ‹ɏɏŜŠ‹‰ɐʴ
ʴʴʴ‡šƒ’އʰŠ‹‰ſƀ
ʴʴʴ’”‹–ſ‡šƒ’އƀ
ʳɏɏƒ‹ɏɏŜŠ‹‰‘„Œ‡ –ƒ–ɥšɨɥɥɭˆɪˆ†ɥʴ

10.2. Создайте новый класс с именем Š‹‰ɩ и присвойте переменной letters зна-
чение ɐƒ„ ɐ. Выведите на экран значение letters.

ʴʴʴ Žƒ••Š‹‰ɩś
ŜŜŜއ––‡”•ʰɐƒ„ ɐ
ŜŜŜ
ʴʴʴ’”‹–ſŠ‹‰ɩŜއ––‡”•ƀ
ƒ„

10.3. Создайте еще один класс, который, конечно же, называется Š‹‰ɪ. В этот раз
присвойте значение ɐš›œɐ переменной объекта letters. Выведите на экран
значение атрибута letters. Понадобилось ли вам создавать объект класса,
чтобы сделать это?
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ʴʴʴ Žƒ••Š‹‰ɪś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆƀś
ŜŜŜ•‡ŽˆŜއ––‡”•ʰɐš›œɐ
ŜŜŜ

Переменная letters принадлежит любому объекту класса Š‹‰ɪ, но не самому классу


Š‹‰ɪ:
ʴʴʴ’”‹–ſŠ‹‰ɪŜއ––‡”•ƀ
”ƒ ‡„ƒ ſ‘•–”‡ ‡– ƒŽŽŽƒ•–ƀś
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨř‹ʳ‘†—އʴ
––”‹„—–‡””‘”ś–›’‡‘„Œ‡ –ɐŠ‹‰ɪɐŠƒ•‘ƒ––”‹„—–‡ɐއ––‡”•ɐ
ʴʴʴ•‘‡–Š‹‰ʰŠ‹‰ɪſƀ
ʴʴʴ’”‹–ſ•‘‡–Š‹‰Ŝއ––‡”•ƀ
š›œ

10.4. Создайте класс އ‡–, имеющий атрибуты объекта ƒ‡, •›„‘Ž и —„‡”.
Создайте объект этого класса со значениями ɐ ›†”‘‰‡ɐ, ɐ ɐ и ɨ.

ʴʴʴ Žƒ••އ‡–ś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ř•›„‘Žř—„‡”ƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰƒ‡
ŜŜŜ•‡ŽˆŜ•›„‘Žʰ•›„‘Ž
ŜŜŜ•‡ŽˆŜ—„‡”ʰ—„‡”
ŜŜŜ
ʴʴʴŠ›†”‘‰‡ʰއ‡–ſɐ ›†”‘‰‡ɐřɐ ɐřɨƀ

10.5. Создайте словарь со следующими ключами и значениями: ɐƒ‡ɐ: ɐ ›†”‘‰‡ɐ,


ɐ•›„‘Žɐ: ɐ ɐ, ɐ—„‡”ɐ: ɨ. Далее создайте объект с именем Š›†”‘‰‡ класса
އ‡– с помощью этого словаря.

Начнем со словаря:
ʴʴʴ‡Žɏ†‹ –ʰƇɐƒ‡ɐśɐ ›†”‘‰‡ɐřɐ•›„‘Žɐśɐ ɐřɐ—„‡”ɐśɨƈ

Это работает, однако необходимо напечатать много текста:


ʴʴʴŠ›†”‘‰‡ʰއ‡–ſ‡Žɏ†‹ –ƃɐƒ‡ɐƄř‡Žɏ†‹ –ƃɐ•›„‘ŽɐƄř‡Žɏ†‹ –ƃɐ—„‡”ɐƄƀ

Убедимся, что это работает:


ʴʴʴŠ›†”‘‰‡Ŝƒ‡
ɐ ›†”‘‰‡ɐ

Однако вы также можете инициализировать объект непосредственно с помощью слова-


ря, поскольку его ключ имени совпадает с аргументами функции ɏɏ‹‹–ɏɏ (аргументы —
ключевые слова рассматриваются в главе 9):
ʴʴʴŠ›†”‘‰‡ʰއ‡–ſƋƋ‡Žɏ†‹ –ƀ
ʴʴʴŠ›†”‘‰‡Ŝƒ‡
ɐ ›†”‘‰‡ɐ
  ǷȘȐȓȖȎȍȕȐȧ

10.6. Для класса އ‡– определите метод с именем †—’ſƀ, который выводит на
экран значения атрибутов объекта (ƒ‡, •›„‘Ž и —„‡”). Создайте объект
Š›†”‘‰‡ из этого нового определения и используйте метод †—’ſƀ, чтобы вы-
вести на экран его атрибуты.

ʴʴʴ Žƒ••އ‡–ś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ř•›„‘Žř—„‡”ƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰƒ‡
ŜŜŜ•‡ŽˆŜ•›„‘Žʰ•›„‘Ž
ŜŜŜ•‡ŽˆŜ—„‡”ʰ—„‡”
ŜŜŜ†‡ˆ†—’ſ•‡Žˆƀś
ŜŜŜ’”‹–ſɐƒ‡ʰʩ•ř•›„‘Žʰʩ•ř—„‡”ʰʩ•ɐʩ
ŜŜŜſ•‡ŽˆŜƒ‡ř•‡ŽˆŜ•›„‘Žř•‡ŽˆŜ—„‡”ƀƀ
ŜŜŜ
ʴʴʴŠ›†”‘‰‡ʰއ‡–ſƋƋ‡Žɏ†‹ –ƀ
ʴʴʴŠ›†”‘‰‡Ŝ†—’ſƀ
ƒ‡ʰ ›†”‘‰‡ř•›„‘Žʰ ř—„‡”ʰɨ

10.7. Вызовите функцию ’”‹–ſŠ›†”‘‰‡ƀ. В определении класса އ‡– измените


имя метода †—’ на ɏɏ•–”ɏɏ, создайте новый объект Š›†”‘‰‡ и затем снова вы-
зовите метод ’”‹–ſŠ›†”‘‰‡ƀ.

ʴʴʴ’”‹–ſŠ›†”‘‰‡ƀ
ʳɏɏƒ‹ɏɏŜއ‡–‘„Œ‡ –ƒ–ɥšɨɥɥɭˆɬɪɨɥʴ
ʴʴʴ Žƒ••އ‡–ś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ř•›„‘Žř—„‡”ƀś
ŜŜŜ•‡ŽˆŜƒ‡ʰƒ‡
ŜŜŜ•‡ŽˆŜ•›„‘Žʰ•›„‘Ž
ŜŜŜ•‡ŽˆŜ—„‡”ʰ—„‡”
ŜŜŜ†‡ˆɏɏ•–”ɏɏſ•‡Žˆƀś
ŜŜŜ”‡–—”ſɐƒ‡ʰʩ•ř•›„‘Žʰʩ•ř—„‡”ʰʩ•ɐʩ
ŜŜŜſ•‡ŽˆŜƒ‡ř•‡ŽˆŜ•›„‘Žř•‡ŽˆŜ—„‡”ƀƀ
ŜŜŜ
ʴʴʴŠ›†”‘‰‡ʰއ‡–ſƋƋ‡Žɏ†‹ –ƀ
ʴʴʴ’”‹–ſŠ›†”‘‰‡ƀ
ƒ‡ʰ ›†”‘‰‡ř•›„‘Žʰ ř—„‡”ʰɨ

Метод ɏɏ•–”ɏɏſƀ — это один из волшебных методов Python. Функция print вызывает
метод объекта ɏɏ•–”ɏɏſƀ, чтобы получить его строковое представление. Если у объ-
екта нет метода ɏɏ•–”ɏɏſƀ, то он получает метод по умолчанию от его родительского
класса „Œ‡ –, который возвращает строку наподобие ʳɏɏƒ‹ɏɏŜއ‡– ‘„Œ‡ – ƒ–
ɥšɨɥɥɭˆɬɪɨɥʴ.

10.8. Модифицируйте класс އ‡–, сделав атрибуты ƒ‡, •›„‘Ž и —„‡” приват-
ными. Определите свойство получателя для каждого атрибута, возвращающее
его значение.

ʴʴʴ Žƒ••އ‡–ś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆřƒ‡ř•›„‘Žř—„‡”ƀś
ŜŜŜ•‡ŽˆŜɏɏƒ‡ʰƒ‡
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ŜŜŜ•‡ŽˆŜɏɏ•›„‘Žʰ•›„‘Ž
ŜŜŜ•‡ŽˆŜɏɏ—„‡”ʰ—„‡”
ŜŜŜɒ’”‘’‡”–›
ŜŜŜ†‡ˆƒ‡ſ•‡Žˆƀś
ŜŜŜ”‡–—”•‡ŽˆŜɏɏƒ‡
ŜŜŜɒ’”‘’‡”–›
ŜŜŜ†‡ˆ•›„‘Žſ•‡Žˆƀś
ŜŜŜ”‡–—”•‡ŽˆŜɏɏ•›„‘Ž
ŜŜŜɒ’”‘’‡”–›
ŜŜŜ†‡ˆ—„‡”ſ•‡Žˆƀś
ŜŜŜ”‡–—”•‡ŽˆŜɏɏ—„‡”
ŜŜŜ
ʴʴʴŠ›†”‘‰‡ʰއ‡–ſɐ ›†”‘‰‡ɐřɐ ɐřɨƀ
ʴʴʴŠ›†”‘‰‡Ŝƒ‡
ɐ ›†”‘‰‡ɐ
ʴʴʴŠ›†”‘‰‡Ŝ•›„‘Ž
ɐ ɐ
ʴʴʴŠ›†”‘‰‡Ŝ—„‡”
ɨ

10.9. Определите три класса: ‡ƒ”, ƒ„„‹– и  –‘–Š‘”’‡. Для каждого из них опре-
делите всего один метод — ‡ƒ–•ſƀ. Этот метод должен возвращать значения
ɐ„‡””‹‡•ɐ (для ‡ƒ”), ɐ Ž‘˜‡”ɐ (для ƒ„„‹–) или ɐ ƒ’‡”•ɐ (для  –‘–Š‘”’‡).
Создайте по одному объекту каждого класса и выведите на экран то, что ест
указанное животное.

ʴʴ Žƒ••‡ƒ”ś
ŜŜŜ†‡ˆ‡ƒ–•ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ„‡””‹‡•ɐ
ŜŜŜ
ʴʴʴ Žƒ••ƒ„„‹–ś
ŜŜŜ†‡ˆ‡ƒ–•ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ Ž‘˜‡”ɐ
ŜŜŜ
ʴʴʴ Žƒ•• –‘–Š‘”’‡ś
ŜŜŜ†‡ˆ‡ƒ–•ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ ƒ’‡”•ɐ
ŜŜŜ
ʴʴʴ„ʰ‡ƒ”ſƀ
ʴʴʴ”ʰƒ„„‹–ſƀ
ʴʴʴ‘ʰ –‘–Š‘”’‡ſƀ
ʴʴʴ’”‹–ſ„Ŝ‡ƒ–•ſƀƀ
berries
ʴʴʴ’”‹–ſ”Ŝ‡ƒ–•ſƀƀ
Ž‘˜‡”
ʴʴʴ’”‹–ſ‘Ŝ‡ƒ–•ſƀƀ
ƒ’‡”•

10.10. Определите три класса: ƒ•‡”, Žƒ™ и ƒ”–Š‘‡. Каждый из них имеет только
один метод — †‘‡•ſƀ. Он возвращает значения ɐ†‹•‹–‡‰”ƒ–‡ɐ (для ƒ•‡”),
ɐ ”—•Šɐ (для Žƒ™) или ɐ”‹‰ɐ (для ƒ”–Š‘‡). Далее определите класс ‘„‘–,
  ǷȘȐȓȖȎȍȕȐȧ

содержащий по одному объекту каждого из этих классов. Определите метод †‘‡•ſƀ


для класса ‘„‘–, который выводит на экран все, что делают его компоненты.

ʴʴʴ Žƒ••ƒ•‡”ś
ŜŜŜ†‡ˆ†‘‡•ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ†‹•‹–‡‰”ƒ–‡ɐ
ŜŜŜ
ʴʴʴ Žƒ••Žƒ™ś
ŜŜŜ†‡ˆ†‘‡•ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ ”—•Šɐ
ŜŜŜ
ʴʴʴ Žƒ••ƒ”–Š‘‡ś
ŜŜŜ†‡ˆ†‘‡•ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐ”‹‰ɐ
ŜŜŜ
ʴʴʴ Žƒ••‘„‘–ś
ŜŜŜ†‡ˆɏɏ‹‹–ɏɏſ•‡Žˆƀś
ŜŜŜ•‡ŽˆŜŽƒ•‡”ʰƒ•‡”ſƀ
ŜŜŜ•‡ŽˆŜ Žƒ™ʰŽƒ™ſƀ
ŜŜŜ•‡ŽˆŜ•ƒ”–’Š‘‡ʰƒ”–Š‘‡ſƀ
ŜŜŜ†‡ˆ†‘‡•ſ•‡Žˆƀś
ŜŜŜ”‡–—”ɐɐɐ Šƒ˜‡ƒ›ƒ––ƒ Š‡–•ś
ŜŜŜ›Žƒ•‡”ř–‘ʩ•Ŝ
ŜŜŜ› Žƒ™ř–‘ʩ•Ŝ
ŜŜŜ›•ƒ”–’Š‘‡ř–‘ʩ•Ŝɐɐɐʩſ
ŜŜŜ•‡ŽˆŜŽƒ•‡”Ŝ†‘‡•ſƀř
ŜŜŜ•‡ŽˆŜ Žƒ™Ŝ†‘‡•ſƀř
ŜŜŜ•‡ŽˆŜ•ƒ”–’Š‘‡Ŝ†‘‡•ſƀƀ
ŜŜŜ
ʴʴʴ”‘„„‹‡ʰ‘„‘–ſƀ
ʴʴʴ’”‹–ſ”‘„„‹‡Ŝ†‘‡•ſƀƀ
Šƒ˜‡ƒ›ƒ––ƒ Š‡–•ś
›Žƒ•‡”ř–‘†‹•‹–‡‰”ƒ–‡Ŝ
› Žƒ™ř–‘ ”—•ŠŜ
›•ƒ”–’Š‘‡ř–‘”‹‰Ŝ

ǴȖȌțȓȐȗȈȒȍȚȣȐȗȘȖȋȘȈȔȔȣ
11.1. Создайте файл с именем œ‘‘Ŝ’›. В нем объявите функцию Š‘—”•ſƀ, которая вы-
водит на экран строку ɐ’‡ ɰŞɬ †ƒ‹Ž›ɐ. Далее используйте интерактивный ин-
терпретатор, чтобы импортировать модуль œ‘‘ и вызвать его функцию Š‘—”•ſƀ.

Так выглядит файл œ‘‘Ŝ’›:


†‡ˆŠ‘—”•ſƀś
’”‹–ſɐ’‡ɰŞɬ†ƒ‹Ž›ɐƀ

А теперь импортируем его интерактивно:


ʴʴʴ‹’‘”–œ‘‘
ʴʴʴœ‘‘ŜŠ‘—”•ſƀ
’‡ɰŞɬ†ƒ‹Ž›
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

11.2. В интерактивном интерпретаторе импортируйте модуль œ‘‘ под именем


‡ƒ‰‡”‹‡ и вызовите его функцию Š‘—”•ſƀ.

ʴʴʴ‹’‘”–œ‘‘ƒ•‡ƒ‰‡”‹‡
ʴʴʴ‡ƒ‰‡”‹‡ŜŠ‘—”•ſƀ
’‡ɰŞɬ†ƒ‹Ž›

11.3. Оставаясь в интерпретаторе, импортируйте непосредственно функцию Š‘—”•ſƀ


из модуля œ‘‘ и вызовите ее.

ʴʴʴˆ”‘œ‘‘‹’‘”–Š‘—”•
ʴʴʴŠ‘—”•ſƀ
’‡ɰŞɬ†ƒ‹Ž›

11.4. Импортируйте функцию Š‘—”•ſƀ под именем info и вызовите ее.

ʴʴʴˆ”‘œ‘‘‹’‘”–Š‘—”•ƒ•‹ˆ‘
ʴʴʴ‹ˆ‘ſƀ
’‡ɰŞɬ†ƒ‹Ž›

11.5. Создайте словарь с именем plain, содержащий пары «ключ — значение» ɐƒɐś
ɨř ɐ„ɐś ɩ и ɐ ɐśɪ, а затем выведите его на экран.

ʴʴʴ’Žƒ‹ʰƇɐƒɐśɨřɐ„ɐśɩřɐ ɐśɪƈ
ʴʴʴ’Žƒ‹
Ƈɐƒɐśɨřɐ ɐśɪřɐ„ɐśɩƈ

11.6. Создайте ”†‡”‡†‹ – с именем ˆƒ › из пар «ключ — значение», приведенных


в упражнении 11.5, и выведите его на экран. Изменился ли порядок ключей?

ʴʴʴˆ”‘ ‘ŽŽ‡ –‹‘•‹’‘”–”†‡”‡†‹ –


ʴʴʴˆƒ ›ʰ”†‡”‡†‹ –ſƃſɐƒɐřɨƀřſɐ„ɐřɩƀřſɐ ɐřɪƀƄƀ
ʴʴʴˆƒ ›
”†‡”‡†‹ –ſƃſɐƒɐřɨƀřſɐ„ɐřɩƀřſɐ ɐřɪƀƄƀ

11.7. Создайте †‡ˆƒ—Ž–†‹ – с именем †‹ –ɏ‘ˆɏŽ‹•–• и передайте ему аргумент


list. Создайте список †‹ –ɏ‘ˆɏŽ‹•–•ƃɐƒɐƄ и присоедините к нему значение
ɐ•‘‡–Š‹‰ for ƒɐ за одну операцию. Выведите на экран †‹ –ɏ‘ˆɏŽ‹•–•ƃɐƒɐƄ.

ʴʴʴˆ”‘ ‘ŽŽ‡ –‹‘•‹’‘”–†‡ˆƒ—Ž–†‹ –


ʴʴʴ†‹ –ɏ‘ˆɏŽ‹•–•ʰ†‡ˆƒ—Ž–†‹ –ſŽ‹•–ƀ
ʴʴʴ†‹ –ɏ‘ˆɏŽ‹•–•ƃɐƒɐƄŜƒ’’‡†ſɐ•‘‡–Š‹‰ˆ‘”ƒɐƀ
ʴʴʴ†‹ –ɏ‘ˆɏŽ‹•–•ƃɐƒɐƄ
ƃɐ•‘‡–Š‹‰ˆ‘”ƒɐƄ
  ǷȘȐȓȖȎȍȕȐȧ

ǶȉȘȈȉȈȚȣȊȈȍȔȌȈȕȕȣȍ
12.1. Создайте строку Unicode с именем ›•–‡”› и присвойте ей значение ɐɎɥɥɥɨˆɫƒɰɐ.
Выведите на экран значение ›•–‡”› и ее имя Unicode.

ʴʴʴ‹’‘”–—‹ ‘†‡†ƒ–ƒ
ʴʴʴ›•–‡”›ʰɐɎɥɥɥɨˆɰɯɫɐ
ʴʴʴ›•–‡”›
ɐชɐ
ʴʴʴ—‹ ‘†‡†ƒ–ƒŜƒ‡ſ›•–‡”›ƀ
ɐ  ɐ

Ой-ой-ой! Что еще у них там есть?


12.2. Закодируйте строку ›•–‡”›, на этот раз с использованием кодировки UTF-8,
в переменную типа bytes с именем ’‘’ɏ„›–‡•. Выведите на экран значение
переменной ’‘’ɏ„›–‡•.

ʴʴʴ’‘’ɏ„›–‡•ʰ›•–‡”›Ŝ‡ ‘†‡ſɐ—–ˆŞɯɐƀ
ʴʴʴ’‘’ɏ„›–‡•
„ɐɎšˆɥɎšɰˆɎšɰɩɎšƒɰɐ

12.3. Используя кодировку UTF-8, декодируйте переменную popbytes в строку


’‘’ɏ•–”‹‰. Выведите на экран значение переменной ’‘’ɏ•–”‹‰. Равно ли оно
значению переменной ›•–‡”›?

ʴʴʴ’‘’ɏ•–”‹‰ʰ’‘’ɏ„›–‡•Ŝ†‡ ‘†‡ſɐ—–ˆŞɯɐƀ
ʴʴʴ’‘’ɏ•–”‹‰
ɐชɐ
ʴʴʴ’‘’ɏ•–”‹‰ʰʰ›•–‡”›
”—‡

12.4. При работе с текстом вам могут пригодиться регулярные выражения. Мы вос-
пользуемся ими несколькими способами в следующем примере текста. Перед
вами стихотворение Ode on the Mammoth Cheese, написанное Джеймсом
Макинтайром в 1866 году во славу головки сыра весом 7000 фунтов, которая
была изготовлена в Онтарио и отправлена в международное путешествие. Если
не хотите самостоятельно перепечатывать это стихотворение, используйте
свой любимый поисковик и скопируйте текст в программу. Или скопируйте
стихотворение из проекта «Гутенберг» (KWWSELWO\PFLQW\UHSRHWU\). Назовите
следующую строку ƒ‘–Š.

ʴʴʴƒ‘–Šʰɐɐɐ
ŜŜŜ‡Šƒ˜‡•‡‡–Ї‡ř“—‡‡‘ˆ Ї‡•‡ř
ŜŜŜ›‹‰“—‹‡–Ž›ƒ–›‘—”‡ƒ•‡ř
ŜŜŜ ‡–Ž›ˆƒ‡†„›‡˜‡‹‰„”‡‡œ‡ř
ŜŜŜŠ›ˆƒ‹”ˆ‘”‘ˆŽ‹‡•†ƒ”‡•‡‹œ‡Ŝ
ŜŜŜ
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ŜŜŜŽŽ‰ƒ‹Ž›†”‡••‡†•‘‘›‘—ɐŽŽ‰‘
ŜŜŜ‘–Ї‰”‡ƒ–”‘˜‹ ‹ƒŽ•Š‘™ř
ŜŜŜ‘„‡ƒ†‹”‡†„›ƒ›ƒ„‡ƒ—
ŜŜŜ –Ї ‹–›‘ˆ‘”‘–‘Ŝ
ŜŜŜ
ŜŜŜ‘™•—‡”‘—•ƒ•ƒ•™ƒ”‘ˆ„‡‡•ř
ŜŜŜ”ƒ•–Їއƒ˜‡•—’‘–Ї–”‡‡•ř
ŜŜŜ –†‹†”‡“—‹”‡–‘ƒ‡–Ї‡’އƒ•‡ř
ŜŜŜ†•–ƒ†—”‹˜ƒŽŽ‡†ř“—‡‡‘ˆ Ї‡•‡Ŝ
ŜŜŜ
ŜŜŜƒ››‘—‘–”‡ ‡‹˜‡ƒ• ƒ”ƒ•
ŜŜŜ‡Šƒ˜‡Їƒ”†–Šƒ–”Ŝ ƒ””‹•
ŜŜŜ –‡†•–‘•‡†›‘—‘ˆˆƒ•ˆƒ”ƒ•
ŜŜŜЇ‰”‡ƒ–™‘”ކɐ••Š‘™ƒ–ƒ”‹•Ŝ
ŜŜŜ
ŜŜŜˆ–Ї›‘—–Š„‡™ƒ”‡‘ˆ–Ї•‡ř
ŜŜŜ ‘”•‘‡‘ˆ–Ї‹‰Š–”—†‡Ž›•“—‡‡œ‡
ŜŜŜ†„‹–‡›‘—” Ї‡ř–Ї•‘‰•‘”‰Ž‡‡•
ŜŜŜ‡ ‘—ކ‘–•‹‰ř‘ŠŠ“—‡‡‘ˆ Ї‡•‡Ŝ
ŜŜŜ
ŜŜŜ‡ɐ”––Š‘—•—•’‡†‡†ˆ”‘„ƒŽŽ‘‘ř
ŜŜŜ‘—ɐ† ƒ•–ƒ•Šƒ†‡‡˜‡ƒ–‘‘ř
ŜŜŜ ‘Ž•™‘—ކ–Š‹‹–™ƒ•–Ї‘‘
ŜŜŜ„‘—––‘ˆƒŽŽƒ† ”—•Š–Ї•‘‘Ŝ
ŜŜŜɐɐɐ

12.5. Импортируйте модуль re, чтобы использовать функции регулярных выраже-


ний в Python. Примените функцию ”‡Ŝˆ‹†ƒŽŽſƀ для вывода на экран всех
слов, которые начинаются с буквы ȥ.

Мы определим переменную pat для шаблона и затем будем искать такой шаблон в стро-
ке ƒ‘–Š:
ʴʴʴ‹’‘”–”‡
ʴʴʴ’ƒ–ʰ”ɐɎ„ Ɏ™Ƌɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐ Ї‡•‡ɐřɐ ‹–›ɐřɐ Ї‡•‡ɐřɐ Ї‡ɐřɐ ‘—ކɐřɐ Ї‡•‡ɐřɐ ƒ•–ɐřɐ ”—•ŠɐƄ

Элемент Ɏ„ означает, что нужно начать с границы между словом и не словом. Используйте
такую конструкцию, чтобы указать либо на начало, либо на конец слова. Литерал —
это первая буква всех слов, которые мы ищем. Элемент Ɏ™ означает любой символ слова,
которое включает в себя буквы, цифры и подчеркивания (ɏ). Элемент * означает ноль
или больше таких символов. Целиком это выражение находит слова, которые начина-
ются с ȥ, включая ɐ ɐ. Если вы не использовали простую строку (у таких строк r стоит
прямо перед открывающей кавычкой), Python интерпретирует Ɏ„ как возврат на шаг,
и поиск по таинственной причине ничего не найдет:
ʴʴʴ’ƒ–ʰɐɎ„ Ɏ™Ƌɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃƄ
  ǷȘȐȓȖȎȍȕȐȧ

12.6. Найдите все четырехбуквенные слова, которые начинаются с буквы .

ʴʴʴ’ƒ–ʰ”ɐɎ„ Ɏ™ƇɪƈɎ„ɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐ ‹–›ɐřɐ ƒ•–ɐƄ

Вам нужен последний символ Ɏ„, чтобы указать на конец слова. В противном случае вы
получите первые четыре буквы всех слов, которые начинаются с ȥ и имеют как минимум
четыре буквы:
ʴʴʴ’ƒ–ʰ”ɐɎ„ Ɏ™Ƈɪƈɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐ Ї‡ɐřɐ ‹–›ɐřɐ Ї‡ɐřɐ Ї‡ɐřɐ ‘—Žɐřɐ Ї‡ɐřɐ ƒ•–ɐřɐ ”—•ɐƄ

12.7. Найдите все слова, которые заканчиваются на букву r.

Это упражнение с подвохом. Мы получаем правильный результат для слов, которые за-
канчиваются на r:
ʴʴʴ’ƒ–ʰ”ɐɎ„Ɏ™Ƌ”Ɏ„ɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐ›‘—”ɐřɐˆƒ‹”ɐřɐ”ɐřɐ• ƒ”ɐřɐ”ɐřɐˆƒ”ɐřɐ ‘”ɐřɐ›‘—”ɐřɐ‘”ɐƄ

Однако результаты будут не так хороши, если мы поищем слова, которые заканчивают-
ся на l:
ʴʴʴ’ƒ–ʰ”ɐɎ„Ɏ™ƋŽɎ„ɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐŽŽɐřɐŽŽɐřɐ”‘˜‹ ‹ƒŽɐřɐˆƒŽŽɐƄ

Что здесь делает буквосочетание ll? Паттерн Ɏ™ совпадает только c буквами, цифра-
ми и подчеркиваниями, но не с апострофами ASCII. В результате вы увидите букво-
сочетание ll. Мы можем обработать этот крайний случай, добавив апостроф в список
символов, с которыми должен совпасть набор символов. Наша первая попытка не ра-
ботает:
ʴʴʴ’ƒ–ʰ”ɐɎ„ƃɎ™ɐƄƋŽɎ„ɐ
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨ
’ƒ–ʰ”ɐɎ„ƃɎ™ɐƄƋŽɎ„ɐ

Python указывает на окрестности ошибки, но может потребоваться какое-то время на


осознание: ошибка заключалась в том, что строка шаблона окружена такими же апо-
строфами — символами кавычки. Один из способов решить эту проблему — использо-
вать управляющую последовательность с обратным слешем:
ʴʴʴ’ƒ–ʰ”ɐɎ„ƃɎ™ɎɐƄƋŽɎ„ɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐŽŽɐřɑ›‘—ɐŽŽɑřɐ”‘˜‹ ‹ƒŽɐřɐˆƒŽŽɐƄ

Еще одно решение — окружить строку шаблона двойными кавычками:


ʴʴʴ’ƒ–ʰ”ɑɎ„ƃɎ™ɐƄƋŽɎ„ɑ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐŽŽɐřɑ›‘—ɐŽŽɑřɐ”‘˜‹ ‹ƒŽɐřɐˆƒŽŽɐƄ
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

Это упражнение с подвохом. Мы получаем правильный результат для слов, которые за-
канчиваются на r:
ʴʴʴ’ƒ–ʰ”ɐɎ„Ɏ™Ƌ”Ɏ„ɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐ›‘—”ɐřɐˆƒ‹”ɐřɐ”ɐřɐ• ƒ”ɐřɐ”ɐřɐˆƒ”ɐřɐ ‘”ɐřɐ›‘—”ɐřɐ‘”ɐƄ

Однако результаты будут не так хороши, если мы поищем слова, которые заканчивают-
ся на l:
ʴʴʴ’ƒ–ʰ”ɐɎ„Ɏ™ƋŽɎ„ɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐŽŽɐřɐŽŽɐřɐ”‘˜‹ ‹ƒŽɐřɐˆƒŽŽɐƄ

Что здесь делает буквосочетание ll? Паттерн Ɏ™ совпадает только c буквами, цифрами
и подчеркиваниями, но не с апострофами ASCII. В результате вы увидите буквосочета-
ние ll. Мы можем обработать этот крайний случай, добавив апостроф в список симво-
лов, с которыми должен совпасть набор символов. Наша первая попытка не работает:
ʴʴʴ’ƒ–ʰ”ɐɎ„ƃɎ™ɐƄƋŽɎ„ɐ
 ‹Ž‡ɑʳ•–†‹ʴɑřŽ‹‡ɨ
’ƒ–ʰ”ɐɎ„ƃɎ™ɐƄƋŽɎ„ɐ

Python указывает на окрестности ошибки, но может потребоваться какое-то время на


осознание: ошибка заключалась в том, что строка шаблона окружена такими же апо-
строфами — символами кавычки. Один из способов решить эту проблему — использо-
вать управляющую последовательность с обратным слешем:
ʴʴʴ’ƒ–ʰ”ɐɎ„ƃɎ™ɎɐƄƋŽɎ„ɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐŽŽɐřɑ›‘—ɐŽŽɑřɐ”‘˜‹ ‹ƒŽɐřɐˆƒŽŽɐƄ

Еще одно решение — окружить строку шаблона двойными кавычками:


ʴʴʴ’ƒ–ʰ”ɑɎ„ƃɎ™ɐƄƋŽɎ„ɑ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐŽŽɐřɑ›‘—ɐŽŽɑřɐ”‘˜‹ ‹ƒŽɐřɐˆƒŽŽɐƄ

12.8. Найдите все слова, которые содержат три гласные подряд.

Начиная с границы слова, любое количество символов слова, три гласные и далее любые
символы, не являющиеся гласными, до конца слова:
ʴʴʴ’ƒ–ʰ”ɐɎ„ƃɋƒ‡‹‘—ƄƋƃƒ‡‹‘—ƄƇɪƈƃɋƒ‡‹‘—ƄƋɎ„ɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐ“—‡‡ɐřɐ“—‹‡–Ž›ɐřɐ„‡ƒ—Ɏ ɐřɐ“—‡‡ɐřɐ•“—‡‡œ‡ɐřɐ“—‡‡ɐƄ

Выглядит правильно, за исключением строки ɐ„‡ƒ—Ɏ ɐ. Мы искали строку ƒ‘–Š


целиком. Конструкция ƃɋƒ‡‹‘—Ƅ совпадает с любыми символами, не являющимися глас-
ными, включая Ɏ (перенос строки, который отмечает конец текстовой строки). Нам
нужно добавить еще кое-что в набор игнорируемых символов: Ɏ• совпадает с любыми
символами пробелов, включая Ɏ:
ʴʴʴ’ƒ–ʰ”ɐɎ„Ɏ™Ƌƃƒ‡‹‘—ƄƇɪƈƃɋƒ‡‹‘—Ɏ•ƄɎ™ƋɎ„ɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐ“—‡‡ɐřɐ“—‹‡–Ž›ɐřɐ“—‡‡ɐřɐ•“—‡‡œ‡ɐřɐ“—‡‡ɐƄ
  ǷȘȐȓȖȎȍȕȐȧ

На сей раз мы не нашли слово beau, поэтому нужно внести в шаблон еще одно исправле-
ние: совпадение с любым числом (даже нулем) не гласных после трех гласных. Наш пре-
дыдущий шаблон всегда совпадал с одним не гласным символом:
ʴʴʴ’ƒ–ʰ”ɐɎ„Ɏ™Ƌƃƒ‡‹‘—ƄƇɪƈƃɋƒ‡‹‘—Ɏ•ƄƋɎ™ƋɎ„ɐ
ʴʴʴ”‡Ŝˆ‹†ƒŽŽſ’ƒ–řƒ‘–Šƀ
ƃɐ“—‡‡ɐřɐ“—‹‡–Ž›ɐřɐ„‡ƒ—ɐřɐ“—‡‡ɐřɐ•“—‡‡œ‡ɐřɐ“—‡‡ɐƄ

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

12.9. Используйте метод —Š‡šŽ‹ˆ› для того, чтобы преобразовать эту шестнадца-
теричную строку, созданную путем объединения двух строк для размещения
на странице, в переменную типа bytes с именем gif.
ɐɫɮɫɰɫɭɪɯɪɰɭɨɥɨɥɥɥɨɥɥɯɥɥɥɥɥɥɥɥɥɥɥˆˆˆˆˆˆɩɨˆɰɐʫ
ɐɥɫɥɨɥɥɥɥɥɥɥɥɩ ɥɥɥɥɥɥɥɥɥɨɥɥɥɨɥɥɥɥɥɩɥɨɫɫɥɥɪ„ɐ

ʴʴʴ‹’‘”–„‹ƒ• ‹‹
ʴʴʴЇšɏ•–”ʰɐɫɮɫɰɫɭɪɯɪɰɭɨɥɨɥɥɥɨɥɥɯɥɥɥɥɥɥɥɥɥɥɥˆˆˆˆˆˆɩɨˆɰɐʫɎ
ŜŜŜɐɥɫɥɨɥɥɥɥɥɥɥɥɩ ɥɥɥɥɥɥɥɥɥɨɥɥɥɨɥɥɥɥɥɩɥɨɫɫɥɥɪ„ɐ
ʴʴʴ‰‹ˆʰ„‹ƒ• ‹‹Ŝ—Š‡šŽ‹ˆ›ſЇšɏ•–”ƀ
ʴʴʴއſ‰‹ˆƀ
ɫɩ

12.10. Байты, содержащиеся в переменной gif, определяют однопиксельный про-


зрачный GIF-файл. Этот формат является одним из самых распространен-
ных. Корректный файл формата GIF начинается со строки ɯɰƒ. Коррек-
тен ли этот файл?

ʴʴʴ‰‹ˆƃśɭƄʰʰ„ɐ ɯɰƒɐ
”—‡

Обратите внимание: с помощью b мы можем указать, что строка состоит из байтов,


а не из символов Unicode. Вы можете сравнить байты с байтами, но не байты и сим-
волы:
ʴʴʴ‰‹ˆƃśɭƄʰʰɐ ɯɰƒɐ
ƒŽ•‡
ʴʴʴ–›’‡ſ‰‹ˆƀ
ʳ Žƒ••ɐ„›–‡•ɐʴ
ʴʴʴ–›’‡ſɐ ɯɰƒɐƀ
ʳ Žƒ••ɐ•–”ɐʴ
ʴʴʴ–›’‡ſ„ɐ ɯɰƒɐƀ
ʳ Žƒ••ɐ„›–‡•ɐʴ

12.11. Ширина GIF-файла в пикселах является шестнадцатибитным целым числом


с обратным порядком байтов, которое начинается со смещения 6 байт. Высота
имеет такой же размер и начинается со смещения 8 байт. Извлеките и выве-
дите на экран эти значения для переменной gif. Равны ли они ɨ?
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ʴʴʴ‹’‘”–•–”— –
ʴʴʴ™‹†–ŠřЇ‹‰Š–ʰ•–”— –Ŝ—’ƒ ſɐʳ ɐř‰‹ˆƃɭśɨɥƄƀ
ʴʴʴ™‹†–ŠřЇ‹‰Š–
ſɨřɨƀ

DzȈȓȍȕȌȈȘȐȐȟȈșȣ
13.1. Запишите текущие дату и время как строку в текстовый файл –‘†ƒ›Ŝ–š–.

ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡
ʴʴʴ‘™ʰ†ƒ–‡Ŝ–‘†ƒ›ſƀ
ʴʴʴ‘™ɏ•–”ʰ‘™Ŝ‹•‘ˆ‘”ƒ–ſƀ
ʴʴʴ™‹–Š‘’‡ſɐ–‘†ƒ›Ŝ–š–ɐřɐ™–ɐƀƒ•‘—–’—–ś
ŜŜŜ’”‹–ſ‘™ɏ•–”řˆ‹Ž‡ʰ‘—–’—–ƀ
ʴʴʴ

Когда я запустил этот фрагмент кода, в файле –‘†ƒ›Ŝ–š– увидел следующее:


ɩɥɨɰŞɥɮŞɩɪ

Вместо функции print вы могли бы задействовать такую строку, как ‘—–’—–Ŝ™”‹–‡ſ‘™ɏ•–”ƀ.


Использование функции print добавляет символ перевода строки в конце.

13.2. Прочтите текстовый файл –‘†ƒ›Ŝ–š– и разместите данные в строке –‘†ƒ›ɏ


string.

ʴʴʴ™‹–Š‘’‡ſɐ–‘†ƒ›Ŝ–š–ɐřɐ”–ɐƀƒ•‹’—–ś
ŜŜŜ–‘†ƒ›ɏ•–”‹‰ʰ‹’—–Ŝ”‡ƒ†ſƀ
ŜŜŜ
ʴʴʴ–‘†ƒ›ɏ•–”‹‰
ɐɩɥɨɰŞɥɮŞɩɪɎɐ

13.3. Проанализируйте дату из строки –‘†ƒ›ɏ•–”‹‰.

ʴʴʴˆ–ʰɐʩŞʩŞʩ†Ɏɐ
ʴʴʴ†ƒ–‡–‹‡Ŝ•–”’–‹‡ſ–‘†ƒ›ɏ•–”‹‰řˆ–ƀ
†ƒ–‡–‹‡Ŝ†ƒ–‡–‹‡ſɩɥɨɰřɮřɩɪřɥřɥƀ

Если вы записали тот символ новой строки в файл, то вам нужно, чтобы он совпал со
строкой формата.

13.4. Создайте объект †ƒ–‡ с датой вашего рождения.

Предположим, вы родились 14 августа 1982 года:


ʴʴʴ›ɏ†ƒ›ʰ†ƒ–‡ſɨɰɯɩřɯřɨɫƀ
ʴʴʴ›ɏ†ƒ›
†ƒ–‡–‹‡Ŝ†ƒ–‡ſɨɰɯɩřɯřɨɫƀ
  ǷȘȐȓȖȎȍȕȐȧ

13.5. В какой день недели вы родились?

ʴʴʴ›ɏ†ƒ›Ŝ™‡‡†ƒ›ſƀ
ɬ
ʴʴʴ›ɏ†ƒ›Ŝ‹•‘™‡‡†ƒ›ſƀ
6

Для ™‡‡†ƒ›ſƀ значение для понедельника равно ɥ, а для воскресенья — 6. Для функции
‹•‘™‡‡†ƒ›ſƀ значение для понедельника равно ɨ, а для воскресенья — 7. Поэтому ис-
комый день — суббота.

13.6. Когда вам будет (или уже было) 10 000 дней от роду?

ʴʴʴˆ”‘†ƒ–‡–‹‡‹’‘”––‹‡†‡Ž–ƒ
ʴʴʴ’ƒ”–›ɏ†ƒ›ʰ›ɏ†ƒ›ʫ–‹‡†‡Ž–ƒſ†ƒ›•ʰɨɥɥɥɥƀ
ʴʴʴ’ƒ”–›ɏ†ƒ›
†ƒ–‡–‹‡Ŝ†ƒ–‡ſɩɥɥɰřɨɩřɪɥƀ

Если это был ваш день рождения, то вы, возможно, пропустили еще один повод повесе-
литься.

ǼȈȑȓȣȐȒȈȚȈȓȖȋȐ
14.1. Выведите на экран список файлов текущего каталога.

Если ваш текущий каталог называется RKP\ и содержит три файла с именами по назва-
ниям животных, то код может выглядеть так:
ʴʴʴ‹’‘”–‘•
ʴʴʴ‘•ŜŽ‹•–†‹”ſɐŜɐƀ
ƃɐ„‡ƒ”•ɐřɐŽ‹‘•ɐřɐ–‹‰‡”•ɐƄ

14.2. Выведите на экран список всех файлов родительского каталога.

Если родительский каталог содержит два файла и текущий каталог RKP\, то код может
выглядеть так:
ʴʴʴ‹’‘”–‘•
ʴʴʴ‘•ŜŽ‹•–†‹”ſɐŜŜɐƀ
ƃɐ‘Š›ɐřɐ’ƒ™•ɐřɐ™Š‹•‡”•ɐƄ

14.3. Присвойте строку Š‹• is a test of the ‡‡”‰‡ › –‡š– •›•–‡ переменной –‡•–ɨ
и запишите эту переменную в файл с именем –‡•–Ŝ–š–.

ʴʴʴ–‡•–ɨʰɐŠ‹•‹•ƒ–‡•–‘ˆ–Ї‡‡”‰‡ ›–‡š–•›•–‡ɐ
ʴʴʴއſ–‡•–ɨƀ
ɫɪ
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

Вот как это можно сделать с помощью функций open, write и Ž‘•‡:
ʴʴʴ‘—–ˆ‹Ž‡ʰ‘’‡ſɐ–‡•–Ŝ–š–ɐřɐ™–ɐƀ
ʴʴʴ‘—–ˆ‹Ž‡Ŝ™”‹–‡ſ–‡•–ɨƀ
ɫɪ
ʴʴʴ‘—–ˆ‹Ž‡Ŝ Ž‘•‡ſƀ
Или можете использовать with и избежать вызова Ž‘•‡ (Python сделает это за вас):
ʴʴʴ™‹–Š‘’‡ſɐ–‡•–Ŝ–š–ɐřɐ™–ɐƀƒ•‘—–ˆ‹Ž‡ś
ŜŜŜ‘—–ˆ‹Ž‡Ŝ™”‹–‡ſ–‡•–ɨƀ
ŜŜŜ
ɫɪ

14.4. Откройте файл –‡•–Ŝ–š– и считайте его содержимое в строку –‡•–ɩ. Будут ли
одинаковыми строки –‡•–ɨ и –‡•–ɩ?

ʴʴʴ™‹–Š‘’‡ſɐ–‡•–Ŝ–š–ɐřɐ”–ɐƀƒ•‹ˆ‹Ž‡ś
ŜŜŜ–‡•–ɩʰ‹ˆ‹Ž‡Ŝ”‡ƒ†ſƀ
ŜŜŜ
ʴʴʴއſ–‡•–ɩƀ
ɫɪ
ʴʴʴ–‡•–ɨʰʰ–‡•–ɩ
”—‡

ǬȈȕȕȣȍȊȖȊȘȍȔȍȕȐȗȘȖȞȍșșȣ
ȐȒȖȕȒțȘȍȕȚȕȖșȚȤ
15.1. Используйте модуль —Ž–‹’”‘ ‡••‹‰, чтобы создать три отдельных процес-
са. Заставьте каждый из них подождать случайное количество секунд между
нулем и единицей, вывести текущее время, а затем завершить работу.

‹’‘”–—Ž–‹’”‘ ‡••‹‰

†‡ˆ‘™ſ•‡ ‘†•ƀś
ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
ˆ”‘–‹‡‹’‘”–•އ‡’
•އ‡’ſ•‡ ‘†•ƀ
’”‹–ſɐ™ƒ‹–ɐř•‡ ‘†•řɐ•‡ ‘†•ř–‹‡‹•ɐř†ƒ–‡–‹‡Ŝ—– ‘™ſƀƀ

‹ˆɏɏƒ‡ɏɏʰʰɐɏɏƒ‹ɏɏɐś
‹’‘”–”ƒ†‘
ˆ‘”‹”ƒ‰‡ſɪƀś
•‡ ‘†•ʰ”ƒ†‘Ŝ”ƒ†‘ſƀ
’”‘ ʰ—Ž–‹’”‘ ‡••‹‰Ŝ”‘ ‡••ſ–ƒ”‰‡–ʰ‘™řƒ”‰•ʰſ•‡ ‘†•řƀƀ
’”‘ Ŝ•–ƒ”–ſƀ

ɛpython multi_times.py
™ƒ‹–ɥŜɨɥɮɩɥɪɭɨɨɨɪɥɬɰɩɩɰ•‡ ‘†•ř–‹‡‹•ɩɥɨɰŞɥɮŞɩɫɥɥśɨɰśɩɪŜɰɬɨɬɰɫ
™ƒ‹–ɥŜɬɯɩɬɨɫɫɥɥɩɪɮɥɥɭɬ•‡ ‘†•ř–‹‡‹•ɩɥɨɰŞɥɮŞɩɫɥɥśɨɰśɩɫŜɫɩɬɥɫɮ
™ƒ‹–ɥŜɭɭɫɮɭɰɥɬɭɰɥɩɰɫɮɮ•‡ ‘†•ř–‹‡‹•ɩɥɨɰŞɥɮŞɩɫɥɥśɨɰśɩɫŜɬɥɰɰɰɬ
  ǷȘȐȓȖȎȍȕȐȧ

ǬȈȕȕȣȍȊȒȖȘȖȉȒȍțșȚȖȑȟȐȊȣȍȝȘȈȕȐȓȐȡȈ
16.1. Сохраните следующие несколько строк в файл „‘‘•Ŝ •˜. Обратите внимание
на то, что, если поля разделены запятыми, вам нужно заключить в кавычки
поле, содержащее запятую:
ƒ—–Š‘”ř„‘‘
‘Ž‹‡řЇ ‘„„‹–
›‡”—••řɑƒ–•řŠ‘‘–•ĺ‡ƒ˜‡•ɑ

ʴʴʴ–‡š–ʰɐɐɐƒ—–Š‘”ř„‘‘
ŜŜŜ ‘Ž‹‡řЇ ‘„„‹–
ŜŜŜ›‡”—••řɑƒ–•řŠ‘‘–•ĺ‡ƒ˜‡•ɑ
ŜŜŜɐɐɐ
ʴʴʴ™‹–Š‘’‡ſɐ–‡•–Ŝ •˜ɐřɐ™–ɐƀƒ•‘—–ˆ‹Ž‡ś
ŜŜŜ‘—–ˆ‹Ž‡Ŝ™”‹–‡ſ–‡š–ƀ
ŜŜŜ
ɮɪ

16.2. Используйте модуль •˜ и его метод ‹ –‡ƒ†‡”, чтобы считать содержимое фай-
ла „‘‘•Ŝ •˜ в переменную „‘‘•. Выведите на экран значения переменной „‘‘•.
Обработал ли метод ‹ –‡ƒ†‡” кавычки и запятые в заголовке второй книги?

ʴʴʴ™‹–Š‘’‡ſɐ„‘‘•Ŝ •˜ɐřɐ”–ɐƀƒ•‹ˆ‹Ž‡ś
ŜŜŜ„‘‘•ʰ •˜Ŝ‹ –‡ƒ†‡”ſ‹ˆ‹Ž‡ƀ
ŜŜŜˆ‘”„‘‘‹„‘‘•ś
ŜŜŜ’”‹–ſ„‘‘ƀ
ŜŜŜ
Ƈɐ„‘‘ɐśɐЇ ‘„„‹–ɐřɐƒ—–Š‘”ɐśɐ ‘Ž‹‡ɐƈ
Ƈɐ„‘‘ɐśɐƒ–•řŠ‘‘–•ĺ‡ƒ˜‡•ɐřɐƒ—–Š‘”ɐśɐ›‡”—••ɐƈ

16.3. Создайте CSV-файл „‘‘•Ŝ •˜ и запишите его в следующие строки.


–‹–އřƒ—–Š‘”ř›‡ƒ”
Ї‡‹”†•–‘‡‘ˆ”‹•‹‰ƒ‡řŽƒ ƒ”‡”řɨɰɭɥ
‡”†‹†‘–”‡‡––ƒ–‹‘řŠ‹ƒ‹²˜‹ŽŽ‡řɩɥɥɥ
Š—†Šř‡””›”ƒ– Ї––řɩɥɥɬ
Ї’‡ŽŽƒ ‹Ž‡•ř‹•ƒ—–œřɩɥɥɮ
ƒŽŽ ‘†•ř‡””›”ƒ– Ї––řɨɰɰɩ

ʴʴʴ–‡š–ʰɐɐɐ–‹–އřƒ—–Š‘”ř›‡ƒ”
ŜŜŜЇ‡‹”†•–‘‡‘ˆ”‹•‹‰ƒ‡řŽƒ ƒ”‡”řɨɰɭɥ
ŜŜŜ‡”†‹†‘–”‡‡––ƒ–‹‘řŠ‹ƒ‹²˜‹ŽŽ‡řɩɥɥɥ
ŜŜŜŠ—†Šř‡””›”ƒ– Ї––řɩɥɥɬ
ŜŜŜЇ’‡ŽŽƒ ‹Ž‡•ř‹•ƒ—–œřɩɥɥɮ
ŜŜŜƒŽŽ ‘†•ř‡””›”ƒ– Ї––řɨɰɰɩ
ŜŜŜɐɐɐ
ʴʴʴ™‹–Š‘’‡ſɐ„‘‘•ɩŜ •˜ɐřɐ™–ɐƀƒ•‘—–ˆ‹Ž‡ś
ŜŜŜ‘—–ˆ‹Ž‡Ŝ™”‹–‡ſ–‡š–ƀ
ŜŜŜ
ɩɥɨ
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

16.4. Используйте модуль •“Ž‹–‡ɪ, чтобы создать базу данных SQLite „‘‘•Ŝ†„
и таблицу „‘‘•, содержащую следующие поля: title (текст), author (текст)
и year (целое значение).

ʴʴʴ‹’‘”–•“Ž‹–‡ɪ
ʴʴʴ†„ʰ•“Ž‹–‡ɪŜ ‘‡ –ſɐ„‘‘•Ŝ†„ɐƀ
ʴʴʴ —”•ʰ†„Ŝ —”•‘”ſƀ
ʴʴʴ —”•Ŝ‡š‡ —–‡ſɐɐɐ ”‡ƒ–‡–ƒ„އ„‘‘ſ–‹–އ–‡š–řƒ—–Š‘”–‡š–ř›‡ƒ”‹–ƀɐɐɐƀ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɭ‡ɪ„ɰɥʴ
ʴʴʴ†„Ŝ ‘‹–ſƀ

16.5. Считайте данные из файла „‘‘•ɩŜ •˜ и добавьте их в таблицу „‘‘.

ʴʴʴ‹’‘”– •˜
ʴʴʴ‹’‘”–•“Ž‹–‡ɪ
ʴʴʴ‹•ɏ•–”ʰɐ‹•‡”–‹–‘„‘‘˜ƒŽ—‡•ſţřţřţƀɐ
ʴʴʴ™‹–Š‘’‡ſɐ„‘‘•Ŝ •˜ɐřɐ”–ɐƀƒ•‹ˆ‹Ž‡ś
ŜŜŜ„‘‘•ʰ •˜Ŝ‹ –‡ƒ†‡”ſ‹ˆ‹Ž‡ƀ
ŜŜŜˆ‘”„‘‘‹„‘‘•ś
ŜŜŜ —”•Ŝ‡š‡ —–‡ſ‹•ɏ•–”řſ„‘‘ƃɐ–‹–އɐƄř„‘‘ƃɐƒ—–Š‘”ɐƄř„‘‘ƃɐ›‡ƒ”ɐƄƀƀ
ŜŜŜ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɮ„ɩɨˆɥʴ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɮ„ɩɨˆɥʴ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɮ„ɩɨˆɥʴ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɮ„ɩɨˆɥʴ
ʳ•“Ž‹–‡ɪŜ—”•‘”‘„Œ‡ –ƒ–ɥšɨɥɥɮ„ɩɨˆɥʴ
ʴʴʴ†„Ŝ ‘‹–ſƀ

16.6. Считайте и выведите на экран столбец title таблицы „‘‘ в алфавитном по-
рядке.

ʴʴʴ•“Žʰɐ•‡Ž‡ ––‹–އˆ”‘„‘‘‘”†‡”„›–‹–އƒ• ɐ
ʴʴʴˆ‘””‘™‹†„Ŝ‡š‡ —–‡ſ•“Žƀś
ŜŜŜ’”‹–ſ”‘™ƀ
ŜŜŜ
ſɐ‡”†‹†‘–”‡‡––ƒ–‹‘ɐřƀ
ſɐƒŽŽ ‘†•ɐřƀ
ſɐЇ’‡ŽŽƒ ‹Ž‡•ɐřƀ
ſɐЇ‡‹”†•–‘‡‘ˆ”‹•‹‰ƒ‡ɐřƀ
ſɐŠ—†Šɐřƀ

Если вы хотите вывести на экран значение title, не пользуясь конструкциями для ра-
боты с кортежем (круглыми скобками и запятой), то попробуйте следующее:
ʴʴʴˆ‘””‘™‹†„Ŝ‡š‡ —–‡ſ•“Žƀś
ŜŜŜ’”‹–ſ”‘™ƃɥƄƀ
ŜŜŜ
‡”†‹†‘–”‡‡––ƒ–‹‘
ƒŽŽ ‘†•
Ї’‡ŽŽƒ ‹Ž‡•
  ǷȘȐȓȖȎȍȕȐȧ

Ї‡‹”†•–‘‡‘ˆ”‹•‹‰ƒ‡
Š—†Š

Если хотите проигнорировать начальное слово ɐЇɐ в заголовках, то вам нужно напи-
сать еще одну строку SQL:
ʴʴʴ•“Žʰɐɐɐ•‡Ž‡ ––‹–އˆ”‘„‘‘‘”†‡”„›
ŜŜŜ ƒ•‡™Š‡ſ–‹–އŽ‹‡ɑЇʩɑƀ
ŜŜŜ–Ї•—„•–”ſ–‹–އřɬƀ
ŜŜŜ‡Ž•‡–‹–އ‡†ɐɐɐ
ʴʴʴˆ‘””‘™‹†„Ŝ‡š‡ —–‡ſ•“Žƀś
ŜŜŜ’”‹–ſ”‘™ƃɥƄƀ
ŜŜŜ
‡”†‹†‘–”‡‡––ƒ–‹‘
ƒŽŽ ‘†•
Ї’‡ŽŽƒ ‹Ž‡•
Š—†Š
Ї‡‹”†•–‘‡‘ˆ”‹•‹‰ƒ‡

16.7. Считайте и выведите на экран все столбцы таблицы „‘‘ в порядке публикации.

ʴʴʴˆ‘””‘™‹†„Ŝ‡š‡ —–‡ſɐ•‡Ž‡ –Ƌˆ”‘„‘‘‘”†‡”„››‡ƒ”ɐƀś


ŜŜŜ’”‹–ſ”‘™ƀ
ŜŜŜ
ſɐЇ‡‹”†•–‘‡‘ˆ”‹•‹‰ƒ‡ɐřɐŽƒ ƒ”‡”ɐřɨɰɭɥƀ
ſɐƒŽŽ ‘†•ɐřɐ‡””›”ƒ– Ї––ɐřɨɰɰɩƀ
ſɐ‡”†‹†‘–”‡‡––ƒ–‹‘ɐřɐŠ‹ƒ‹²˜‹ŽŽ‡ɐřɩɥɥɥƀ
ſɐŠ—†Šɐřɐ‡””›”ƒ– Ї––ɐřɩɥɥɬƀ
ſɐЇ’‡ŽŽƒ ‹Ž‡•ɐřɐ‹•ƒ—–œɐřɩɥɥɮƀ

Чтобы вывести на экран все столбцы каждой строки, просто разделите их запятой
и пробелом:
ʴʴʴˆ‘””‘™‹†„Ŝ‡š‡ —–‡ſɐ•‡Ž‡ –Ƌˆ”‘„‘‘‘”†‡”„››‡ƒ”ɐƀś
ŜŜŜ’”‹–ſƋ”‘™ř•‡’ʰɐřɐƀ
ŜŜŜ
Ї‡‹”†•–‘‡‘ˆ”‹•‹‰ƒ‡řŽƒ ƒ”‡”řɨɰɭɥ
ƒŽŽ ‘†•ř‡””›”ƒ– Ї––řɨɰɰɩ
‡”†‹†‘–”‡‡––ƒ–‹‘řŠ‹ƒ‹²˜‹ŽŽ‡řɩɥɥɥ
Š—†Šř‡””›”ƒ– Ї––řɩɥɥɬ
Ї’‡ŽŽƒ ‹Ž‡•ř‹•ƒ—–œřɩɥɥɮ

16.8. Используйте модуль •“ŽƒŽ Š‡›, чтобы подключиться к базе данных •“Ž‹–‡ɪ
„‘‘•Ŝ†„, которую вы создали в упражнении 16.4. Как и в упражнении 16.6,
считайте и выведите на экран столбец title таблицы „‘‘ в алфавитном по-
рядке.

ʴʴʴ‹’‘”–•“ŽƒŽ Š‡›
ʴʴʴ ‘ʰ•“ŽƒŽ Š‡›Ŝ ”‡ƒ–‡ɏ‡‰‹‡ſɐ•“Ž‹–‡śŵŵŵ„‘‘•Ŝ†„ɐƀ
ʴʴʴ•“Žʰɐ•‡Ž‡ ––‹–އˆ”‘„‘‘‘”†‡”„›–‹–އƒ• ɐ
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ʴʴʴ”‘™•ʰ ‘Ŝ‡š‡ —–‡ſ•“Žƀ


ʴʴʴˆ‘””‘™‹”‘™•ś
ŜŜŜ’”‹–ſ”‘™ƀ
ŜŜŜ
ſɐ‡”†‹†‘–”‡‡––ƒ–‹‘ɐřƀ
ſɐƒŽŽ ‘†•ɐřƀ
ſɐЇ’‡ŽŽƒ ‹Ž‡•ɐřƀ
ſɐЇ‡‹”†•–‘‡‘ˆ”‹•‹‰ƒ‡ɐřƀ
ſɐŠ—†Šɐřƀ

16.9. Установите сервер Redis и библиотеку Python ”‡†‹• (с помощью команды pip
install ”‡†‹•) на свой компьютер. Создайте хеш redis с именем test, содержа-
щий поля ‘—–ſɨƀ и ƒ‡ſɐ ‡•–‡” ‡•–‡”–‡•–‡”ɐƀ. Выведите все поля хеша test.

ʴʴʴ‹’‘”–”‡†‹•
ʴʴʴ ‘ʰ”‡†‹•Ŝ‡†‹•ſƀ
ʴʴʴ ‘Ŝ†‡Ž‡–‡ſɐ–‡•–ɐƀ
ɨ
ʴʴʴ ‘ŜŠ•‡–ſɐ–‡•–ɐřƇɐ ‘—–ɐśɨřɐƒ‡ɐśɐ ‡•–‡”‡•–‡”–‡•–‡”ɐƈƀ
”—‡
ʴʴʴ ‘ŜЉ‡–ƒŽŽſɐ–‡•–ɐƀ
Ƈ„ɐƒ‡ɐś„ɐ ‡•–‡”‡•–‡”–‡•–‡”ɐř„ɐ ‘—–ɐś„ɐɨɐƈ

16.10. Увеличьте поле ‘—– хеша test и выведите его на экран.

ʴʴʴ ‘ŜŠ‹ ”„›ſɐ–‡•–ɐřɐ ‘—–ɐřɪƀ


ɫ
ʴʴʴ ‘ŜЉ‡–ſɐ–‡•–ɐřɐ ‘—–ɐƀ
„ɐɫɐ

ǬȈȕȕȣȍȊȗȘȖșȚȘȈȕșȚȊȍșȍȚȐ
17.1. Используйте объект класса •‘ ‡–, чтобы реализовать сервис, сообщающий
текущее время. Когда клиент отправляет на сервер строку ɐ–‹‡ɐ, верните
текущие дату и время как строку ISO.

Вот так можно написать сервер —†’ɏ–‹‡ɏ•‡”˜‡”Ŝ’›:


ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
‹’‘”–•‘ ‡–

ƒ††”‡••ʰſɐŽ‘ ƒŽŠ‘•–ɐřɭɮɯɰƀ
ƒšɏ•‹œ‡ʰɫɥɰɭ

’”‹–ſɐ–ƒ”–‹‰–Ї•‡”˜‡”ƒ–ɐř†ƒ–‡–‹‡Ŝ‘™ſƀƀ
’”‹–ſɐƒ‹–‹‰ˆ‘”ƒ Ž‹‡––‘ ƒŽŽŜɐƀ
  ǷȘȐȓȖȎȍȕȐȧ

•‡”˜‡”ʰ•‘ ‡–Ŝ•‘ ‡–ſ•‘ ‡–Ŝ ɏ ř•‘ ‡–Ŝɏ ƀ


•‡”˜‡”Ŝ„‹†ſƒ††”‡••ƀ
™Š‹Ž‡”—‡ś
†ƒ–ƒř Ž‹‡–ɏƒ††”ʰ•‡”˜‡”Ŝ”‡ ˜ˆ”‘ſƒšɏ•‹œ‡ƀ
‹ˆ†ƒ–ƒʰʰ„ɐ–‹‡ɐś
‘™ʰ•–”ſ†ƒ–‡–‹‡Ŝ—– ‘™ſƀƀ
†ƒ–ƒʰ‘™Ŝ‡ ‘†‡ſɐ—–ˆŞɯɐƀ
•‡”˜‡”Ŝ•‡†–‘ſ†ƒ–ƒř Ž‹‡–ɏƒ††”ƀ
’”‹–ſɐ‡”˜‡”•‡–ɐř†ƒ–ƒƀ
•‡”˜‡”Ŝ Ž‘•‡ſƀ

А так — клиент —†’ɏ–‹‡ɏ Ž‹‡–Ŝ’›:


‹’‘”–•‘ ‡–
ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
ˆ”‘–‹‡‹’‘”–•އ‡’

ƒ††”‡••ʰſɐŽ‘ ƒŽŠ‘•–ɐřɭɮɯɰƀ
ƒšɏ•‹œ‡ʰɫɥɰɭ

’”‹–ſɐ–ƒ”–‹‰–Ї Ž‹‡–ƒ–ɐř†ƒ–‡–‹‡Ŝ‘™ſƀƀ
Ž‹‡–ʰ•‘ ‡–Ŝ•‘ ‡–ſ•‘ ‡–Ŝ ɏ ř•‘ ‡–Ŝɏ ƀ
™Š‹Ž‡”—‡ś
•އ‡’ſɬƀ
 Ž‹‡–Ŝ•‡†–‘ſ„ɐ–‹‡ɐřƒ††”‡••ƀ
†ƒ–ƒř•‡”˜‡”ɏƒ††”ʰ Ž‹‡–Ŝ”‡ ˜ˆ”‘ſƒšɏ•‹œ‡ƀ
’”‹–ſɐŽ‹‡–”‡ƒ†ɐř†ƒ–ƒƀ
Ž‹‡–Ŝ Ž‘•‡ſƀ

Я поместил вызов •Ž‡‡’ſɬƀ в верхней части цикла клиента, чтобы сделать обмен данны-
ми менее быстрым. Запустите сервер в одном окне:
ɛpython udp_time_server.py
–ƒ”–‹‰–Ї•‡”˜‡”ƒ–ɩɥɨɫŞɥɭŞɥɩɩɥśɩɯśɫɮŜɫɨɬɨɮɭ
ƒ‹–‹‰ˆ‘”ƒ Ž‹‡––‘ ƒŽŽŜ

Запустите клиент в другом окне:


ɛpython udp_time_client.py
–ƒ”–‹‰–Ї Ž‹‡–ƒ–ɩɥɨɫŞɥɭŞɥɩɩɥśɩɯśɬɨŜɫɬɫɯɥɬ

Через 5 секунд вы начнете видеть сообщения в обоих окнах. Так выглядят первые
три строки от сервера:
‡”˜‡”•‡–„ɐɩɥɨɫŞɥɭŞɥɪɥɨśɩɯśɬɭŜɫɭɩɬɭɬɐ
‡”˜‡”•‡–„ɐɩɥɨɫŞɥɭŞɥɪɥɨśɩɰśɥɨŜɫɭɪɰɥɭɐ
‡”˜‡”•‡–„ɐɩɥɨɫŞɥɭŞɥɪɥɨśɩɰśɥɭŜɫɭɬɯɥɩɐ

А так — первые три строки от клиента:


Ž‹‡–”‡ƒ†„ɐɩɥɨɫŞɥɭŞɥɪɥɨśɩɯśɬɭŜɫɭɩɬɭɬɐ
Ž‹‡–”‡ƒ†„ɐɩɥɨɫŞɥɭŞɥɪɥɨśɩɰśɥɨŜɫɭɪɰɥɭɐ
Ž‹‡–”‡ƒ†„ɐɩɥɨɫŞɥɭŞɥɪɥɨśɩɰśɥɭŜɫɭɬɯɥɩɐ

Обе программы работают вечно, поэтому вам нужно завершать их вручную.


ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

17.2. Задействуйте сокеты ZeroMQ REQ и REP, чтобы сделать то же самое.

‹’‘”–œ“
ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
Š‘•–ʰɐɨɩɮŜɥŜɥŜɨɐ
’‘”–ʰɭɮɯɰ
‘–‡š–ʰœ“Ŝ‘–‡š–ſƀ
•‡”˜‡”ʰ ‘–‡š–Ŝ•‘ ‡–ſœ“Ŝƀ
•‡”˜‡”Ŝ„‹†ſɑ– ’śŵŵʩ•śʩ•ɑʩſŠ‘•–ř’‘”–ƀƀ
’”‹–ſɐ‡”˜‡”•–ƒ”–‡†ƒ–ɐř†ƒ–‡–‹‡Ŝ—– ‘™ſƀƀ
™Š‹Ž‡”—‡ś
ɤȢȚȜȘȔșȠȥȟșȘȧȲȭșȗȢțȔȣȤȢȥȔȢȦȞȟȜșȡȦȔ
‡••ƒ‰‡ʰ•‡”˜‡”Ŝ”‡ ˜ſƀ
‹ˆ‡••ƒ‰‡ʰʰ„ɐ–‹‡ɐś
‘™ʰ†ƒ–‡–‹‡Ŝ—– ‘™ſƀ
”‡’Ž›ʰ•–”ſ‘™ƀ
•‡”˜‡”Ŝ•‡†ſ„›–‡•ſ”‡’Ž›řɐ—–ˆŞɯɐƀƀ
’”‹–ſɐ‡”˜‡”•‡–ɐř”‡’Ž›ƀ

‹’‘”–œ“
ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
ˆ”‘–‹‡‹’‘”–•އ‡’

Š‘•–ʰɐɨɩɮŜɥŜɥŜɨɐ
’‘”–ʰɭɮɯɰ
‘–‡š–ʰœ“Ŝ‘–‡š–ſƀ
Ž‹‡–ʰ ‘–‡š–Ŝ•‘ ‡–ſœ“Ŝƀ
Ž‹‡–Ŝ ‘‡ –ſɑ– ’śŵŵʩ•śʩ•ɑʩſŠ‘•–ř’‘”–ƀƀ
’”‹–ſɐŽ‹‡–•–ƒ”–‡†ƒ–ɐř†ƒ–‡–‹‡Ŝ—– ‘™ſƀƀ
™Š‹Ž‡”—‡ś
•އ‡’ſɬƀ
”‡“—‡•–ʰ„ɐ–‹‡ɐ
 Ž‹‡–Ŝ•‡†ſ”‡“—‡•–ƀ
”‡’Ž›ʰ Ž‹‡–Ŝ”‡ ˜ſƀ
’”‹–ſɑŽ‹‡–”‡ ‡‹˜‡†ʩ•ɑʩ”‡’Ž›ƀ

Для простых сокетов вам нужно сначала запустить сервер. С помощью ZeroMQ вы мо-
жете запустить первым как клиент, так и сервер:
ɛpython zmq_time_server.py
‡”˜‡”•–ƒ”–‡†ƒ–ɩɥɨɫŞɥɭŞɥɪɥɨśɪɰśɪɭŜɰɪɪɬɪɩ
ɛpython zmq_time_client.py
Ž‹‡–•–ƒ”–‡†ƒ–ɩɥɨɫŞɥɭŞɥɪɥɨśɪɰśɫɩŜɬɪɯɩɫɬ

Через 15 секунд вы должны увидеть сообщения от сервера:


‡”˜‡”•‡–ɩɥɨɫŞɥɭŞɥɪɥɨśɪɰśɫɮŜɬɪɰɯɮɯ
‡”˜‡”•‡–ɩɥɨɫŞɥɭŞɥɪɥɨśɪɰśɬɩŜɬɫɥɭɬɰ
‡”˜‡”•‡–ɩɥɨɫŞɥɭŞɥɪɥɨśɪɰśɬɮŜɬɫɨɫɥɪ

Эти строки вы должны увидеть в сообщении от клиента:


Ž‹‡–”‡ ‡‹˜‡†„ɐɩɥɨɫŞɥɭŞɥɪɥɨśɪɰśɫɮŜɬɪɰɯɮɯɐ
Ž‹‡–”‡ ‡‹˜‡†„ɐɩɥɨɫŞɥɭŞɥɪɥɨśɪɰśɬɩŜɬɫɥɭɬɰɐ
Ž‹‡–”‡ ‡‹˜‡†„ɐɩɥɨɫŞɥɭŞɥɪɥɨśɪɰśɬɮŜɬɫɨɫɥɪɐ
  ǷȘȐȓȖȎȍȕȐȧ

17.3. Попробуйте сделать то же самое с помощью XMLRPC.

С сервера:
ˆ”‘šŽ”’ Ŝ•‡”˜‡”‹’‘”–‹’އ‡”˜‡”

†‡ˆ‘™ſƀś
ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
†ƒ–ƒʰ•–”ſ†ƒ–‡–‹‡Ŝ—– ‘™ſƀƀ
’”‹–ſɐ‡”˜‡”•‡–ɐř†ƒ–ƒƀ
”‡–—”†ƒ–ƒ

•‡”˜‡”ʰ‹’އ‡”˜‡”ſſɑŽ‘ ƒŽŠ‘•–ɑřɭɮɯɰƀƀ
•‡”˜‡”Ŝ”‡‰‹•–‡”ɏˆ— –‹‘ſ‘™řɑ‘™ɑƀ
•‡”˜‡”Ŝ•‡”˜‡ɏˆ‘”‡˜‡”ſƀ

С клиента:
‹’‘”–šŽ”’ Ŝ Ž‹‡–
ˆ”‘–‹‡‹’‘”–•އ‡’

’”‘š›ʰšŽ”’ Ŝ Ž‹‡–Ŝ‡”˜‡””‘š›ſɑŠ––’śŵŵŽ‘ ƒŽŠ‘•–śɭɮɯɰŵɑƀ


™Š‹Ž‡”—‡ś
•އ‡’ſɬƀ
†ƒ–ƒʰ’”‘š›Ŝ‘™ſƀ
’”‹–ſɐŽ‹‡–”‡ ‡‹˜‡†ɐř†ƒ–ƒƀ

Запустим сервер:
ɛpython xmlrpc_time_server.py

Запустим клиент:
ɛpython xmlrpc_time_client.py

Подождите примерно 15 секунд. Так выглядят первые три строки от сервера:


‡”˜‡”•‡–ɩɥɨɫŞɥɭŞɥɪɥɩśɨɫśɬɩŜɩɰɰɨɩɩ
ɨɩɮŜɥŜɥŜɨŞŞƃɥɩŵ —ŵɩɥɨɫɩɨśɨɫśɬɩƄɑŵ ŵɨŜɨɑɩɥɥŞ
‡”˜‡”•‡–ɩɥɨɫŞɥɭŞɥɪɥɩśɨɫśɬɮŜɪɥɫɮɫɨ
ɨɩɮŜɥŜɥŜɨŞŞƃɥɩŵ —ŵɩɥɨɫɩɨśɨɫśɬɮƄɑŵ ŵɨŜɨɑɩɥɥŞ
‡”˜‡”•‡–ɩɥɨɫŞɥɭŞɥɪɥɩśɨɬśɥɩŜɪɨɥɪɮɮ
ɨɩɮŜɥŜɥŜɨŞŞƃɥɩŵ —ŵɩɥɨɫɩɨśɨɬśɥɩƄɑŵ ŵɨŜɨɑɩɥɥŞ

А так — первые три строки от клиента:


Ž‹‡–”‡ ‡‹˜‡†ɩɥɨɫŞɥɭŞɥɪɥɩśɨɫśɬɩŜɩɰɰɨɩɩ
Ž‹‡–”‡ ‡‹˜‡†ɩɥɨɫŞɥɭŞɥɪɥɩśɨɫśɬɮŜɪɥɫɮɫɨ
Ž‹‡–”‡ ‡‹˜‡†ɩɥɨɫŞɥɭŞɥɪɥɩśɨɬśɥɩŜɪɨɥɪɮɮ

17.4. Возможно, вы видели эпизод телесериала I Love Lucy, в котором Люси и Этель
работают на шоколадной фабрике. Парочка стала отставать, когда линия конвейе-
ра, направлявшая к ним на обработку конфеты, еще более ускорилась. Напишите
симуляцию, которая отправляет разные типы конфет в список Redis, и клиент
Lucy, делающий блокирующие выталкивания из списка. Ей нужно 0,5 секунды,
чтобы обработать одну конфету. Выведите на экран время и тип каждой конфеты,
которую получит Lucy, а также количество необработанных конфет:
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

Симуляция ”‡†‹•ɏ Š‘ ɏ•—’’Ž›Ŝ’› передает бесконечное количество конфет:


‹’‘”–”‡†‹•
‹’‘”–”ƒ†‘
ˆ”‘–‹‡‹’‘”–•އ‡’

‘ʰ”‡†‹•Ŝ‡†‹•ſƀ
˜ƒ”‹‡–‹‡•ʰƃɐ–”—ˆˆŽ‡ɐřɐ Ї””›ɐřɐ ƒ”ƒ‡Žɐřɐ‘—‰ƒ–ɐƄ
‘˜‡›‘”ʰɐ Š‘ ‘Žƒ–‡•ɐ
™Š‹Ž‡”—‡ś
•‡ ‘†•ʰ”ƒ†‘Ŝ”ƒ†‘ſƀ
•އ‡’ſ•‡ ‘†•ƀ
’‹‡ ‡ʰ”ƒ†‘Ŝ Š‘‹ ‡ſ˜ƒ”‹‡–‹‡•ƀ
 ‘Ŝ”’—•Šſ ‘˜‡›‘”ř’‹‡ ‡ƀ

Клиент ”‡†‹•ɏŽ— ›Ŝ’› может выглядеть так:


‹’‘”–”‡†‹•
ˆ”‘†ƒ–‡–‹‡‹’‘”–†ƒ–‡–‹‡
ˆ”‘–‹‡‹’‘”–•އ‡’

‘ʰ”‡†‹•Ŝ‡†‹•ſƀ
–‹‡‘—–ʰɨɥ
‘˜‡›‘”ʰɐ Š‘ ‘Žƒ–‡•ɐ
™Š‹Ž‡”—‡ś
•އ‡’ſɥŜɬƀ
•‰ʰ ‘Ŝ„Ž’‘’ſ ‘˜‡›‘”ř–‹‡‘—–ƀ
”‡ƒ‹‹‰ʰ ‘ŜŽŽ‡ſ ‘˜‡›‘”ƀ
‹ˆ•‰ś
’‹‡ ‡ʰ•‰ƃɨƄ
’”‹–ſɐ— ›‰‘–ƒɐř’‹‡ ‡řɐƒ–ɐř†ƒ–‡–‹‡Ŝ—– ‘™ſƀř
ɐř‘Ž›ɐř”‡ƒ‹‹‰řɐއˆ–ɐƀ

Запустите их в любом порядке. Поскольку Люси требуется 0,5 секунды для обработки
каждой конфеты и они появляются в среднем каждые 0,5 секунды, это становится по-
хоже на гонку. Чем раньше вы запустите конвейер, тем более сложной сделаете жизнь
Люси:
ɛpython redis_choc_supply.py &

ɛpython redis_lucy.py
— ›‰‘–ƒ„ɐ‘—‰ƒ–ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɥɯŜɮɩɨɨɭɰř‘Ž›ɫއˆ–
— ›‰‘–ƒ„ɐ Ї””›ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɥɰŜɩɩɩɯɨɭř‘Ž›ɪއˆ–
— ›‰‘–ƒ„ɐ–”—ˆˆŽ‡ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɥɰŜɮɩɪɭɰɨř‘Ž›ɬއˆ–
— ›‰‘–ƒ„ɐ–”—ˆˆŽ‡ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɨɥŜɩɩɬɥɥɯř‘Ž›ɫއˆ–
— ›‰‘–ƒ„ɐ Ї””›ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɨɥŜɮɩɮɨɥɮř‘Ž›ɫއˆ–
— ›‰‘–ƒ„ɐ Ї””›ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɨɨŜɩɩɯɩɩɭř‘Ž›ɬއˆ–
— ›‰‘–ƒ„ɐ Ї””›ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɨɨŜɮɩɰɮɪɬř‘Ž›ɫއˆ–
— ›‰‘–ƒ„ɐ–”—ˆˆŽ‡ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɨɩŜɩɪɥɯɰɫř‘Ž›ɭއˆ–
— ›‰‘–ƒ„ɐ ƒ”ƒ‡Žɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɨɩŜɮɪɩɮɮɮř‘Ž›ɮއˆ–
— ›‰‘–ƒ„ɐ Ї””›ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɨɪŜɩɪɫɮɯɬř‘Ž›ɭއˆ–
— ›‰‘–ƒ„ɐ Ї””›ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɨɪŜɮɪɭɨɥɪř‘Ž›ɮއˆ–
— ›‰‘–ƒ„ɐ ƒ”ƒ‡Žɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɨɫŜɩɪɯɨɬɩř‘Ž›ɰއˆ–
— ›‰‘–ƒ„ɐ Ї””›ɐƒ–ɩɥɨɫŞɥɭŞɥɪɥɪśɨɬśɨɫŜɮɪɰɬɭɨř‘Ž›ɯއˆ–

Бедная Люси.
  ǷȘȐȓȖȎȍȕȐȧ

17.5. Используйте ZeroMQ, чтобы публиковать стихотворение из упражнения 12.4


(пример 12.1) по одному слову за раз. Напишите потребитель ZeroMQ, кото-
рый будет выводить на экран каждое слово, начинающееся с гласной. Напи-
шите другой потребитель, который станет выводить все слова, состоящие из
пяти букв. Знаки препинания игнорируйте.

Так выглядит сервер ’‘‡ɏ’—„Ŝ’›, который отщипывает по одному слову стихотворения


и публикует его в тему vowels, если оно начинается с гласной, и в тему five, если состо-
ит из пяти букв. Одни слова могут оказаться в обеих темах, другие — ни в одной:
‹’‘”–•–”‹‰
‹’‘”–œ“

Š‘•–ʰɐɨɩɮŜɥŜɥŜɨɐ
’‘”–ʰɭɮɯɰ
–šʰœ“Ŝ‘–‡š–ſƀ
’—„ʰ –šŜ•‘ ‡–ſœ“Ŝƀ
’—„Ŝ„‹†ſɐ– ’śŵŵʩ•śʩ•ɐʩſŠ‘•–ř’‘”–ƀƀ

™‹–Š‘’‡ſɐƒ‘–ŠŜ–š–ɐřɐ”–ɐƀƒ•’‘‡ś
™‘”†•ʰ’‘‡Ŝ”‡ƒ†ſƀ
ˆ‘”™‘”†‹™‘”†•Ŝ•’Ž‹–ſƀś
™‘”†ʰ™‘”†Ŝ•–”‹’ſ•–”‹‰Ŝ’— –—ƒ–‹‘ƀ
†ƒ–ƒʰ™‘”†Ŝ‡ ‘†‡ſɐ—–ˆŞɯɐƀ
‹ˆ™‘”†Ŝ•–ƒ”–•™‹–Šſſɐƒɐřɐ‡ɐřɐ‹ɐřɐ‘ɐřɐ—ɐřɐɐřɐ‡ɐřɐ‹ɐřɐ‘ɐřɐ—ɐƀƀś
’—„Ŝ•‡†ɏ—Ž–‹’ƒ”–ſƃ„ɐ˜‘™‡Ž•ɐř†ƒ–ƒƄƀ
‹ˆއſ™‘”†ƀʰʰɬś
’—„Ŝ•‡†ɏ—Ž–‹’ƒ”–ſƃ„ɐˆ‹˜‡ɐř†ƒ–ƒƄƀ

Клиент ’‘‡ɏ•—„Ŝ’› подписывается на темы vowels и five и выводит на экран тему и слово:
‹’‘”–•–”‹‰
‹’‘”–œ“

Š‘•–ʰɐɨɩɮŜɥŜɥŜɨɐ
’‘”–ʰɭɮɯɰ
–šʰœ“Ŝ‘–‡š–ſƀ
•—„ʰ –šŜ•‘ ‡–ſœ“Ŝƀ
•—„Ŝ ‘‡ –ſɐ– ’śŵŵʩ•śʩ•ɐʩſŠ‘•–ř’‘”–ƀƀ
•—„Ŝ•‡–•‘ ‘’–ſœ“Ŝ ř„ɐ˜‘™‡Ž•ɐƀ
•—„Ŝ•‡–•‘ ‘’–ſœ“Ŝ ř„ɐˆ‹˜‡ɐƀ
™Š‹Ž‡”—‡ś
–‘’‹ ř™‘”†ʰ•—„Ŝ”‡ ˜ɏ—Ž–‹’ƒ”–ſƀ
’”‹–ſ–‘’‹ ř™‘”†ƀ

Если вы запустите эти программы, то они не будут работать, хотя код выглядит хорошо.
Вам нужно прочитать руководство ZeroMQ (KWWS]JXLGH]HURPTRUJSDJHDOO), чтобы
узнать о проблеме медленного присоединившегося: даже если вы запустите клиент рань-
ше сервера, тот начнет отправлять данные сразу после запуска, а клиенту потребуется
некоторое время, чтобы подключиться к серверу. Если вы публикуете сообщения посто-
янным потоком и не задумываетесь о том, когда к вам подключаются подписчики, то это
не проблема. Но в таком случае поток данных настолько короткий, что заканчивается
еще до того, как подписчик успеет моргнуть.
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

Простейший способ исправить это — заставить публикатор пропустить секунду после


вызова метода „‹†ſƀ и до того, как он начнет отправлять сообщения. Назовем данную
версию ’‘‡ɏ’—„ɏ•އ‡’Ŝ’›:
‹’‘”–•–”‹‰
‹’‘”–œ“
ˆ”‘–‹‡‹’‘”–•އ‡’

Š‘•–ʰɐɨɩɮŜɥŜɥŜɨɐ
’‘”–ʰɭɮɯɰ
–šʰœ“Ŝ‘–‡š–ſƀ
’—„ʰ –šŜ•‘ ‡–ſœ“Ŝƀ
’—„Ŝ„‹†ſɐ– ’śŵŵʩ•śʩ•ɐʩſŠ‘•–ř’‘”–ƀƀ

•އ‡’ſɨƀ

™‹–Š‘’‡ſɐƒ‘–ŠŜ–š–ɐřɐ”–ɐƀƒ•’‘‡ś
™‘”†•ʰ’‘‡Ŝ”‡ƒ†ſƀ
ˆ‘”™‘”†‹™‘”†•Ŝ•’Ž‹–ſƀś
™‘”†ʰ™‘”†Ŝ•–”‹’ſ•–”‹‰Ŝ’— –—ƒ–‹‘ƀ
†ƒ–ƒʰ™‘”†Ŝ‡ ‘†‡ſɐ—–ˆŞɯɐƀ
‹ˆ™‘”†Ŝ•–ƒ”–•™‹–Šſſɐƒɐřɐ‡ɐřɐ‹ɐřɐ‘ɐřɐ—ɐřɐɐřɐ‡ɐřɐ‹ɐřɐ‘ɐřɐ—ɐƀƀś
’”‹–ſɐ˜‘™‡Ž•ɐř†ƒ–ƒƀ
’—„Ŝ•‡†ɏ—Ž–‹’ƒ”–ſƃ„ɐ˜‘™‡Ž•ɐř†ƒ–ƒƄƀ
‹ˆއſ™‘”†ƀʰʰɬś
’”‹–ſɐˆ‹˜‡ɐř†ƒ–ƒƀ
’—„Ŝ•‡†ɏ—Ž–‹’ƒ”–ſƃ„ɐˆ‹˜‡ɐř†ƒ–ƒƄƀ

Запустите подписчик, а затем и «сонный» публикатор:


ɛpython poem_sub.py

ɛpython poem_pub_sleep.py

Теперь у подписчика есть время на то, чтобы получить сообщения по выбранным темам.
Так выглядят первые строки выходной информации:
„ɐˆ‹˜‡ɐ„ɐ“—‡‡ɐ
„ɐ˜‘™‡Ž•ɐ„ɐ‘ˆɐ
„ɐˆ‹˜‡ɐ„ɐ›‹‰ɐ
„ɐ˜‘™‡Ž•ɐ„ɐƒ–ɐ
„ɐ˜‘™‡Ž•ɐ„ɐ‡ƒ•‡ɐ
„ɐ˜‘™‡Ž•ɐ„ɐ‡˜‡‹‰ɐ
„ɐˆ‹˜‡ɐ„ɐˆŽ‹‡•ɐ
„ɐˆ‹˜‡ɐ„ɐ•‡‹œ‡ɐ
„ɐ˜‘™‡Ž•ɐ„ɐŽŽɐ
„ɐˆ‹˜‡ɐ„ɐ‰ƒ‹Ž›ɐ
„ɐˆ‹˜‡ɐ„ɐ‰”‡ƒ–ɐ
„ɐ˜‘™‡Ž•ɐ„ɐƒ†‹”‡†ɐ

Если вы не можете добавить вызов •Ž‡‡’ſƀ в код публикатора, то синхронизируйте


публикатор и подписчик с помощью сокетов  и . Примеры файлов ’—„Ž‹•Ї”Ŝ’›
и •—„• ”‹„‡”Ŝ’› вы можете найти на GitHub (KWWSELWO\S\]PTJK).
  ǷȘȐȓȖȎȍȕȐȧ

ǸȈșȗțȚȣȊȈȍȔǪșȍȔȐȘȕțȦȗȈțȚȐȕț
18.1. Если вы еще не установили Flask, то сделайте это сейчас. Это также позволит
установить ™‡”œ‡—‰, Œ‹Œƒɩ и, возможно, другие пакеты.
18.2. Создайте скелет сайта с помощью веб-сервера Flask. Убедитесь, что сервер
начинает свою работу по адресу ‘ ƒŽŠ‘•– на стандартном порте 5000. Если
ваш компьютер уже использует этот порт для чего-то еще, то воспользуйтесь
другим портом.

Так выглядит файл ˆŽƒ•ɨŜ’›:


ˆ”‘ˆŽƒ•‹’‘”– Žƒ•

ƒ’’ʰ Žƒ•ſɏɏƒ‡ɏɏƀ

ƒ’’Ŝ”—ſ’‘”–ʰɬɥɥɥř†‡„—‰ʰ”—‡ƀ
Поехали:
ɛpython [Link]
Ƌ—‹‰‘Š––’śŵŵɨɩɮŜɥŜɥŜɨśɬɥɥɥŵ
Ƌ‡•–ƒ”–‹‰™‹–Š”‡Ž‘ƒ†‡”

18.3. Добавьте функцию Š‘‡ſƀ для обработки запросов к главной странице. Пусть
она возвращает строку –ɐ• ƒŽ‹˜‡Š.

Как нам назвать этот файл, ˆŽƒ•ɩŜ’›?


ˆ”‘ˆŽƒ•‹’‘”– Žƒ•

ƒ’’ʰ Žƒ•ſɏɏƒ‡ɏɏƀ

ɒƒ’’Ŝ”‘—–‡ſɐŵɐƀ
†‡ˆŠ‘‡ſƀś
”‡–—”ɑ –ɐ•ƒŽ‹˜‡Šɑ

ƒ’’Ŝ”—ſ†‡„—‰ʰ”—‡ƀ
Запустим сервер:
ɛpython [Link]
Ƌ—‹‰‘Š––’śŵŵɨɩɮŜɥŜɥŜɨśɬɥɥɥŵ
Ƌ‡•–ƒ”–‹‰™‹–Š”‡Ž‘ƒ†‡”
Наконец, получим доступ к главной странице через браузер, HTTP-программы команд-
ной строки, такие как —”Ž, или wget, или даже telnet:
ɛcurl [Link]
–ɐ•ƒŽ‹˜‡Š

18.4. Создайте шаблон для Œ‹Œƒɩ, который называется Š‘‡ŜŠ–Ž и содержит сле-
дующий контент:
ʳŠ–Žʴ
ʳЇƒ†ʴ
ǷȘȐȓȖȎȍȕȐȍǫǶȚȊȍȚȣȒțȗȘȈȎȕȍȕȐȧȔ  

ʳ–‹–އʴ –ɐ•ƒŽ‹˜‡Šʳŵ–‹–އʴ
ʳ„‘†›ʴ
ɐ‘ˆ ‘—”•‡”‡ˆ‡””‹‰–‘ƇƇ–Š‹‰ƈƈř™Š‹ Š‹•ƇƇЇ‹‰Š–ƈƈˆ‡‡––ƒŽŽƒ†
ƇƇ ‘Ž‘”ƈƈŜ
ʳŵ„‘†›ʴ
ʳŵŠ–Žʴ

Создайте каталог –‡’Žƒ–‡• и файл Š‘‡ŜŠ–Ž, содержащий показанное. Если ваш сервер
Flask все еще работает после запуска предыдущих примеров, то обнаружит новый кон-
тент и перезапустится.

18.5. Модифицируйте функцию Š‘‡ſƀ вашего сервера, чтобы она использовала


шаблон Š‘‡ŜŠ–Ž. Передайте ей три параметра для команды : thing, height
и ‘Ž‘”.

Перед вами файл ˆŽƒ•ɪŜ’›:


ˆ”‘ˆŽƒ•‹’‘”– Žƒ•ř”‡“—‡•–ř”‡†‡”ɏ–‡’Žƒ–‡

ƒ’’ʰ Žƒ•ſɏɏƒ‡ɏɏƀ

ɒƒ’’Ŝ”‘—–‡ſɐŵɐƀ
†‡ˆŠ‘‡ſƀś
–Š‹‰ʰ”‡“—‡•–Ŝ˜ƒŽ—‡•Ŝ‰‡–ſɐ–Š‹‰ɐƀ
Ї‹‰Š–ʰ”‡“—‡•–Ŝ˜ƒŽ—‡•Ŝ‰‡–ſɐЇ‹‰Š–ɐƀ
 ‘Ž‘”ʰ”‡“—‡•–Ŝ˜ƒŽ—‡•Ŝ‰‡–ſɐ ‘Ž‘”ɐƀ
”‡–—””‡†‡”ɏ–‡’Žƒ–‡ſɐŠ‘‡ŜŠ–Žɐř
–Š‹‰ʰ–Š‹‰řЇ‹‰Š–ʰЇ‹‰Š–ř ‘Ž‘”ʰ ‘Ž‘”ƀ

ƒ’’Ŝ”—ſ†‡„—‰ʰ”—‡ƀ

Перейдите в своем клиенте по следующему адресу:


Š––’śŵŵŽ‘ ƒŽŠ‘•–śɬɥɥɥŵţ–Š‹‰ʰ –‘–Š‘”’‡ĺЇ‹‰Š–ʰɮĺ ‘Ž‘”ʰ‰”‡‡

Вы должны увидеть вот что:


ɐ‘ˆ ‘—”•‡”‡ˆ‡””‹‰–‘ –‘–Š‘”’‡ř™Š‹ Š‹•ɮˆ‡‡––ƒŽŽƒ†‰”‡‡Ŝ

ǩȣȚȤȗȐȚȖȕȡȐȒȖȔ
Питонщикам сегодня ничего не задавали.

ǷȐǨȘȚ
20.1. Установите ƒ–’Ž‘–Ž‹„. Нарисуйте диаграмму рассеивания для следующих
пар ſšř ›ƀ: ( ſɥř ɥƀ, ſɪřɬƀ, ſɭř ɩƀ, ſɰř ɯƀ, ſɨɫř ɨɥƀ ƀ.
20.2. Нарисуйте линейчатый график на основе тех же данных.
20.3. Нарисуйте график на основе тех же данных.
  ǷȘȐȓȖȎȍȕȐȧ

В этом фрагменте кода показаны все три подграфика:


‹’‘”–ƒ–’Ž‘–Ž‹„Ŝ’›’Ž‘–ƒ•’Ž–

šʰſɥřɪřɭřɰřɨɫƀ
›ʰſɥřɬřɩřɯřɨɥƀ
ˆ‹‰ř’Ž‘–•ʰ’Ž–Ŝ•—„’Ž‘–•ſ”‘™•ʰɨř ‘Ž•ʰɪƀ

’Ž‘–•ƃɥƄŜ• ƒ––‡”ſšř›ƀ
’Ž‘–•ƃɨƄŜ’Ž‘–ſšř›ƀ
’Ž‘–•ƃɩƄŜ’Ž‘–ſšř›řɐ‘Şɐƀ

’Ž–Ŝ•Š‘™ſƀ

ǯȈȘȈȉȖȚȖȑ
21.1. Установите Geopandas и запустите пример 21.1. Попробуйте поизменять цвета
и размеры меток.

3\WKRQȊȕȈțȒȍ
22.1. Установите Pandas. Получите CSV-файл в примере 16.1. Запустите программу
из примера 16.2. Поэкспериментируйте с командами Pandas.
ƗƘƐƓƖƎƍƕƐƍƌ
ǪșȗȖȔȖȋȈȚȍȓȤȕȣȍȚȈȉȓȐȞȣ

Я обнаружил, что кое-какие вещи мне приходится подсматривать слишком часто.


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

ǷȘȐȖȘȐȚȍȚȖȗȍȘȈȚȖȘȖȊ
Таблица Д.1 — ремикс официальной документации о приоритетах для Python 3,
операторы с самым высоким приоритетом находятся наверху.
ǺȈȉȓȐȞȈǬǷȘȐȖȘȐȚȍȚȖȗȍȘȈȚȖȘȖȊ

ǶȗȍȘȈȚȖȘ ǶȗȐșȈȕȐȍȐȗȘȐȔȍȘȣ
[v, …], {v1, …}, {k1:v1, …}, (…) Создание или включение списка/множества/словаря/
генератора, выражение в скобках
seq[n], seq[n:m], func(args…), [Link] Индекс, разбиение, вызов функции, ссылка на атрибут
** Экспонента
+n, –n, ~x Знаки плюс и минус, битовое НЕ
*, /, //, % Умножение, деление с плавающей точкой,
целочисленное деление, напоминание
+, - Сложение, вычитание
<<, >> Битовый сдвиг вправо или влево
& Битовое И
| Битовое ИЛИ
in, not in, is, is not, <, <=, >, >=, !=, == Проверка на членство и равенство
not x Булево (логическое) НЕ
and Булево И
or Булево ИЛИ
if… else Условное выражение
lambda… Лямбда-выражение
  ǷȘȐȓȖȎȍȕȐȧ

ǹȚȘȖȒȖȊȣȍȔȍȚȖȌȣ
Python предлагает строковые методы (можно применять с любым объектом str)
и модуль string, содержащий полезные определения. Задействуем проверочные
переменные:
ʴʴʴ•ʰɑ ř›’ƒ™•ƒ†™Š‹•‡”•Šɑ
ʴʴʴ–ʰɑ ɐŽƒ–‡Šɑ

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


оригинальные переменные s и t не изменятся.

ǰȏȔȍȕȍȕȐȍȘȍȋȐșȚȘȈ
ʴʴʴ•Ŝ ƒ’‹–ƒŽ‹œ‡ſƀ
ɐŠř›’ƒ™•ƒ†™Š‹•‡”•Šɐ
ʴʴʴ•ŜŽ‘™‡”ſƀ
ɐ‘Šř›’ƒ™•ƒ†™Š‹•‡”•Šɐ
ʴʴʴ•Ŝ•™ƒ’ ƒ•‡ſƀ
ɐ‘Šř Šɐ
ʴʴʴ•Ŝ–‹–އſƀ
ɐŠř›ƒ™•†Š‹•‡”•Šɐ
ʴʴʴ•Ŝ—’’‡”ſƀ
ɐ ř Šɐ

ǷȖȐșȒ
ʴʴʴ•Ŝ ‘—–ſɐ™ɐƀ
ɩ
ʴʴʴ•Ŝˆ‹†ſɐ™ɐƀ
9
ʴʴʴ•Ŝ‹†‡šſɐ™ɐƀ
9
ʴʴʴ•Ŝ”ˆ‹†ſɐ™ɐƀ
ɨɭ
ʴʴʴ•Ŝ”‹†‡šſɐ™ɐƀ
ɨɭ
ʴʴʴ•Ŝ•–ƒ”–•™‹–Šſɐ ɐƀ
”—‡

ǰȏȔȍȕȍȕȐȍ
ʴʴʴɐɐŜŒ‘‹ſ•ƀ
ɐ ř›’ƒ™•ƒ†™Š‹•‡”•Šɐ
ʴʴʴɐɐŜŒ‘‹ſ•ƀ
ɐ ř›’ƒ™•ƒ†™Š‹•‡”•Šɐ
ʴʴʴɐɐŜŒ‘‹ſſ•ř–ƀƀ
ɑ ř›’ƒ™•ƒ†™Š‹•‡”•Š ɐŽƒ–‡Šɑ
ʴʴʴ•ŜŽ•–”‹’ſɐ ɐƀ
ɐř›’ƒ™•ƒ†™Š‹•‡”•Šɐ
ǷȘȐȓȖȎȍȕȐȍǬǪșȗȖȔȖȋȈȚȍȓȤȕȣȍȚȈȉȓȐȞȣ  

ʴʴʴ•Ŝ”‡’Žƒ ‡ſɐ ɐřɐ ɐƀ


ɐ ř›’ƒ™•ƒ†™Š‹•‡”•Šɐ
ʴʴʴ•Ŝ”•’Ž‹–ſƀ
ƃɐ řɐřɐ›ɐřɐ’ƒ™•ɐřɐƒ†ɐřɐ™Š‹•‡”•ŠɐƄ
ʴʴʴ•Ŝ”•’Ž‹–ſɐɐřɨƀ
ƃɐ ř›’ƒ™•ƒ†ɐřɐ™Š‹•‡”•ŠɐƄ
ʴʴʴ•Ŝ•’Ž‹–ſɐɐřɨƀ
ƃɐ řɐřɐ›’ƒ™•ƒ†™Š‹•‡”•ŠɐƄ
ʴʴʴ•Ŝ•’Ž‹–ſɐɐƀ
ƃɐ řɐřɐ›ɐřɐ’ƒ™•ɐřɐƒ†ɐřɐ™Š‹•‡”•ŠɐƄ
ʴʴʴ•Ŝ•’Ž‹–Ž‹‡•ſƀ
ƃɐ ř›’ƒ™•ƒ†™Š‹•‡”•ŠɐƄ
ʴʴʴ•Ŝ•–”‹’ſƀ
ɐ ř›’ƒ™•ƒ†™Š‹•‡”•Šɐ
ʴʴʴ•Ŝ•–”‹’ſɐ•Šɐƀ
ɐ ř›’ƒ™•ƒ†™Š‹•‡”ɐ

ǼȖȘȔȈȚȐȘȖȊȈȕȐȍ
ʴʴʴ•Ŝ ‡–‡”ſɪɥƀ
ɐ ř›’ƒ™•ƒ†™Š‹•‡”•Šɐ
ʴʴʴ•Ŝ‡š’ƒ†–ƒ„•ſƀ
ɐ ř›’ƒ™•ƒ†™Š‹•‡”•Šɐ
ʴʴʴ•ŜŽŒ—•–ſɪɥƀ
ɐ ř›’ƒ™•ƒ†™Š‹•‡”•Šɐ
ʴʴʴ•Ŝ”Œ—•–ſɪɥƀ
ɐ ř›’ƒ™•ƒ†™Š‹•‡”•Šɐ

ǺȐȗșȚȘȖȒȐ
ʴʴʴ•Ŝ‹•ƒŽ—ſƀ
ƒŽ•‡
ʴʴʴ•Ŝ‹•ƒŽ’Šƒſƀ
ƒŽ•‡
ʴʴʴ•Ŝ‹•’”‹–ƒ„އſƀ
”—‡
ʴʴʴ•Ŝ‹•–‹–އſƀ
ƒŽ•‡
ʴʴʴ•Ŝ‹•—’’‡”ſƀ
ƒŽ•‡
ʴʴʴ•Ŝ‹•†‡ ‹ƒŽſƀ
ƒŽ•‡
ʴʴʴ•Ŝ‹•—‡”‹ ſƀ
ƒŽ•‡

ǨȚȘȐȉțȚȣȔȖȌțȓȧVWULQJ
Существуют атрибуты класса, которые используются как определение констант
(табл. Д.2).
  ǷȘȐȓȖȎȍȕȐȧ

ǺȈȉȓȐȞȈǬǨȚȘȐȉțȚȣȌȓȧȖȗȘȍȌȍȓȍȕȐȧȒȖȕșȚȈȕȚ

ǨȚȘȐȉțȚ ǷȘȐȔȍȘ
ascii_letters 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
ascii_lowercase 'abcdefghijklmnopqrstuvwxyz'
ascii_uppercase 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
digits '0123456789'
hexdigits '0123456789abcdefABCDEF'
octdigits '01234567'
punctuation '!”#$%&\'()*+,–./:;<=>?@[\\]^_\{|}~'`
printable цифры + ascii_символы + пунктуация + пробел
whitespace ' \t\n\r\x0b\x0c'
ȻɢɥɥɅɸɛɚɧɨɜɢɱ
ɉɪɨɫɬɨɣ3\WKRQɋɨɜɪɟɦɟɧɧɵɣɫɬɢɥɶɩɪɨɝɪɚɦɦɢɪɨɜɚɧɢɹ
ɟɢɡɞɚɧɢɟ
ɉɟɪɟɜɟɥɫɚɧɝɥɢɣɫɤɨɝɨȿɁɚɡɧɨɛɚ

 Ɂɚɜɟɞɭɸɳɚɹɪɟɞɚɤɰɢɟɣ ɘɋɟɪɝɢɟɧɤɨ
 ȼɟɞɭɳɢɣɪɟɞɚɤɬɨɪ ɇȽɪɢɧɱɢɤ
 Ʌɢɬɟɪɚɬɭɪɧɵɟɪɟɞɚɤɬɨɪɵ ɇɄɭɞɪɟɣɤɨɇɏɥɟɛɢɧɚ
 ɏɭɞɨɠɟɫɬɜɟɧɧɵɣɪɟɞɚɤɬɨɪ ȼɆɨɫɬɢɩɚɧ
 Ʉɨɪɪɟɤɬɨɪɵ ȿɉɚɜɥɨɜɢɱȿɊɚɮɚɥɸɤȻɭɡɨɜɫɤɚɹ
 ȼɟɪɫɬɤɚ ȽȻɥɢɧɨɜ

ɂɡɝɨɬɨɜɥɟɧɨɜɊɨɫɫɢɢɂɡɝɨɬɨɜɢɬɟɥɶɈɈɈ©ɉɪɨɝɪɟɫɫɤɧɢɝɚª
ɆɟɫɬɨɧɚɯɨɠɞɟɧɢɹɢɮɚɤɬɢɱɟɫɤɢɣɚɞɪɟɫɊɨɫɫɢɹɝɋɚɧɤɬɉɟɬɟɪɛɭɪɝ
ȻɋɚɦɩɫɨɧɢɟɜɫɤɢɣɩɪɞȺɩɨɦɌɟɥ
Ⱦɚɬɚɢɡɝɨɬɨɜɥɟɧɢɹɇɚɢɦɟɧɨɜɚɧɢɟɤɧɢɠɧɚɹɩɪɨɞɭɤɰɢɹɋɪɨɤɝɨɞɧɨɫɬɢɧɟɨɝɪɚɧɢɱɟɧ
ɇɚɥɨɝɨɜɚɹɥɶɝɨɬɚ²ɨɛɳɟɪɨɫɫɢɣɫɤɢɣɤɥɚɫɫɢɮɢɤɚɬɨɪɩɪɨɞɭɤɰɢɢɈɄ²
Ʉɧɢɝɢɩɟɱɚɬɧɵɟɩɪɨɮɟɫɫɢɨɧɚɥɶɧɵɟɬɟɯɧɢɱɟɫɤɢɟɢɧɚɭɱɧɵɟ
ɂɦɩɨɪɬɟɪɜȻɟɥɚɪɭɫɶɈɈɈ©ɉɂɌȿɊɆªɊȻɝɆɢɧɫɤɭɥɌɢɦɢɪɹɡɟɜɚɞɤɬɟɥɮɚɤɫ
ɉɨɞɩɢɫɚɧɨɜɩɟɱɚɬɶɎɨɪɦɚɬîȻɭɦɚɝɚɨɮɫɟɬɧɚɹɍɫɥɩɥɌɢɪɚɠɁɚɤɚɡ

Вам также может понравиться