КулЛиб - Классная библиотека! Скачать книги бесплатно
Всего книг - 712469 томов
Объем библиотеки - 1400 Гб.
Всего авторов - 274472
Пользователей - 125055

Новое на форуме

Новое в блогах

Впечатления

Влад и мир про Владимиров: Ирландец 2 (Альтернативная история)

Написано хорошо. Но сама тема не моя. Становление мафиози! Не люблю ворьё. Вор на воре сидит и вором погоняет и о ворах книжки сочиняет! Любой вор всегда себя считает жертвой обстоятельств, мол не сам, а жизнь такая! А жизнь кругом такая, потому, что сам ты такой! С арифметикой у автора тоже всё печально, как и у ГГ. Простая задачка. Есть игроки, сдающие определённую сумму для участия в игре и получающие определённое количество фишек. Если в

  подробнее ...

Рейтинг: 0 ( 0 за, 0 против).
DXBCKT про Дамиров: Курсант: Назад в СССР (Детективная фантастика)

Месяца 3-4 назад прочел (а вернее прослушал в аудиоверсии) данную книгу - а руки (прокомментировать ее) все никак не доходили)) Ну а вот на выходных, появилось время - за сим, я наконец-таки сподобился это сделать))

С одной стороны - казалось бы вполне «знакомая и местами изьезженная» тема (чуть не сказал - пластинка)) С другой же, именно нюансы порой позволяют отличить очередной «шаблон», от действительно интересной вещи...

В начале

  подробнее ...

Рейтинг: +1 ( 1 за, 0 против).
DXBCKT про Стариков: Геополитика: Как это делается (Политика и дипломатия)

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

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

  подробнее ...

Рейтинг: +1 ( 1 за, 0 против).
DXBCKT про Москаленко: Малой. Книга 3 (Боевая фантастика)

Третья часть делает еще более явный уклон в экзотерику и несмотря на все стсндартные шаблоны Eve-вселенной (базы знаний, нейросети и прочие девайсы) все сводится к очередной "ступени самосознания" и общения "в Астралях")) А уж почти каждодневные "глюки-подключения-беседы" с "проснувшейся планетой" (в виде галлюцинации - в образе симпатичной девчонки) так и вообще...))

В общем герою (лишь формально вникающему в разные железки и нейросети)

  подробнее ...

Рейтинг: +1 ( 1 за, 0 против).
Влад и мир про Черепанов: Собиратель 4 (Боевая фантастика)

В принципе хорошая РПГ. Читается хорошо.Есть много нелогичности в механике условий, заданных самим же автором. Ну например: Зачем наделять мечи с поглощением душ и забыть об этом. Как у игрока вообще можно отнять душу, если после перерождении он снова с душой в своём теле игрока. Я так и не понял как ГГ не набирал опыта занимаясь ремеслом, особенно когда служба якобы только за репутацию закончилась и групповое перераспределение опыта

  подробнее ...

Рейтинг: 0 ( 0 за, 0 против).

Python для детей. Самоучитель по программированию [Джейсон Бриггс] (pdf) читать онлайн

Книга в формате pdf! Изображения и текст могут не отображаться!


 [Настройки текста]  [Cбросить фильтры]

San Francisco

Джейсон Бриггс

М
«Манн, Иванов и Фербер»
2017

УДК 087.5:004.43
ББК 76.1,62:32.973.412
Б87
Перевод с английского Станислава Ломакина
Издано с разрешения No Starch Press, Inc., a California Corporation
На русском языке публикуется впервые
Возрастная маркировка в соответствии
с Федеральным законом № 436-ФЗ: 0+

Б87

Бриггс, Джейсон
Python для детей. Самоучитель по программированию / Джейсон Бриггс ;
пер. с англ. Станислава Ломакина ; [науч. ред. Д. Абрамова]. — М. : Манн,
Иванов и Фербер, 2017. — 320 с.
ISBN 978-5-00100-616-9
Эта книга позволит вам погрузиться в программирование и с легкостью
освоить Python. Вы сможете написать несколько настоящих игр. На каждом шагу вы будете видеть результаты своих трудов — в виде работающей
программы, а с понятными инструкциями и примерами с забавными иллюстрациями обучение будет только приятным. Книга для детей от 10 лет.
УДК 087.5:004.43
ББК 76.1,62:32.973.412
Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без
письменного разрешения владельцев авторских прав.

ISBN 978-5-00100-616-9

Copyright © 2013 by Jason R. Briggs.
Title of English-language original: Python for Kids,
ISBN 978-1-59327-407-8, published by No Starch Press.
© Перевод на русский язык, издание на русском языке,
оформление. ООО «Манн, Иванов и Фербер», 2017

О ГЛ А В ЛЕ НИЕ
ВВЕДЕНИЕ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
ЧАСТЬ I
УЧИМСЯ ПРОГРАММИРОВАТЬ
1. НЕ ВСЕ ЗМЕИ ПРЕСМЫКАЮТСЯ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Немного о языке . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Установка Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
Когда Python установлен . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Сохранение Python-программ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2. ВЫЧИСЛЕНИЯ И ПЕРЕМЕННЫЕ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Вычисления в Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
Переменные как ярлыки для данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Использование переменных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3. СТРОКИ, СПИСКИ, КОРТЕЖИ И СЛОВАРИ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Строки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Списки мощнее строк . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Кортежи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Словари в Python — не для поиска слов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4. РИСОВАНИЕ С ПОМОЩЬЮ ЧЕРЕПАШКИ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Использование модуля черепашки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5. ЗАДАЕМ ВОПРОСЫ С ПОМОЩЬЮ IF И ELSE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Конструкция if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Конструкция if-then-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Команды if и elif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Объединение условий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Переменные без значения — None . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Разница между строками и числами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
6. ПРИШЛО ВРЕМЯ ЗАЦИКЛИТЬСЯ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Использование цикла for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Цикл while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
7. ПОВТОРНОЕ ИСПОЛЬЗОВАНИЕ КОДА
С ПОМОЩЬЮ ФУНКЦИЙ И МОДУЛЕЙ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Применение функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Применение модулей . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

5

8. КАК ПОЛЬЗОВАТЬСЯ КЛАССАМИ И ОБЪЕКТАМИ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Разделяем сущности на классы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Другие полезные свойства объектов и классов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Инициализация объектов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
9. ВСТРОЕННЫЕ ФУНКЦИИ PYTHON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
Использование встроенных функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
Работа с файлами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
10. ПОЛЕЗНЫЕ МОДУЛИ PYTHON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
Создание копий с помощью модуля copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
Ключевые слова и модуль keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
Генерация случайных чисел с помощью модуля random . . . . . . . . . . . . . . . . . . . . . . . . . 133
Управление оболочкой с помощью модуля sys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
Работа со временем и модуль time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
Модуль pickle и сохранение информации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
11. И СНОВА ЧЕРЕПАШЬЯ ГРАФИКА . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Начнем с обычного квадрата . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Рисуем звезды . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Рисуем машину . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Возьмемся за краски . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
Функция рисования квадрата . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
Рисуем заполненные квадраты . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
Рисуем закрашенные звезды . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
12. БОЛЕЕ СОВЕРШЕННАЯ ГРАФИКА С МОДУЛЕМ TKINTER . . . . . . . . . . . . . . . . . . 161
Создаем кнопку . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
Именованные аргументы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
Создаем холст для рисования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
Рисование линий . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
Рисование прямоугольников . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
Рисование дуг . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
Рисование многоугольников . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Отображение текста . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Вывод изображений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
Создание простой анимации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
Реакция объектов на события . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
Для чего еще нужен идентификатор . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
ЧАСТЬ II
ПИШЕМ ИГРУ «ПРЫГСКОК!»
13. НАША ПЕРВАЯ ИГРА: «ПРЫГСКОК!» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
Прыгающий мяч . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193

6

Оглавление

Создаем игровой холст . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Создаем класс для мяча . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Добавим движение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14. ДОДЕЛЫВАЕМ ПЕРВУЮ ИГРУ: «ПРЫГСКОК!» . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Создаем ракетку . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Добавим возможность проигрыша . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ЧАСТЬ III
ПИШЕМ ИГРУ «ЧЕЛОВЕЧЕК СПЕШИТ К ВЫХОДУ»
15. СОЗДАЕМ ГРАФИКУ ДЛЯ ИГРЫ ПРО ЧЕЛОВЕЧКА . . . . . . . . . . . . . . . . . . . . . . . . . .
План игры про человечка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Устанавливаем GIMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Создаем изображения для игры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16. РАЗРАБОТКА ИГРЫ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Создаем класс игры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Создаем класс Coords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Проверка столкновений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Создаем класс Sprite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Добавляем платформы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17. СОЗДАЕМ ЧЕЛОВЕЧКА . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Инициализация спрайта . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Поворот фигурки вправо и влево . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Прыжок фигурки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Что мы уже написали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18. ДОДЕЛЫВАЕМ ИГРУ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Анимация фигурки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Проверяем спрайт человечка . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Дверь . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Код игры целиком . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Что мы узнали . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ПОСЛЕСЛОВИЕ: КУДА ДВИГАТЬСЯ ДАЛЬШЕ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Игры и программирование графики . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Языки программирования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Заключение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ПРИЛОЖЕНИЕ: КЛЮЧЕВЫЕ СЛОВА PYTHON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ГЛОССАРИЙ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ПРЕДМЕТНЫЙ УКАЗАТЕЛЬ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

194
195
197
203
204
204
210
214
215

219
219
220
221
228
229
229
233
234
239
240
244
245
246
246
249
250
251
252
253
253
265
266
268
274
275
276
276
278
282
283
297
302

ВВЕДЕНИЕ

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

Почему именно Python?
Python — простой в изучении язык программирования, он особенно хорош для начинающих. В отличие от многих других языков, Python-код
легко читается, а интерактивная оболочка позволяет вводить программы и сразу же получать результат. Помимо простой структуры языка
и интерактивной оболочки, в Python есть инструменты, заметно ускоряющие обучение и позволяющие создавать несложные анимации для своих видеоигр. Один из таких инструментов — специально созданный для
обучения модуль turtle, который имитирует «черепашью графику» (в
1960-х годах она использовалась в языке Logo). Другой инструмент — модуль tkinter для работы с графической библиотекой Tk, позволяющей
создавать программы с продвинутой графикой и анимацией.

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

8

что-то покажется вам непонятным или чересчур сложным, советую действовать так:
1. Разбейте задачу на составные части. Постарайтесь сперва понять,
что делает небольшой фрагмент кода (фокусируйтесь на кусочках программы, не пытайтесь с ходу разобраться, как она устроена целиком).
2. Если это не помогает, иногда проблему лучше всего отложить,
чтобы вернуться к ней на другой день. Этот способ хорош
для многих жизненных ситуаций, и особенно при изучении
программирования.

Для кого эта книга
Эта книга — для всех, кто интересуется программированием, будь это
ребенок или взрослый, которому программирование в новинку. Если вы
хотите не просто пользоваться чужими разработками, а создавать свое,
«Python для детей» — хороший способ приступить к делу.
Изучив основы программирования, вы узнаете, как создавать собственные игры. Вам предстоит разработать две игры, научившись определять столкновения, использовать события и применять разные способы анимации.
Большинство примеров в этой книге рассчитаны на программирование в среде IDLE, которая идет в комплекте с Python. IDLE поддерживает
подсветку синтаксиса, копирование и вставку текста, а также возможность сохранения и загрузки вашего кода. То есть IDLE одновременно
и интерактивная среда для экспериментов, и что-то вроде текстового
редактора. Хоть для запуска примеров достаточно стандартной консоли
и обычного редактора текстов, подсветка синтаксиса и дружественный
интерфейс IDLE облегчат вашу задачу, поэтому мы обязательно разберемся, как настроить и использовать эту среду.

Что вас ждет?
Вот краткое описание материала каждой из глав.
Глава 1 — введение в программирование и инструкции по установке
Python.
Глава 2 — знакомство с простыми вычислениями и с переменными.
Глава 3 — описание некоторых основных типов данных (таких как строки, списки, кортежи).
Глава 4 — знакомство с модулем turtle. От основ программирования
мы перейдем к перемещению черепашки (она похожа на стрелочку)
по экрану.
Глава 5 — описание логических условий и конструкции if.

Введение

9

Глава 6 — циклы for и while.
Глава 7 — введение в создание и использование функций.
Глава 8 — введение в классы и объекты. На этом этапе мы освоим достаточно базовых возможностей языка, чтобы использовать приемы программирования игр.
Глава 9 — обзор большинства встроенных функций Python.
Глава 10 — обзор нескольких модулей, которые идут в комплекте
с Python.
Глава 11 — снова о модуле turtle и рисовании более сложных фигур.
Глава 12 — модуль tkinter и создание продвинутой графики.
Главы 13 и 14 — пишем нашу первую игру, «Прыг-скок!», используя знания, полученные в предыдущих главах.
Главы от 15 до 18 — создаем вторую игру, «Человечек спешит к выходу».
При вводе кода из глав, посвященных играм, вы можете допустить ошибки. Если найти их самостоятельно не получится, скачайте код игры с сайта этой книги (python-for-kids.com/ или mann-ivanov-ferber.ru) и сравните
с ним вашу программу.
Послесловие — краткий обзор модуля PyGame и некоторых других популярных языков программирования.
Приложение — подробное описание ключевых слов Python.
Глоссарий — определения терминов из области программирования, которые встречаются в данной книге.

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

ЧАС ТЬ I

Учимся
программировать

1
НЕ ВСЕ ЗМЕИ ПРЕСМЫК АЮТСЯ

Компьютерная программа — это набор инструкций, следуя которым
компьютер выполняет различные действия. Программу не найти среди
деталей компьютера: проводов, микросхем, карт памяти, жестких дисков
и тому подобного. Ее невозможно увидеть, однако выполняется она с помощью аппаратуры. Компьютерная программа (или просто программа)
состоит из последовательности команд, указывающих оборудованию,
что и как делать. Совокупность работающих на компьютере программ
называют программным обеспечением.
Практически любое из электронных устройств, которыми мы пользуемся, не будет работать или станет гораздо менее полезным, если лишить его программного обеспечения. Программы управляют не только
компьютерами, но и мобильными телефонами, игровыми приставками,
автомобильными GPS-навигаторами. Среди не столь очевидных примеров — жидкокристаллические телевизоры, DVD-плееры, микроволновые
печи и некоторые модели холодильников. Даже двигатели автомобилей,
светофоры и уличные фонари, электронные рекламные панели и лифты
в наши дни работают благодаря программам.
Программы чем-то похожи на мысли. Если бы у нас не было мыслей, мы, наверное, сидели бы на полу, ничего не делая. Мысль встать
с пола — это инструкция, или команда, которая говорит нашему телу,
что нужно подняться. Так же и программы говорят компьютеру, как ему
действовать.
Научившись программировать, вы сможете делать множество полезных вещей. Вряд ли вы будете создавать программы для автомобилей,
светофоров или холодильников (во всяком случае, это требует специальной подготовки), однако вы сможете разрабатывать веб-страницы,

13

видеоигры и даже писать программы, помогающие делать домашние
задания.

Немного о языке

Python —
букв. питон

Как и люди, компьютеры «говорят» на разных языках, только языки
эти — компьютерные. Компьютерный язык служит для того, чтобы переговариваться с компьютером, используя команды, понятные и компьютеру, и человеку.
Некоторые языки программирования названы в честь людей (например, Ада и Паскаль), другие названия являются простыми акронимами,
то есть аббревиатурой (к примеру, BASIC — от англ. Beginner’s All-purpose
Symbolic Instruction Code, универсальный код символических инструкций для начинающих), и уж совсем немногие языки названы в честь телевизионных шоу — как Python. О да, язык программирования Python
(произносится «Пайтон», с ударением на первый слог, хотя имейте в виду,
что в России многие называют язык просто «питон») получил свое имя
благодаря телешоу «Летающий цирк Монти Пайтона», так что змея питон
здесь вовсе ни при чем.

!

«Летающий цирк Монти Пайтона» — британское комедийное телешоу, впервые вышедшее на экраны в 1970 году. Хотя съемки «летающего цирка» давно прекращены, у него множество поклонников
по всему миру. Среди комедийных скетчей этого шоу есть, например,
зарисовки «Министерство глупых походок», «Рыбошлепский танец»
и «Сырная лавка» (в которой не продают сыр).

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

Установка Python
IDLE (от Integrated
DeveLopment
Environment) —
интегрированная среда
разработки

14

Установить Python на компьютер совсем несложно. Сейчас мы шаг за шагом
разберем, как устанавливать его на системы Windows 7, Mac OS X и Ubuntu.
Также мы создадим на рабочем столе ярлык для IDLE — среды разработки
Python-программ. Если Python уже установлен на вашем компьютере, можете сразу переходить к разделу «Когда Python установлен» на стр. 20.

Часть I. Учимся программировать

Установка Python в системе Windows 7
Чтобы установить Python в системе Microsoft Windows 7, откройте
веб-браузер, введите адрес http://www.python.org/ и скачайте последнюю
версию программы-установщика Python 3 для Windows (для этого зайдите в меню Downloads и выберите Windows).

!

Download —
скачать

Неважно, какую конкретно версию Python вы скачаете. Главное,
чтобы ее номер начинался с цифры 3.

После того как установщик скачается, дважды кликните мышкой
по его значку и установите Python, следуя инструкциям программы:
1. Выберите Install for All Users и нажмите Next.
2. Не меняйте указанный адрес установки, но запомните его (например, C:\Python31 или C:\Python32). Нажмите Next.
3. Ничего не меняйте в разделе установщика Customize Python, просто нажмите Next.
После окончания установки в меню Start (Пуск) должен появиться
раздел Python 3.

Install for All
Users — установить для всех
пользователей
Next — далее
Customize
Python — настроить Python
Start — пуск

1. Не все змеи пресмыкаются

15

Теперь добавьте ярлык Python 3 на рабочий стол:
1. Кликните по рабочему столу правой кнопкой мышки и выберите
из появившегося меню New ▶ Shortcut (Создать ▶ Ярлык).
2. Введите в поле с пометкой Type the location of the item (Укажите
расположение объекта) следущую строку (каталог в начале этой
строки должен соответствовать каталогу установки, который
я просил вас запомнить):
c:\Python32\Lib\idlelib\idle.pyw –n

Диалоговое окно должно выглядеть так:

16

Часть I. Учимся программировать

3. Нажмите Next (Далее), чтобы перейти к следующему диалогу.
4. Укажите имя IDLE и нажмите Finish (Готово), чтобы создать
ярлык.
Теперь переходите к разделу «Когда Python установлен» на стр. 20
и начинайте знакомство с Python.

Установка Python в системе MAC OS X
Если у вас Mac, Python должен быть уже установлен в системе, однако
скорее всего это одна из старых версий языка. Откройте веб-браузер,
перейдите по адресу http://www.python.org/getit/ и скачайте последнюю
версию инсталлятора для Mac OS X.
Вам нужно выбрать инсталлятор в зависимости от вашей версии
Mac OS X (чтобы узнать версию, кликните по значку с яблоком в верхнем
меню и выберите пункт About this Mac).
После того как файл скачается, дважды клините по нему. Должно появиться окошко с содержимым файла.

В этом окне дважды кликните по значку Python.mpkg и следуйте инструкциям. Перед установкой система попросит вас ввести пароль администратора (не знаете пароль? Спросите у родителей).
Теперь добавьте на рабочий стол скрипт для запуска среды разработки IDLE:
1. Кликните по значку Spotlight — увеличительному стеклышку
в правом верхнем углу экрана.

Spotlight — букв.
прожектор

2. В появившемся поле введите Automator.
3. Кликните по приложению со значком в виде робота, когда оно появится в меню (либо в секции Top Hit, либо в секции Applications).
4. После того как Automator запустится, выберите шаблон Application (Программа).

Application —
приложение

1. Не все змеи пресмыкаются

17

Choose — выбрать

5. Нажмите кнопку Choose (Выбрать).

Run — запустить
Shell Script —
скрипт оболочки

6. Отыщите в списке действий пункт Run Shell Script (Запустить
shell-скрипт) и перетащите его на пустую панель справа. Результат будет выглядеть примерно так:

18

Часть I. Учимся программировать

7.

В поле ввода вы увидите слово cat. Замените его такой строкой:
open -a "/Applications/Python 3.2/IDLE.app" —args -n

8. Выберите File ▶ Save (Файл ▶ Сохранить) и укажите в качестве
имени IDLE.
9.

В диалоге Where выберите Desktop (Рабочий стол) и нажмите
Save (Сохранить).

Теперь переходите к разделу «Когда Python установлен» (на стр. 20)
и начинайте знакомство с Python.

Установка Python в системе Ubuntu
Python уже входит в Ubuntu Linux, но это может быть старая версия языка. Для установки Python 3 выполните следующие шаги:
1. В сайдбаре кликните по кнопке центра приложений Ubuntu
(значок с оранжевой сумкой. Если вы его не видите, кликните
по значку меню Dash и введите в строке поиска Software).

Software —
программное
обеспечение

2. Запустив центр приложений, введите Python в строке поиска
(расположенной в правом верхнем углу окна).
3. В появившемся списке приложений выберите последнюю версию
IDLE, например IDLE (using Python 3.2):

1. Не все змеи пресмыкаются

19

4. Нажмите Install.
5. Введите пароль администратора и нажмите Authenticate (не знаете пароль? Спросите у родителей).

Authenticate —
авторизация

!

В некоторых версиях Ubuntu в списке будет лишь строка Python
(v3.2) — без слова IDLE. Это тоже подходит.

Итак, у вас установлена последняя версия Python. Давайте скорее посмотрим, что же это такое.

Когда Python установлен
Если вы пользуетесь Windows или Mac OS Х, к этому моменту на вашем рабочем столе должен находиться значок
с надписью IDLE. Если же вы используете Ubuntu, в меню
Applications должен появиться раздел Programming,
а в нем приложение IDLE (using Python 3.2) (или более
поздняя версия).
Дважды кликните по значку или выберите приложение из меню. Должно появиться такое окно:

Это командная оболочка Python, которая входит в интегрированную среду разработки, а три знака «больше» (>>>) называются
приглашением.
После приглашения можно вводить различные команды. Что ж, давайте приступим:
>>> print("Привет, мир")

20

Часть I. Учимся программировать

Не забудьте про двойные кавычки (" "). Закончив вводить эту строку,
нажмите клавишу Enter. Если вы ввели команду без ошибок, на экране
должно появиться:
>>> print("Привет, мир")
Привет, мир
>>>

Приглашение возникнет снова. Это значит, что оболочка Python готова к выполнению дальнейших команд.
Поздравляю! Вы только что создали первую программу на языке
Python! Слово print относится к разновидности команд, которые называются функциями, и эта конкретная функция выводит на экран все,
что указано после нее в двойных кавычках. То есть вы дали компьютеру
команду напечатать слова «Привет, мир» и эта команда понятна и вам,
и компьютеру.

Print — печать

Сохранение Python-программ
От программ было бы мало толку, если бы их каждый
раз приходилось писать заново. Конечно, если программа совсем короткая, это несложно. Однако большие программы могут состоять из миллионов строк кода. Чтобы
распечатать весь код такой программы, например редактора документов, потребуется не меньше 100 000 листов
бумаги. Представьте, каково нести такую груду листов
домой!
К счастью, тексты программ можно сохранять на диск.
Чтобы сохранить новую программу, запустите IDLE и выберите в меню File ▶ New File. Откроется пустое окно со словом
Untitled в заголовке. Введите в этом новом окне такой код:

Untitled — без
названия

print("Привет, мир")

Теперь выберите в меню File ▶ Save. Введите в ответ на запрос имени
файла hello.py и сохраните файл на рабочий стол. Теперь выберите Run ▶
Run Module. Сохраненная программа должна запуститься.
Если вы закроете окно оболочки, оставив открытым окно с заголовком hello.py, и выберете из меню Run ▶ Run Module, окно оболочки появится снова и ваша программа запустится. Чтобы открыть оболочку
Python без запуска программы, выберите Run ▶ Python Shell.

Run module —
запустить
модуль

1. Не все змеи пресмыкаются

21

После сохранения и запуска этой программы вы
обнаружите на рабочем столе новый значок с названием hello.py. Если дважды кликнуть по нему мышкой,
на экране появится черное окно и тут же исчезнет. Что
произошло?
Это было консольное окно Python (что-то вроде командной оболочки), где наша программа запустилась,
напечатала слова «Привет, мир» и тут же завершила работу. Это окно практически невозможно рассмотреть,
прежде чем оно закроется:

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

22

Часть I. Учимся программировать

• В системах Windows и Ubuntu используйте CTRL-N для создания нового окна, CTRL-S — для сохранения отредактированного файла и F5 — для запуска программы.
• В системе Mac OS X используйте -N для создания нового
окна и -S для сохранения файла, а для запуска программы
нажмите клавишу FN и, удерживая ее, нажмите F5.

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

2
ВЫЧИС ЛЕНИЯ И ПЕРЕМЕННЫЕ

Итак, вы установили Python и знаете, как запускать его командную оболочку, а значит, пора использовать его по назначению. Мы начнем с простых математических расчетов, а затем перейдем к важной части языка — переменным. Переменные — это удобный способ хранения данных
в программе, и они пригодятся нам для решения самых разных задач.

Вычисления в Python
Если нужно перемножить два числа, к примеру узнать, сколько будет
8 × 3,57, мы обычно пользуемся калькулятором либо берем ручку и умножаем в столбик на листе бумаги. А что если использовать для подсчетов
оболочку Python? Давайте попробуем.
Запустите оболочку, дважды кликнув по значку IDLE на рабочем
столе, либо, если у вас система Ubuntu, кликнув по значку IDLE в меню
Applications. Затем после значка >>> введите выражение и нажмите
Enter:
>>> 8 * 3.57
28.56

Обратите внимание, что при записи числа 3,57 используется не запятая, а точка. Кроме того, в Python числа перемножаются с помощью
звездочки (*), а не знака умножения (×).
Теперь рассмотрим более полезную задачу.
Представьте, что вы рыли яму и случайно нашли кошелек с 20 золотыми монетами. На следующий день вы тихонько залезли в подвал, где

24

стоит изобретение вашего дедушки — работающий на паровом ходу механизм для копирования предметов, и, на ваше счастье, в него удалось
запихнуть все 20 монет. Раздался свист, потом щелчок, и устройство выдало еще 10 новеньких монеток.
Сколько монет вы накопите, если будете проделывать эту операцию
каждый день в течение года? На бумаге эти расчеты выглядят примерно
так:
10 × 365 = 3650
20 + 3650 = 3670
Что ж, ничего сложного, осталось лишь выяснить, как посчитать
то же в оболочке Python. Первым делом умножаем 10 монет на 365 дней,
получится 3650. Затем добавим 20 монет, которые были изначально,
и выйдет 3670.
>>> 10 * 365
3650
>>> 20 + 3650
3670

Но что если о вашем богатстве узнает пронырливая ворона? Предположим, она будет каждую неделю залетать в окно и красть по три монетки.
Сколько у вас будет монет через год? В оболочке Python эти расчеты
будут выглядеть так:
>>> 3 * 52
156
>>> 3670 – 156
3514

Сперва умножаем 3 монеты на 52 недели в году, получаем
156. Затем вычитаем это значение из общего количества монет. Выходит, через год у вас останется 3514 монет.
Получилась очень простая программа. Изучая эту книгу дальше, вы узнаете, как писать более сложные и полезные
программы.

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

25

которых выполняются математические действия в языке Python, называются операторами. Основные математические операторы перечислены
в таблице 2.1.
Символ

Операция

+

Сложение

-

Вычитание

*

Умножение

/

Деление

Таблица 2.1. Основные операторы в Python

Прямой слеш (/) обозначает деление, этот символ похож на линию
между числителем и знаменателем дроби. Например, у вас 100 пиратов и 20 больших бочек, и вы хотите рассчитать, сколько пиратов можно спрятать в каждой бочке. Для этого следует разделить 100 пиратов
на 20 бочек, введя в оболочке 100 / 20. И запомните — прямым слешем
называют черту, верх которой наклонен вправо.

Порядок выполнения операций
Операции — это любые действия, которые совершаются с помощью операторов. Математические операции выполняются по очереди в зависимости
от их приоритета (если не задать другую очередность с помощью скобок).
Умножение и деление имеют более высокий приоритет, чем сложение
и вычитание, и это значит, что они будут выполняться первыми. Иначе
говоря, при вычислении математического выражения Python сначала умножит и разделит числа, а затем перейдет к сложению и вычитанию.
Например, в этом выражении сперва будут перемножены числа
30 и 20, а затем к их произведению будет прибавлено число 5.
>>> 5 + 30 * 20
605

По сути это выражение означает «умножить 30 на 20 и прибавить
к результату 5». Получается 605. Однако мы можем изменить порядок
операций, заключив первые два числа в скобки. Вот так:
>>> (5 + 30) * 20
700

26

Часть I. Учимся программировать

В результате получилось 700, а не 605, поскольку Python
выполняет операции в скобках прежде, чем операции вне скобок. Другими словами, это выражение означает «прибавить 5
к 30 и умножить результат на 20».
Скобки могут быть вложенными, то есть внутри скобок могут стоять еще одни скобки:
>>> ((5 + 30) * 20) / 10
70.0

В этом примере Python сперва вычислит выражение во внутренних
скобках, затем во внешних и в самом конце выполнит стоящую за скобками операцию деления.
Иначе говоря, это выражение означает «прибавить 5 к 30, затем
умножить результат на 20, потом разделить результат на 10». Вот что
при этом происходит:


сложение 5 и 30 дает 35;



умножение 35 на 20 дает 700;



деление 700 на 10 дает окончательный результат — 70.

Если бы мы не использовали скобки, результат вышел бы другим:
>>> 5 + 30 * 20 / 10
65.0

В этом случае сперва 30 умножается на 20 (получается 600), затем
600 делится на 10 (выходит 60) и, наконец, к 60 прибавляется 5, что дает
в итоге 65.

!

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

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

2. Вычисления и переменные

27

Например, чтобы создать переменную с именем fred, нужно указать
имя, поставить знак «равно» (=) и ввести соответствующие данные. Давайте создадим переменную fred (Фред), указав, что ей соответствует
значение 100 (однако из этого не следует, что другая переменная не может иметь такое же значение):
>>> fred = 100

Чтобы напечатать значение нашей переменной, введите в оболочке
Python команду print и следом за ней — имя переменной в скобках.
Вот так:
>>> print(fred)
100

Можно изменить значение переменной fred — сделать так, чтобы ей
соответствовали другие данные. Например, вот как заменить значение
fred числом 200:
>>> fred = 200
>>> print(fred)
200

В первой строке говорится, что переменной fred теперь соответствует
число 200. Во второй строке мы запрашиваем значение fred, чтобы убедиться, что оно поменялось. Последней строкой Python печатает ответ.
Можно использовать несколько переменных для одного и того же
значения:
>>> fred = 200
>>> john = fred
>>> print(john)
200

В этом примере знак «равно» между именами john (Джон) и fred
говорит о том, что переменной john соответствует значение переменной
fred.
Конечно, fred — не самое удачное имя переменной, поскольку оно
не поясняет, для чего эта переменная используется. Лучше назовем переменную не fred, а, допустим, number_of_coins (количество монет):

28

Часть I. Учимся программировать

>>> number_of_coins = 200
>>> print(number_of_coins)
200

Number of coins —
количество
монет

Теперь понятно, что речь идет о двухстах монетах.
Имена переменных могут состоять из латинских букв, цифр и знака
подчеркивания (_), однако начинаться с цифры они не могут. В остальном допустимо использовать любые имена, которые могут состоять как
из отдельных букв (например, a), так и из целых предложений (пробелы
в именах недопустимы, но слова можно разделять знаками подчеркивания). Для небольших программ часто удобны короткие имена, но в целом
желательно, чтобы имя переменной отражало смысл, который вы вкладываете в ее использование.
Теперь вы знаете, как создавать переменные. Давайте посмотрим,
что с ними можно делать.

Использование переменных
Помните, как мы вычисляли, сколько монет накопится за год, если каждый день создавать новые монеты с помощью изобретения вашего дедушки? Итак, вот на чем мы остановились:
>>> 20 + 10 * 365
3670
>>> 3 * 52
156
>>> 3670 – 156
3514

Все это можно записать одной строкой кода:
>>> 20 + 10 * 365 – 3 * 52
3514

А что если заменить в этом выражении числа переменными? Введите:
>>> found_coins = 20
>>> magic_coins = 10
>>> stolen_coins = 3

Мы создали три переменные: found_coins, magic_coins
и stolen_coins.

Found coins —
найденные
монеты
Magic coins —
волшебные
монеты
Stolen coins —
украденные
монеты

2. Вычисления и переменные

29

Теперь можно записать наше выражение так:
>>> found_coins + magic_coins * 365 — stolen_coins * 52
3514

Как видите, результат остался прежним. А зачем все это? Ради особой магии
переменных. Представьте, что вы поставили у окошка пугало и поэтому осторожная ворона крадет по две, а не по три
монеты. Если использовать в расчетах
переменную, достаточно поменять ее
значение на другое число, чтобы оно использовалось везде, где эта переменная
фигурирует. То есть мы можем поменять
значение stolen_coins, введя:
>>> stolen_coins = 2

А затем скопировать и снова вставить наше выражение, чтобы пересчитать ответ. Вот так:
1. Выделите текст, который нужно скопировать. Для этого кликните по нему и, не отпуская кнопку мышки, перетащите область выделения от начала строки до ее конца, как показано
на рисунке:

2. Нажав и удерживая клавишу Ctrl (или, если вы используете
Mac OS, клавишу ), нажмите C, чтобы скопировать выделенный
текст (далее я буду называть это действие Ctrl-C).

30

Часть I. Учимся программировать

3. Кликните по строке с приглашением (следующей после stolen_
coins = 2).
4. Нажав и удерживая Ctrl, нажмите V, чтобы вставить скопированный ранее текст (далее я буду называть это действие Ctrl-V).
5. Нажмите Enter, чтобы заново вычислить результат:

Не правда ли, так гораздо проще, чем заново вводить все выражение?
Можете поменять значения других переменных, а потом опять скопировать (Ctrl-C) и вставить (Ctrl-V) выражение, чтобы увидеть результат
изменений. Предположим, вы обнаружили, что если стукнуть по дедушкиному изобретению, из него вылетает на 3 монеты больше. Поступая
так каждый раз, через год вы получите 4661 монету:
>>> magic_coins = 13
>>> found_coins + magic_coins * 365 — stolen_coins * 52
4661

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

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

3
С Т Р О К И , С ПИ С К И , КО Р Т Е Ж И
И С ЛОВАРИ

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

Строки
Фрагменты текста в программировании обычно называют строками.
Можно сказать, что строка — это последовательность символов. Из всех
букв, пробелов, цифр и других печатных знаков в этой книге можно составить строку, и из вашего имени или адреса тоже. По сути, первая программа на Python, которую мы создали в главе 1, уже включала в себя
строку «Привет, мир».

!

Текст в кавычках нужно вводить без переносов. Здесь его пришлось
перенести, поскольку он не вместился в ширину страницы, и это
показано значком  . Встретив такой значок, вводите текст без
переноса.

Создание строк
Чтобы создать строку, нужно ввести текст в кавычках — так Python отличает строки от чисел и других типов данных. Например, возьмем переменную fred из главы 2 и присвоим ей строковое значение:

32

fred = "Почему у горилл большие ноздри? Потому что у них 
толстые пальцы!"

Теперь напечатаем значение fred, воспользовавшись командой
print(fred):
>>> print(fred)
Почему у горилл большие ноздри? Потому что у них толстые пальцы!

Строку можно записать и в одинарных кавычках:
>>> fred = 'Что это: розовое и пушистое? Розовый пушистик!'
>>> print(fred)
Что это: розовое и пушистое? Розовый пушистик!

Однако если вы попытаетесь перенести текст, который начинается
с одинарной (') или двойной (") кавычки на новую строку или поставить
в начале текста кавычку одного типа, а в конце — другого, Python выдаст
сообщение об ошибке. Например, введите:
>>> fred = "Что едят на полдник динозавры?

И вот что получится:
SyntaxError: EOL while scanning string literal

Python выдал сообщение о синтаксической ошибке, потому что, вопреки правилам, мы не завершили строку одинарной или двойной кавычкой.
Синтаксическая ошибка — это неверное расположение слов в предложении или — в нашем случае — слов и символов в программе. Сообщение SyntaxError означает, что вы ввели данные не в том порядке, который ожидает Python, или не ввели те данные, которые он от вас ждал.
Здесь Python, дойдя до конца строки, не обнаружил закрывающую кавычку и выдал ошибку.
Если нужно ввести текст, занимающий несколько строк, поставьте
в начале и в конце три одинарные кавычки, а когда понадобится сделать
перенос, нажимайте Enter. Вот так:

Syntax Error —
синтаксическая
ошибка

>>> fred = '''Что едят на полдник динозавры?
ТиРекс-кекс!'''

33

Теперь напечатаем значение переменной fred:
>>> print(fred)
Что едят на полдник динозавры?
ТиРекс-кекс!

Проблемы со строками
Теперь посмотрите на следующую строку. Попытка ее ввести приведет
к сообщению об ошибке:
Silly string — глупая строка
Invalid syntax —
недопустимый
синтаксис

>>> silly_string = '"Тут что-то не так, не будь я д'Артаньян" — 
подумал он.'
SyntaxError: invalid syntax

Мы попытались создать (и присвоить переменной silly_string)
строку в одинарных кавычках, в которой есть двойные кавычки и еще
одна одинарная в слове "д'Артаньян". Ну и беспорядок!
Не забывайте, что Python не обладает человеческим разумом, поэтому видит только строку, за которой следуют лишние символы. Когда
Python встречает кавычку (одинарную или двойную) в начале строки, он
считает, что такая же кавычка должна стоять и в конце. Поскольку в этом
примере строка начинается с одинарной кавычки, Python воспринимает
одинарную кавычку после буквы «д» как конец строки. Напечатав сообщение об ошибке, Python подсвечивает проблемное место в коде (это слово «Артаньян» после закрывающей кавычки):

34

Часть I. Учимся программировать

Последней строкой IDLE сообщает тип ошибки. В данном случае это
ошибка синтаксическая.
Если вместо одинарных кавычек заключить нашу строку в двойные,
ошибка все равно возникнет, хоть и в другом месте:
>>> silly_string = ""Тут что-то не так, не будь я д'Артаньян" — 
подумал он."
SyntaxError: invalid syntax

Теперь Python считает, что это строка в двойных кавычках, которая
началась и тут же закончилась, и стоящее после закрывающей кавычки
слово «Тут» вызывает ошибку:

С точки зрения Python, после закрывающей
кавычки символов быть не должно — он просто
не знает, что с ними делать.
Чтобы решить эту проблему, можно поставить
три одинарные кавычки в начале и в конце строки (мы так уже делали, вводя строку с переносами). Это позволит использовать в тексте двойные
и одинарные кавычки без риска ошибок. Тогда
можно поместить внутрь строки любую комбинацию кавычек, кроме трех одинарных подряд. Вот
корректный вариант строки:
silly_string = '''"Тут что-то не так, 
не будь я д'Артаньян", — подумал он.'''

3. Строки, списки, кортежи и словари

35

Если вы очень хотите записать эту строку в двойных или одинарных
кавычках, можно ставить перед каждым символом кавычек в тексте обратный слеш (\). Такой способ называется экранированием. Этим мы
как бы говорим: да, внутри этой строки есть кавычки, но их не нужно
воспринимать как закрывающие.
Экранирование усложняет восприятие строк, поэтому желательно
пользоваться тремя одинарными кавычками. Однако вы можете встретить фрагменты чужого кода с экранированием, так что стоит понимать,
к чему там используются все эти обратные слеши.
Вот примеры экранирования:
Single quote —
одинарные
кавычки
Double quote —
двойные
кавычки

 >>> single_quote_str = '"Тут что-то не так, не будь я д\'Артаньян", — 
подумал он.'
 >>> double_quote_str = "\"Тут что-то не так, не будь 
я д'Артаньян\", — подумал он."
>>> print(single_quote_str)
"Тут что-то не так, не будь я д'Артаньян", — подумал он.
>>> print(double_quote_str)
"Тут что-то не так, не будь я д'Артаньян", — подумал он.

В строке  мы создали строку текста в одинарных кавычках, поставив перед одинарной кавычкой внутри нее обратный слеш. В строке 
мы создали строку текста в двойных кавычках, экранировав обратным
слешем двойные кавычки внутри нее. Затем мы вывели только что созданные переменные на экран. Обратите внимание, что обратный слеш
при этом напечатан не был.

Переменные внутри строк

My score — мой
результат

Можно печатать строки, содержащие значения переменных. Для этого используются метки %s в тех местах, где должны быть значения (это называется подстановкой, или встраиванием значений в строку). Например, в переменной myscore хранится счет игры, и вы хотите, чтобы он отображался
в сообщении «Мой счет:
очков». Тогда вместо числа используйте
в сообщении метку %s, а при печати укажите нужное значение. Вот так:
>>>
>>>
>>>
Мой

Message — сообщение

36

myscore = 1000
message = 'Мой счет: %s очков'
print(message % myscore)
счет: 1000 очков

Мы создали переменную myscore со значением 1000 и переменную
message со строкой «Мой счет: %s очков», где %s — метка позиции, в которой нужно отобразить значение. В следующей строке программы мы

Часть I. Учимся программировать

используем команду print(message), указав с помощью знака %, что
метку %s нужно заменить значением переменной myscore. В результате
на экране появляется сообщение «Мой счет: 1000 очков». Для подстановки значения использовать переменную необязательно, то же самое получится, если дать команду print(message % 1000).
Печатая строку с меткой %s, можно каждый раз подставлять
в нее значения разных переменных, как в этом примере:
>>> joke_text = '%s: приспособление для поиска мебели в темноте'
>>> bodypart1 = 'Коленка'
>>> bodypart2 = 'Лодыжка'
>>> print(joke_text % bodypart1)
Коленка: приспособление для поиска мебели в темноте
>>> print(joke_text % bodypart2)
Лодыжка: приспособление для поиска мебели в темноте

Мы создали три переменные. Первая, joke_text, содержит строку с меткой %s. Значения двух других переменных — bodypart1
и bodypart2 — строки с названиями частей тела. Теперь можно печатать joke_text, подставляя с помощью оператора % вместо %s разные
переменные: bodypart1 или bodypart2. В том и другом случае на экране появятся разные сообщения.
Можно использовать и несколько меток в одной строке. Вот так:
>>> nums = 'Что сказало число %s числу %s? Славный поясок!'
>>> print(nums % (0, 8))
Что сказало число 0 числу 8? Славный поясок!

Joke text —
шуточный текст
Bodypart — часть
тела

Nums —
от numbers —
числа

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

Умножение строк
Что получится, если умножить 10 на 5? Разумеется, 50. А если умножить
на 10 букву «a»? Вот что думает об этом Python:
>>> print(10 * 'a')
aaaaaaaaaa

Эта особенность может пригодиться для вывода строк с отступом
в заданное число пробелов. Давайте напечатаем в оболочке Python такое
письмо (выберите в меню File ▶ New File, и введите эту программу в новом окне):

3. Строки, списки, кортежи и словари

37

spaces = ' ' * 25
print('%s Задний переулок 12' % spaces)
print('%s Трясогузочья пустошь' % spaces)
print('%s Западный Всхрапшир' % spaces)
print()
print()
print('Уважаемый Сэр,')
print()
print('Хочу сообщить вам, что кое-где на крыше уборной')
print('недостает кусков черепицы.')
print('Думаю, прошлой ночью их сдуло внезапным порывом ветра.')
print()
print('С почтением')
print('Малькольм Конфузли')

Введя этот код в новом окне оболочки, сохраните его под именем
myletter.py, выбрав в меню File ▶ Save As. Теперь можете запустить программу, выбрав Run ▶ Run Module (как мы уже делали).

!
Spaces —
пробелы

38

Увидев перед фрагментом кода указание сохранить его под каким-то
именем, знайте, что нужно выбрать в меню File ▶ New File, ввести
код в появившемся окне и сохранить его так же, как в этом примере.

Мы создали переменную spaces, присвоив ей результат умножения
символа «пробел» на 25 (то есть строку из 25 пробелов). В следующих трех
строках программы мы воспользовались этой переменной, чтобы напечатать блок текста со смещением вправо. Вот что должно получиться:

Часть I. Учимся программировать

Помимо выравнивания блоков текста, умножение пригодится
для заполнения экрана надоедливыми сообщениями. Запустите этот
пример самостоятельно:
>>> print(1000 * 'слякоть')

Списки мощнее строк
Паучьи лапки, жабий палец, глаз тритона, крыло летучей мыши, жир
слизня и перхоть змеи — довольно необычный список покупок (если
только вы не колдун или ведьма), но мы воспользуемся им, чтобы показать разницу между строками и списками.
Можно представить этот список в виде строки, поместив ее в переменную wizard_list:
>>> wizard_list = 'Паучьи лапки, жабий палец, глаз тритона, крыло 
летучей мыши, жир слизня, перхоть змеи'
>>> print(wizard_list)
Паучьи лапки, жабий палец, глаз тритона, крыло летучей мыши, жир
слизня, перхоть змеи

Wizard list — волшебный список

Но лучше воспользоваться списком — специальным колдовским объектом языка Python. Вот как будут выглядеть наши ингредиенты в виде
списка:
>>> wizard_list = ['паучьи лапки', 'жабий палец', 'глаз тритона', 
'крыло летучей мыши', 'жир слизня', 'перхоть змеи']
>>> print(wizard_list)
['паучьи лапки', 'жабий палец', 'глаз тритона', 'крыло летучей
мыши', 'жир слизня', 'перхоть змеи']

Чтобы создать список, понадобится ввести чуть больше символов,
чем при создании строки, зато список позволяет обращаться к его элементам (в нашем случае, к покупкам) по отдельности. Например, мы можем напечатать третий элемент из wizard_list, указав в квадратных
скобках его позицию (которую называют индексом), вот так:
>>> print(wizard_list[2])
глаз тритона

3. Строки, списки, кортежи и словари

39

Что такое? Почему в скобках стоит 2, это же третий элемент в списке!
Да, так и есть, однако отсчет элементов в списках начинается с нуля —
то есть первому элементу соответствует индекс 0, второму 1, а третьему 2. Человеку это может показаться странным, однако для компьютеров
такая нумерация естественна.
Также можно заменить элемент списка — это гораздо проще, чем заменить часть строки. Положим, нам требуется не глаз тритона, а язык
улитки. Не проблема, давайте подправим список:
>>> wizard_list[2] = 'язык улитки'
>>> print(wizard_list)
['паучьи лапки', 'жабий палец', 'язык улитки', 'крыло летучей
мыши', 'жир слизня', 'перхоть змеи']

Итак, мы заменили элемент с индексом 2 — прежде это
был глаз тритона — языком улитки.
Также мы можем отобразить только часть элементов
списка — это делается с помощью двоеточия (:) внутри
квад ратных скобок. Например, чтобы вывести на экран
элементы с третьего до пятого (отличные ингредиенты для
бутерброда), введите:
>>> print(wizard_list[2:5])
['язык улитки', 'крыло летучей мыши', 'жир слизня']

Запись [2:5] означает «показать элементы, начиная с индекса 2
и до индекса 5 (но не включая его)», иначе говоря, элементы 2, 3 и 4.
В списках можно хранить значения разных типов, например числа:
Some numbers —
некоторые числа

>>> some_numbers = [1, 2, 5, 10, 20]

Или строки:
Some strings —
некоторые
строки

>>> some_strings = ['Нож', 'отточен', 'точен', 'очень']

Или числа и строки вперемежку:
>>> numbers_and_strings = [7, 'раз', 'отпей', 1, 'раз', 'отъешь']
>>> print(numbers_and_strings)
[7, 'раз', 'отпей', 1, 'раз', 'отъешь']

40

Часть I. Учимся программировать

В списках могут даже храниться другие списки:
>>> numbers = [1, 2, 3, 4, 5]
>>> strings = ['хватит', 'циферки', 'считать']
>>> mylist = [numbers, strings]
>>> print(mylist)
[[1, 2, 3, 4, 5], ['хватит', 'циферки', 'считать']]

Numbers — числа
Strings — строки
My list — мой
список

Мы создали три переменные: numbers с пятью цифрами, strings
с тремя строками и mylist, где хранятся списки numbers и strings.
Причем в третьем списке (mylist) только два элемента, ведь он содержит два других списка, а не их отдельные элементы.

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

Append — добавить

>>> wizard_list.append('медвежий коготь')
>>> print(wizard_list)
['паучьи лапки', 'жабий палец', 'язык улитки', 'крыло летучей
мыши', 'жир слизня', 'перхоть змеи', 'медвежий коготь']

Тем же способом можно и дальше добавлять в колдовской список
ингредиенты:
>>> wizard_list.append('мандрагора')
>>> wizard_list.append('болиголов')
>>> wizard_list.append('болотный газ')

Теперь наш список выглядит так:
>>> print(wizard_list)
['паучьи лапки', 'жабий палец', 'язык улитки', 'крыло летучей мыши',
'жир слизня', 'перхоть змеи', 'медвежий коготь', 'мандрагора',
'болиголов', 'болотный газ']

Судя по всему, готовится нешуточная шалость!

3. Строки, списки, кортежи и словари

41

Удаление элементов из списка
Del — от delete —
удалить

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

>>> del wizard_list[5]
>>> print(wizard_list)
['паучьи лапки', 'жабий палец', 'язык улитки', 'крыло летучей
мыши', 'жир слизня', 'медвежий коготь', 'мандрагора', 'болиголов',
'болотный газ']

!

Не забывайте, что позиции в списке отсчитываются с нуля, поэтому
wizard_list[5] означает шестой элемент списка.

А вот как можно удалить ингредиенты, которые мы добавили последними (мандрагору, болиголов и болотный газ):
>>> del wizard_list[8]
>>> del wizard_list[7]
>>> del wizard_list[6]
>>> print(wizard_list)
['паучьи лапки', 'жабий палец', 'язык улитки', 'крыло летучей
мыши', 'жир слизня', 'медвежий коготь']

Списковая арифметика
Списки можно объединять, складывая их так же, как числа, с помощью
знака «плюс» (+). Например, у нас есть два списка: list1, в котором
хранятся числа от 1 до 4, и list2, где хранится несколько слов. Тогда
мы можем сложить их, воспользовавшись командой print и знаком +.
Вот так:
>>>
>>>
>>>
[1,

list1 = [1, 2, 3, 4, 5]
list2 = ['я', 'забрался', 'под', 'кровать']
print(list1 + list2)
2, 3, 4, 5, 'я', 'забрался', 'под', 'кровать']

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

42

Часть I. Учимся программировать

>>>
>>>
>>>
>>>
[1,

list1 = [1, 2, 3, 4]
list2 = ['я', 'мечтаю', 'о', 'пломбире']
list3 = list1 + list2
print(list3)
2, 3, 4, 'я', 'мечтаю', 'о', 'пломбире']

Также можно умножить список на число с помощью оператора (*).
Например, умножим list1 на 5:
>>> list1 = [1, 2]
>>> print(list1 * 5)
[1, 2, 1, 2, 1, 2, 1, 2, 1, 2]

Фактически это означает «повторить list1 пять раз», поэтому в итоге получается 1, 2, 1, 2, 1, 2, 1, 2, 1, 2.
Но обратите внимание — деление и вычитание со списками не работают. При попытке сделать это вы получите ошибку, как в следующих
примерах:
>>> list1 / 20
Traceback (most recent call last):
File "", line 1, in
list1 / 20
TypeError: unsupported operand type(s) for /: 'list' and 'int'
>>> list1 – 20
Traceback (most recent call last):
File "", line 1, in
list1 – 20
TypeError: unsupported operand type(s) for -: 'list' and 'int'

Но почему? Дело в том, что объединение списков через + и повторение списков с помощью * — это очевидные действия, у которых есть
аналоги в обычной жизни. Например, если я дам вам два списка покупок
и попрошу их объединить, вы можете переписать все пункты этих списков на новый лист бумаги. Также, если я попрошу умножить этот список
на 3, вы трижды перепишете на новый лист все пункты списка.
Ну а как вы будете список делить? Представьте, что вам нужно разделить список из шести чисел (от 1 до 6) на две части. Вот лишь три из множества вариантов:
[1, 2, 3]
[1]
[1, 2, 3, 4]

[4, 5, 6]
[2, 3, 4, 5, 6]
[5, 6]

3. Строки, списки, кортежи и словари

43

Вы разделите список поровну, отделите первый пункт от остальных или возьмете две части наобум? Единственного правильного
ответа здесь нет, поэтому и Python, если попросить его разделить
список, не знает, что делать, и выдает ошибку.
Также не выйдет сложить список с несписковым значением.
Например, вот что произойдет при попытке прибавить число 50
к list1:
>>> list1 + 50
Traceback (most recent call last):
File "", line 1, in
list1 + 50
TypeError: can only concatenate list (not "int") to list

Почему возникла ошибка? Как именно прибавлять 50 к списку? Прибавить 50 к каждому его элементу? А если элементы не числовые? Может,
имеется в виду, что 50 нужно добавить в начало списка как элемент?
В программировании команды должны быть однозначными, чтобы
каждый раз, когда вы вводите команду, происходило одно и то же. Бестолковые компьютеры понимают только крайности — черное или белое.
Дайте компьютеру задание с несколькими вариантами решений и получите в ответ кучу ошибок.

Кортежи
Кортеж похож на список, элементы которого записаны в круглых скобках, как в этом примере:
Fibs —
здесь от fibonacci
sequence —
последовательность Фибоначчи

>>> fibs = (0, 1, 1, 2, 3)
>>> print(fibs[3])
2

Мы определили переменную fibs как набор чисел 0, 1, 1, 2 и 3. И точно так же, как со списками, мы напечатали элемент с индексом 3 с помощью команды print(fibs[3]).
Главное отличие кортежа от списка в том, что кортеж невозможно
изменить после его создания. Например, если мы попытаемся поменять
первое значение кортежа fibs на число 4 (таким же образом, каким меняли значения в списке wizard_list), мы получим сообщение об ошибке:
>>> fibs[0] = 4
Traceback (most recent call last):

44

Часть I. Учимся программировать

File "", line 1, in
fibs[0] = 4
TypeError: 'tuple' object does not support item assignment

Но в чем смысл использования кортежей, если есть списки? Главная
причина такова: порой удобно использовать набор значений, который
никогда не меняется. Создав кортеж с двумя элементами, можно не сомневаться, что в нем и дальше будут только эти два элемента.

Словари в Python — не для поиска слов
Словарями в Python называются наборы значений аналогично спискам
и кортежам. Отличие состоит в том, что каждому элементу словаря соответствуют ключ и связанное с ним значение.
Например, у нас есть перечень людей и их любимых видов спорта.
Можно поместить эту информацию в список, где следом за именем человека указан вид спорта. Вот так:
>>> favorite_sports = ['Ральф Уильямс, Футбол',
'Майкл Типпетт, Баскетбол',
'Эдвард Элгар, Бейсбол',
'Ребекка Кларк, Нетбол',
'Этель Смит, Бадминтон',
'Фрэнк Бридж, Регби']

Если я спрошу, какой у Ребекки Кларк любимый вид спорта, вы можете пробежать список глазами и обнаружить, что это нетбол. Но что если
в списке 100 или больше людей?
Если мы сохраним те же данные в словаре, сделав имя человека ключом, а вид спорта значением, у нас получится следующий код:
>>> favorite_sports = {'Ральф Уильямс': 'Футбол',
'Майкл Типпетт': 'Баскетбол',
'Эдвард Элгар': 'Бейсбол',
'Ребекка Кларк': 'Нетбол',
'Этель Смит': 'Бадминтон',
'Фрэнк Бридж': 'Регби'}

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

3. Строки, списки, кортежи и словари

45

Ключ

Значение

Ральф Уильямс

Футбол

Майкл Типпетт

Баскетбол

Эдвард Элгар

Бейсбол

Ребекка Кларк

Нетбол

Этель Смит

Бадминтон

Фрэнк Бридж

Регби

Таблица 3.1. Ключи и соответствующие им значения
в словаре любимых видов спорта

Favorite sports —
любимые виды
спорта

Теперь, чтобы узнать любимый вид спорта Ребекки Кларк, нужно обратиться к словарю favorite_sports, использовав ее имя в качестве
ключа:
>>> print(favorite_sports['Ребекка Кларк'])
Нетбол

Ответ: нетбол.
Чтобы удалить значение из словаря, тоже используется ключ. Например, удалим Этель Смит:
>>> del favorite_sports['Этель Смит']
>>> print(favorite_sports)
{'Ральф Уильямс': 'Футбол', 'Эдвард Элгар': 'Бейсбол', 'Фрэнк
Бридж': 'Регби', 'Майкл Типпетт': 'Баскетбол', 'Ребекка Кларк':
'Нетбол'}

Ключ нужен и для замены значения в словаре:
>>> favorite_sports['Ральф Уильямс'] = 'Хоккей на льду'
>>> print(favorite_sports)
{'Ральф Уильямс': 'Хоккей на льду', 'Эдвард Элгар': 'Бейсбол',
'Фрэнк Бридж': 'Регби', 'Майкл Типпетт': 'Баскетбол', 'Ребекка
Кларк': 'Нетбол'}

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

46

Часть I. Учимся программировать

Как видите, работа со словарями напоминает работу со списками
и кортежами, однако объединять словари с помощью оператора "+" нельзя. Попытавшись это сделать, вы получите сообщение об ошибке:
>>> favorite_sports = {'Ребекка Кларк': 'Нетбол',
'Майкл Типпетт': 'Баскетбол',
'Ральф Уильямс': 'Хоккей на льду',
'Эдвард Элгар': 'Бейсбол',
'Фрэнк Бридж': 'Регби'}
>>> favorite_colors = {'Малькольм Уорнер': 'Розовый горошек',
'Джеймс Бакстер': 'Оранжевые полоски',
'Сью Ли': 'Пурпурный орнамент'}
>>> favorite_sports + favorite_colors
Traceback (most recent call last):
File "", line 1, in
TypeError: unsupported operand type(s) for +: 'dict' and 'dict'

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

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

3. Строки, списки, кортежи и словари

47

Упражнения
Вот несколько заданий для самостоятельного выполнения. Варианты
их решений можно найти на сайте http://python-for-kids.com/, а также
на страничке книги на сайте http://mann-ivanov-ferber.ru.

#1. Любимые вещи
Games — игры
Foods — блюда

Создайте список своих любимых развлечений и сохраните его в переменной games. Теперь создайте список любимых лакомств, сохранив его
в переменной foods. Объедините два этих списка, сохранив результат
в переменной favorites, и напечатайте значение этой переменной.

#2. Подсчет воинов
Есть 3 дома, на крыше каждого из которых прячутся по 25 ниндзя, и есть
2 туннеля, в каждом из которых скрывается по 40 самураев. Сколько всего воинов решили устроить заварушку? (Ответ можно найти, введя в оболочке Python арифметическое выражение.)

#3. Приветствие
Создайте две переменные: пусть одна хранит ваше имя, а другая фамилию. Теперь с помощью строки с метками %s напечатайте приветствие
вроде такого: «Привет, Брандо Икетт!».

4
РИСОВАНИЕ
С ПОМОЩЬЮ ЧЕРЕПАШКИ

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

Использование модуля черепашки
В Python модулем называется способ подключения полезного кода к другой программе, и в числе прочего модули обычно содержат функции,
к которым можно обращаться. Подробнее мы поговорим об этом в главе 7, а пока скажу лишь, что в Python есть специальный модуль под названием turtle, которым мы и воспользуемся, чтобы изучить основы
создания изображений на экране. С помощью модуля
turtle можно программировать векторную графику,
то есть составлять рисунки из линий, точек и кривых.
Давайте посмотрим, как работает turtle. Запустите оболочку Python, кликнув по значку на рабочем
столе (или, если вы используете Ubuntu, выбрав в меню
Applications ▶ Programming ▶ IDLE). Затем следует
указать, что мы хотим использовать модуль turtle,
и для этого его нужно импортировать. Вот так:

Turtle — черепаха

>>> import turtle

49

Импортирование модуля сообщает Python о том, что мы собираемся
этот модуль использовать.

!

Если вы пользуетесь Ubuntu и, попытавшись импортировать модуль
turtle, получили ошибку, скорее всего, вам нужно установить
пакет tkinter. Для этого откройте центр приложений Ubuntu
и введите в строке поиска python-tk. В списке должен появиться
пункт «Tkinter — Writing Tk Applications with Python». Кликните
Install, чтобы установить этот пакет.

Создание холста

Pen — ручка

Итак, мы импортировали модуль turtle, и теперь нужно создать
холст — чистое пространство для рисования, вроде холста у художников.
Для этого вызовем функцию Pen из модуля turtle, и она автоматически
создаст холст (о том, что такое «функция», мы поговорим позже). Введите
в оболочке Python такую команду:
>>> t = turtle.Pen()

На экране должно появиться белое окно (это холст) со стрелочкой
посередине:

Эта стрелочка в центре окна и есть черепашка. Да уж, на черепаху
она не слишком-то похожа.
Если окно с черепашкой появится позади окна оболочки Python,
могут возникнуть проблемы, и тогда указатель мыши при наведении
на окно с черепашкой примет вид песочных часов, как на рисунке:

50

Часть I. Учимся программировать

Такое может произойти по разным причинам: возможно, вы запустили оболочку не кликом по значку на рабочем столе (если вы используете
Windows или Mac), а как-то иначе, или, быть может, при установке IDLE
произошла ошибка. Закройте оболочку и запустите ее снова, кликнув
по значку на рабочем столе. Если это не поможет, попробуйте вместо оболочки воспользоваться консолью Python:


В Windows выберите Start ▶ All Programs (Пуск ▶ Все программы),
затем в группе Python 3.2 кликните пункт Python (command line).



В Mac OS X кликните по значку Spotlight в правом верхнем углу
экрана и введите Terminal. Когда откроется окно терминала, введите в нем python.



В Ubuntu запустите терминал из меню Applications и введите
python.

Перемещение черепашки
Теперь мы можем давать черепашке команды, вызывая с помощью только что созданной переменной t специальные функции, подобно тому как до этого вызывали функцию
Pen из модуля turtle. Например, команда
forward служит для перемещения черепашки
вперед. Чтобы черепашка сдвинулась на 50 пикселей, введите:
>>> t.forward(50)

Forward — вперед

4. Рисование с помощью черепашки

51

Вы должны увидеть нечто подобное:

Черепашка передвинулась на 50 пикселей. Пиксель — это одна экранная точка, самый маленький элемент изображения. Все, что вы
видите на экране монитора, состоит из пикселей — крошечных квадратных точек. Если посмотреть в увеличении на холст и линию, которую нарисовала черепашка, обнаружится, что и след черепашки, и она
сама — просто набор пикселей. Это и есть самая простая компьютерная
графика.

Точки!

Теперь повернем черепашку на 90 градусов влево, введя такую команду:

Left — налево

>>> t.left(90)

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

52

Часть I. Учимся программировать



Направление, в котором вы смотрите, это 0 градусов.



Если вы вытянете левую руку вбок, это будет 90 градусов влево.



Если вы вытянете вбок правую руку, это будет 90 градусов вправо.

Вот изображение этих 90-градусных поворотов:

0

90°
влево

90°
вправо

Если продолжать двигаться по часовой стрелке от вашей правой руки
и дальше, 180 градусов — это прямо за вашей спиной. 270 градусов —
там, куда указывает левая рука, а 360 градусов — направление вашего
взгляда, то есть точка, откуда мы начали. Получается, что градусы проходят полный круг от 0 до 360. Вот круг, размеченный на градусы слева
направо, с шагом в 45 градусов:

0
315

45

270

90

225

135
180

После того как черепашка повернется влево, она будет смотреть в новом направлении — как если бы вы развернулись на 90 градусов туда,
куда показывает ваша левая рука.
Поэтому команда t.left(90) разворачивает стрелочку острием
вверх (так как вначале она указывала вправо):

4. Рисование с помощью черепашки

53

Right — направо

!

Команда t.left(90) даст тот же результат, что и команда
t.right(270), а t.right(90) соответствует t.left(270). Просто
вообразите себе круг с градусами, и все станет понятно.

Теперь давайте нарисуем квадрат. Добавьте к уже введенным командам вот такие:
>>>
>>>
>>>
>>>
>>>
>>>

t.forward(50)
t.left(90)
t.forward(50)
t.left(90)
t.forward(50)
t.left(90)

Черепашка должна изобразить квадрат и развернуться:

54

Часть I. Учимся программировать

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

Reset — сброс

>>> t.reset()

Либо можно использовать команду clear. Холст также очистится,
но черепашка останется на прежнем месте.
>>> t.clear()

Clear — очистить

Также черепашку можно поворачивать вправо командой right и перемещать назад командой backward. Еще есть команда up, убирающая
перо с холста (иными словами, она говорит черепашке, что ей не надо
оставлять за собой след, то есть рисовать). С помощью команды down рисование можно снова включить. Вызывать эти функции нужно так же,
как и остальные, которыми мы уже пользовались.
Давайте опробуем некоторые из этих команд, создав еще один рисунок. Пусть на этот раз черепашка изобразит две линии. Введите следующий код:
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>

Backward — назад
Up — вверх
Down — вниз

t.reset()
t.backward(100)
t.up()
t.right(90)
t.forward(20)
t.left(90)
t.down()
t.forward(100)

Сперва командой t.reset() мы очистили холст
и переместили черепашку в начальную позицию. Затем с помощью t.backward(100) мы переместили ее
на 100 пикселей назад и вызовом t.up() отключили
рисование.
Далее командой t.right(90) мы развернули черепашку на 90 градусов вправо так, чтобы она указывала вниз, и командой t.forward(20) передвинули
ее на 20 пикселей вперед. При этом на экране ничего
не появилось, ведь раньше мы отключили рисование.
Затем командой t.left(90) мы повернули черепашку на 90 градусов влево, после чего она стала указывать

4. Рисование с помощью черепашки

55

вправо, и командой down снова включили рисование. И наконец, командой t.forward(100) мы прочертили линию, параллельную первой.
В результате вышел такой рисунок:

Что мы узнали
В этой главе мы узнали, как пользоваться модулем turtle. Мы начертили несколько линий с помощью поворотов влево (left) и вправо (right),
а также движений вперед (forward) и назад (backward). Выяснили, что
рисование можно отключить командой up и включить командой down.
Также мы узнали, что для управления поворотами черепашки используются значения в градусах.

56

Часть I. Учимся программировать

Упражнения
Попробуйте нарисовать с помощью черепашки разные фигуры.

#1. Прямоугольник
Создайте новый холст с помощью функции Pen модуля turtle и изобразите на нем прямоугольник.

#2. Треугольник
Создайте новый холст и нарисуйте на нем треугольник. Разворачивая черепашку, сверяйтесь с изображением окружности и градусов поворота
(см. «Перемещение черепашки» на стр. 51).

#3. Рамка без углов
Напишите программу, которая рисует четыре линии, как на этом изображении (размер «квадрата» неважен, только форма):

5
ЗА Д АЕМ ВОПРОСЫ
С ПОМОЩЬЮ IF И ELSE

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

Конструкция if
If — если
Age — возраст

Условную конструкцию if, которая проверяет возраст, хранящийся в переменной age, можно записать, например, так:

>>> age = 13
>>> if age > 20:
print('Как-то вы староваты!')

Конструкция if состоит из ключевого слова if, после которого записано условие, а затем двоеточие, как в строке if age > 20:. Следом

58

за двоеточием должен идти блок команд, и если
ответ на вопрос — «да» (в Python это называется
Истиной и обозначается словом True), находящиеся в этом блоке команды будут выполнены.
А теперь давайте разберемся, как создавать блоки и записывать условия.

True — истина

Блок — это группа команд
Блок — это набор сгруппированных программных конструкций (команд). Скажем, если условие if age > 20: истинно, может понадобиться
выполнить не одно действие (напечатать «Как-то
вы староваты!»), а несколько. Например, вывести
на экран еще несколько вопросов:
>>> age = 25
>>> if age > 20:
print('Как-то вы староваты!')
print('Что вы здесь делаете?')
print('Почему не стрижете газон или не перекладываете 
бумажки?')

Здесь блок состоит из трех команд print, которые должны выполняться лишь в том случае, если условие age > 20 окажется истинным.
Каждая строка кода в блоке начинается с отступа в четыре пробела (относительно конструкции if, стоящей перед блоком). Давайте посмотрим
на этот код еще раз, обозначив пробелы квадратиками:
>>> age = 25
>>> if age > 20:
print('Как-то вы староваты!')
print('Что вы здесь делаете?')
print('Почему не стрижете газон или не перекладываете 
бумажки?')

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

59

блок 1

строка кода
строка кода
строка кода

блок 2

строка кода
строка кода
строка кода
строка кода
строка кода
строка кода

блок 3

строка кода
строка кода

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

блок 1
блок 2

строка кода
строка кода
строка кода
строка кода
строка кода
строка кода

блок 3

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

60

Часть I. Учимся программировать

>>> if age > 20:
print('Как-то вы староваты!')
print('Что вы здесь делаете?')

Я изобразил пробелы квадратиками, чтобы показать разницу. Заметьте, третья строка начинается с шести пробелов, а не с четырех.
Если попробовать запустить этот код, IDLE пометит красным проблемное место в строке и выдаст ошибку синтаксиса с пояснением:
>>> age = 25
>>> if age > 20:
print('Как-то вы староваты!')
print('Что вы здесь делаете?')
SyntaxError: unexpected indent

Unexpected
indent —
неожиданное
выравнивание

Как видим, Python не ожидал встретить два лишних пробела в начале
следующей строки.

!

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

Условия и сравнение значений
Условие — это программная конструкция, которая что-то с чем-то сравнивает, сообщая, является ли заданное соотношение Истиной (True) или
Ложью (False). Например, выражение age > 10 — это условие, которое
как бы задает вопрос: значение переменной age больше, чем 10? Вот другое условие: hair_color == 'лиловый', и ему соответствует вопрос:
равно ли значение переменной hair_color строке 'лиловый'? Для создания условий в языке Python используются специальные символы-операторы, такие как «равно», «больше» или «меньше». Некоторые из этих
операторов показаны в таблице 5.1.
Оператор
==
!=
>
<
>=
10 даст Истину.

!

Проверяя два значения на равенство, используйте двойной знак
«равно» (==).

Давайте рассмотрим еще несколько примеров. Предположим, вы решили создать условную конструкцию, которая печатает «Вы слишком
стары для моих шуток!», если возраст пользователя (age) больше 10 лет:
>>> age = 10
>>> if age > 10:
print('Вы слишком стары для моих шуток!')

Что случится, если вы введете этот код в IDLE и нажмете
на следующей строке Enter?
А ничего не случится.
Поскольку значение age не больше 10, Python не будет выполнять блок с командой print. Однако, если вы дадите переменной age значение 20, сообщение будет напечатано.
Теперь изменим предыдущий пример, поставив в условии
вместо знака «больше» знак «больше или равно» (>=):

>>> age = 10
>>> if age >= 10:
print('Вы слишком стары для моих шуток!')

На экране появится сообщение «Вы слишком стары для моих шуток!»,
ведь age равно 10, и сравнение «age больше или равно 10» дает Истину.
Теперь попробуем сравнение на равенство (==):

>>> age = 10
>>> if age == 10:
print('Что нельзя съесть на завтрак? Обед и ужин!')

На экране должно возникнуть сообщение «Что нельзя съесть на завтрак? Обед и ужин!».

62

Часть I. Учимся программировать

Конструкция if-then-else
Также с помощью команды if можно что-то сделать, если условие не дает
Истину (то есть дает Ложь). Например, если ваш возраст (age) равен 12,
мы можем вывести на экран одно сообщение, а если не равен 12 — другое. Для этого служит конструкция if-then-else, которая работает
по принципу: «если условие дает Истину, сделай это, иначе сделай то».
Давайте опробуем эту конструкцию. Введите в оболочке Python
следующее:

Else — иначе

>>> print("Хотите услышать грязную шутку?")
Хотите услышать грязную шутку?
>>> age = 12
>>> if age == 12:
print("Свинья шлепнулась в грязь!")
else:
print("Тсс! Это секрет.")
Свинья шлепнулась в грязь!

Поскольку мы задали переменной age значение 12, а условие как раз проверяет, равняется ли
age числу 12, на экране появилось первое сообщение. Теперь поменяйте значение age на какоенибудь другое число, например так:

>>> print("Хотите услышать грязную шутку?")
Хотите услышать грязную шутку?
>>> age = 8
>>> if age == 12:
print("Свинья шлепнулась в грязь!")
else:
print("Тсс! Это секрет.")
Тсс! Это секрет.

На этот раз на экране возникло второе сообщение.

Команды if и elif
Конструкцию if можно сделать еще мощнее с помощью ключевого слова elif (это сокращение от else-if). К примеру, мы можем проверять,
чему равен возраст пользователя — 10, 11 или 12 (и так далее), в каждом

Else-if —
иначе-если

5. Задаем вопросы с помощью if и else

63

из этих случаев выполняя разные действия. В отличие от else, в одной
конструкции if может быть несколько вариантов elif:
>>> age = 12
 >>> if age == 10:

print("Что выйдет, если клюква наденет штаны?")
print("Брюква!")
 elif age == 11:
print("Что сказала зеленая виноградина синей 
виноградине?")
print("Дыши! Дыши!")
 elif age == 12:

print("Что сказал 0 числу 8?")
print("Привет, ребята!")
elif age == 13:
print("Что такое: на потолке сидит и хохочет?")
print("Муха-хохотуха!")
else:
print("Что-что?")
Что сказал 0 числу 8? Привет, ребята!

В строке с отметкой  делается проверка, равно ли значение переменной age числу 10. Соответственно, команды print в блоке  будут выполнены, если age равняется 10. Но поскольку мы задали age значение 12,
компьютер переходит на строку , к следующей проверке, где age сравнивается с числом 11. Однако age не равно 11, и компьютер идет дальше,
на строку , чтобы проверить, равняется ли age числу 12. На этот раз условие дает Истину, и компьютер выполняет команды print в блоке .
При вводе этого кода IDLE будет ставить отступы автоматически,
поэтому не забывайте нажимать Delete или Backspace после блоков
с командами print, так чтобы перед командами if, elif и else отступов (пробелов) не было.

64

Часть I. Учимся программировать

Объединение условий
Несколько условий можно объединить в одно с помощью ключевыхслов
and (что означает «и») и or (что означает «или»). Вот пример использования or:
>>> if age == 10 or age == 11 or age == 12 or age == 13:
print('13 + 49 + 84 + 155 + 97: что получится? Головная 
боль!')
else:
print('Что-что?')

Если любое из условий в первой строке даст Истину (если age равняется 10, 11, 12 или 13), будет выполнен блок с командой print на следующей строке.
Если же ни одно из условий не даст Истину, Python перейдет к блоку
после else, напечатав на экране «Что-что?».
Можно сделать этот пример еще компактнее, воспользовавшись
ключевым словом and, а также операторами «больше или равно» (>=)
и «меньше или равно» (>> if age >= 10 and age >> myval = None
>>> print(myval)
None

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

>>> myval = None
>>> if myval == None:
print("В переменной myval ничего нет")
В переменной myval ничего нет

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

Разница между строками и числами
Пользовательским вводом называют данные, которые пользователь вводит с клавиатуры, будь то буква, цифра, нажатие клавиши Enter или чтото еще. Пользовательский ввод попадает в Python в виде строки, а значит,
если вы напечатаете на клавиатуре 10, Python сохранит эту информацию
в переменной как строку, а не как число.
Чем строка '10' отличается от числа 10? Оба значения выглядят
одинаково, разница лишь в том, что одно из них в кавычках. Однако для
компьютера это разные вещи.
Допустим, мы сравниваем значение переменной age с числом с помощью конструкции if:

>>> if age == 10:
print("Как лучше общаться с монстром?")
print("Издалека!")

66

Часть I. Учимся программировать

Теперь дадим переменной age значение 10:
>>> age = 10
>>> if age == 10:
print("Как лучше всего общаться с монстром?")
print("Издалека!")
Как лучше всего общаться с монстром?
Издалека!

Как видите, запустился блок команд print.
Теперь присвоим переменной age строку '10' (в кавычках):
>>> age = '10'
>>> if age == 10:
print("Как лучше всего общаться с монстром?")
print("Издалека!")

В этом случае команды print не сработали, поскольку Python не считает число в кавычках (то есть
строку с цифрами) числом.
К счастью, в Python есть волшебные функции, которые превращают строки в числа и числа в строки.
Например, сделать из строки '10' число может функция int:
>>> age = '10'
>>> converted_age = int(age)

После этого в переменной converted_age будет число 10.
А для преобразования числа в строку служит функция str:

Converted — преобразованный

>>> age = 10
>>> converted_age = str(age)

Теперь значением converted_age будет не число 10, а строка '10'.
Помните команду if age == 10, которая ничего не печатала, когда
значением переменной была строка (age='10')? Если сперва мы преобразуем эту строку в число, результат будет другим:
>>> age = '10'
>>> converted_age = int(age)

5. Задаем вопросы с помощью if и else

67

>>> if converted_age == 10:
print("Как лучше всего общаться с монстром?")
print("Издалека!")
Как лучше всего общаться с монстром?
Издалека!

Однако будьте осторожны: если вы попытаетесь преобразовать так
число с десятичной точкой, произойдет ошибка, поскольку функция int
ожидает, что в строке будет целое число.
>>> age = '10.5'
>>> converted_age = int(age)
Traceback (most recent call last):
File "", line 1, in
converted_age = int(age)
ValueError: invalid literal for int() with base 10: '10.5'
Value error —
ошибка значения
Float — здесь
«десятичная
дробь»

ValueError — это тип ошибки, которым Python сообщает, что значение, которое вы попытались использовать, здесь не подходит. Чтобы
это исправить, нужно заменить функцию int функцией float, которая
может обрабатывать дробные числа.
>>> age = '10.5'
>>> converted_age = float(age)
>>> print(converted_age)
10.5

Python выдаст ошибку ValueError и в том случае, если в строке, которую вы пытаетесь преобразовать, нет цифровых символов:
>>> age = 'десять'
>>> converted_age = int(age)
Traceback (most recent call last):
File "", line 1, in
converted_age = int(age)
ValueError: invalid literal for int() with base 10: 'десять'

68

Часть I. Учимся программировать

Что мы узнали
В этой главе мы научились работать с конструкциями if и создавать
блоки кода, которые выполняются, только если условие дает Истину.
Мы выяснили, что, расширив конструкцию if с помощью elif, можно
выполнять разные блоки кода в зависимости от поставленных условий.
Узнали, как использовать ключевое слово else, выполняя команды, если
ни одно из предыдущих условий не дало Истину. Еще мы научились объединять условия с помощью ключевых слов and и or и так проверять
число на вхождение в диапазон, а также преобразовывать строки в числа
посредством функций int, str и float. И наконец, мы разобрались, что
такое пустое значение None и как его использовать для сброса значений
переменных.

5. Задаем вопросы с помощью if и else

69

Упражнения
Решите эти задачи, используя конструкции if и условия.

#1. Вы богаты?
Как думаете, что делает этот код? Сначала попробуйте в этом разобраться, не вводя код в оболочку Python, а затем проверьте свой ответ.
Money — деньги

>>> money = 2000
>>> if money > 1000:
print("Я богат!")
else:
print("Я не богат!")
print("Может, когда-нибудь потом…")

#2. Бисквитики!
Twinkies — печенье с кремовой
начинкой

Создайте конструкцию if, которая проверяет, действительно ли количество бисквитов (которое задано в переменной twinkies) меньше 100
или больше 500. Если это условие выполняется, пусть ваша программа
напечатает сообщение «Слишком мало или слишком много».

#3. Подходящая сумма
Создайте конструкцию if, которая проверяет, соответствует ли заданная в переменной money сумма денег диапазону значений от 100 до 500
или диапазону значений от 1000 до 5000.

#4. Я одолею этих ниндзя!
Создайте конструкцию if, которая печатает строку «Их слишком много», если количество ниндзя (заданное в переменной ninjas) меньше 50,
печатает «Будет непросто, но я с ними разделаюсь», если это количество
меньше 30, и печатает «Я одолею этих ниндзя!», если количество меньше 10. Проверьте, как ваш код работает с таким значением:
Ninjas — ниндзя

>>> ninjas = 5

6
ПРИШЛО ВРЕМЯ ЗАЦИК ЛИТЬСЯ

Что может быть хуже, чем повторять одно и то же действие снова
и снова? Люди не просто так считают овец, когда им не спится, и дело
тут не в особых снотворных качествах кудрявых парнокопытных.
Суть в том, что без конца заниматься одним и тем же невыносимо
скучно, а человеческому мозгу, когда он не сфокусирован на чем-то
интересном, проще отключиться.
Программисты тоже не слишком любят однообразные действия
(если не страдают бессонницей). К счастью, в большинстве языков
программирования есть конструкция под названием «цикл for», которая автоматически повторяет другие команды и блоки кода.
В этой главе мы изучим цикл for, а также другую разновидность
цикла в языке Python — цикл while.

Использование цикла for
Если нужно пять раз напечатать слово «привет», вы можете сделать
следующее:
>>> print("привет")
привет
>>> print("привет")
привет
>>> print("привет")
привет
>>> print("привет")
привет
>>> print("привет")
привет

71

Только уж очень это утомительно. Однако вы можете сократить размер кода (а также количество повторов), воспользовавшись циклом for:
 >>> for x in range(0, 5):

print('привет')
привет
привет
привет
привет
привет
Range —
диапазон

Функция range в строке  служит для создания списка чисел, который
начинается с первого числа в скобках и заканчивается числом на единицу
меньше второго числа. Чтобы лучше в этом разобраться, давайте посмотрим, как функция range работает вместе с функцией list. Дело в том,
что range не создает готовый список, а возвращает итератор — объект
языка Python, специально придуманный для работы с циклами. Однако,
если передать этот итератор функции list, получится список чисел.
>>> print(list(range(10, 20)))
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

Если вернуться к нашему циклу for, код в строке  будет представлять собой такую инструкцию:


Начать отсчет с 0 и остановиться, не доходя до числа 5.



Каждое отсчитанное значение сохранять в переменной x.

Далее Python исполняет блок кода . Обратите внимание, что этот
блок начинается с отступа в 4 пробела. При вводе программы IDLE ставит
этот отступ автоматически.
После ввода последней строки и нажатия Enter программа напечатает слово «привет» пять раз.
Переменную x можно использовать в команде print для подсчета
«приветов»:
>>> for x in range(0, 5):
print('привет %s' % x)
привет 0
привет 1
привет 2
привет 3
привет 4

72

Часть I. Учимся программировать

Если записать этот код без цикла for, он будет выглядеть примерно
так:
>>> x = 0
>>> print('привет
привет 0
>>> x = 1
>>> print('привет
привет 1
>>> x = 2
>>> print('привет
привет 2
>>> x = 3
>>> print('привет
привет 3
>>> x = 4
>>> print('привет
привет 4

%s' % x)

%s' % x)

%s' % x)

%s' % x)

%s' % x)

Выходит, цикл избавил нас от необходимости писать восемь дополнительных строк кода. Хорошие программисты терпеть не могут делать
одно и то же несколько раз, поэтому цикл — одна из самых популярных
программных конструкций.
При создании цикла for не обязательно использовать функцию
range или list. Вместо этого можно воспользоваться созданным ранее
списком, таким как список ингредиентов из главы 3:
>>> wizard_list = ['паучьи лапки', 'жабий палец', 'язык улитки',
'крыло летучей мыши', 'жир слизня', 'медвежий коготь']
>>> for i in wizard_list:
print(i)
паучьи лапки
жабий палец
язык улитки
крыло летучей мыши
жир слизня
медвежий коготь

Этот код означает следующее: «Для каждого значения из списка wizard_list: сохранить значение
в переменной i и вывести значение этой переменной
на экран». Без цикла for нам бы пришлось написать
что-то вроде такого:

6. Пришло время зациклиться

73

>>> wizard_list = ['паучьи лапки', 'жабий палец', 'язык улитки',
'крыло летучей мыши', 'жир слизня', 'медвежий коготь']
>>> print(wizard_list[0])
паучьи лапки
>>> print(wizard_list[1])
жабий палец
>>> print(wizard_list[2])
язык улитки
>>> print(wizard_list[3])
крыло летучей мыши
>>> print(wizard_list[4])
жир слизня
>>> print(wizard_list[5])
медвежий коготь

И снова цикл сэкономил нам уйму времени и сил.
Давайте создадим еще один цикл. Введите в оболочке следующий
код (отступы IDLE поставит автоматически).
Huge hairy pants —
огромные волосатые штаны

 >>> hugehairypants = ['огромные', 'волосатые', 'штаны']
 >>> for i in hugehairypants:

print(i)

print(i)

 огромные
огромные
волосатые
волосатые
штаны
штаны

В строке программы с меткой  мы создаем список, содержащий
строки 'огромные', 'волосатые' и 'штаны'. В строке  перебираем
элементы этого списка, каждый раз присваивая очередное значение переменной i. В строках  и  дважды выводим содержимое i на экран.
Нажатие Enter в строке  отмечает конец блока, после чего Python запускает введенный ранее код, дважды печатая каждый элемент списка.
Не забывайте, что, введя некорректное число пробелов, вы получите
сообщение об ошибке. Например, если вы поставите в начале строки 
лишний пробел, Python выдаст ошибку выравнивания:
>>> hugehairypants = ['огромные', 'волосатые', 'штаны']
>>> for i in hugehairypants:
print(i)
print(i)
SyntaxError: unexpected indent

74

Часть I. Учимся программировать

Как мы уже знаем из главы 5, Python ожидает, что у всех строк в блоке
будут одинаковые отступы. И неважно, из скольких пробелов состоит отступ, главное, чтобы каждая новая строка блока начиналась с такого же отступа, как и предыдущая (такой код легче для человеческого восприятия).
Вот более сложный пример цикла с двумя блоками кода:
>>> hugehairypants = ['огромные', 'волосатые', 'штаны']
>>> for i in hugehairypants:
print(i)
for j in hugehairypants:
print(j)

Где в этом коде блоки? Первый блок — содержимое первого цикла for:
>>> hugehairypants = ['огромные', 'волосатые', 'штаны']
>>> for i in hugehairypants:
print(i)
#
for j in hugehairypants: # Эти строки — в ПЕРВОМ блоке
print(j)
#

Второй блок состоит из единственной команды print во втором цикле for:
 hugehairypants = ['огромные', 'волосатые', 'штаны']
for i in hugehairypants:
print(i)

for j in hugehairypants:

print(j) # Эта строка — также и во ВТОРОМ блоке

Постарайтесь понять, что напечатает эта небольшая программа.
В строке  создается список hugehairypants, и, глядя на следующие две строки, можно заключить, что цикл переберет все элементы
списка, напечатав каждый из них. Однако в строке  начинается еще
один цикл по тому же списку, причем на этот раз элементы попадают
в переменную j, и далее в строке  каждое значение будет снова напечатано. Строки  и  все еще являются частью первого цикла, а значит,
они будут выполнены для каждого элемента списка по мере их перебора
в первом цикле for, то есть для каждого значения переменной i.
Запустив этот код, вы увидите слово «огромные», затем слова «огромные», «волосатые», «штаны», потом «волосатые» и следом «огромные»,
«волосатые», «штаны» и так далее.

6. Пришло время зациклиться

75

Введите этот код в оболочке Python и убедитесь сами:
>>> hugehairypants = ['огромные', 'волосатые', 'штаны']
>>> for i in hugehairypants:

print(i)
for j in hugehairypants:

print(j)

огромные
огромные
волосатые
штаны

волосатые
огромные
волосатые
штаны

штаны
огромные
волосатые
штаны

В строке с меткой  Python заходит в первый цикл и печатает первый
элемент списка. Затем заходит во второй цикл, где, перебирая список, печатает в строке  все его элементы. После этого снова переходит к команде print(i), печатая второй элемент списка, опять печатает весь список
с помощью второго цикла и print(j), затем то же самое повторяется
для третьего элемента. Значком  я пометил в выводе программы строки, которые печатает команда print(i), строки же без отметок печатает
print(j).
А теперь, как насчет чего-нибудь более полезного, чем печать
каких-то словечек?
Помните вычисления из главы 2, где мы составили выражение для
количества золотых монет, которое вы накопите к концу года, пользуясь копировальным агрегатом дедушки? Выглядело это выражение
так:

>>> 20 + 10 * 365 – 3 * 52

Здесь учитываются 20 найденных монет
плюс 10 волшебных монет, умноженных на
365 дней в году, минус 3 монеты в неделю, которые крадет ворона.

76

Часть I. Учимся программировать

Любопытно посмотреть, как будут расти ваши богатства с каждой неделей. Для этого можно использовать цикл for, но сначала стоит изменить значение переменной magic_coins, чтобы в ней хранилось общее
количество волшебных монет, полученных за неделю. Нужно 10 волшебных монет в день умножить на 7 дней в неделе, то есть magic_coins
будет равняться 70:

Magic coins —
волшебные
монеты

>>> found_coins = 20
>>> magic_coins = 70
>>> stolen_coins = 3

Теперь можно полюбоваться, как приумножаются ваши сокровища.
Для этого понадобится еще одна переменная — coins, а также цикл:

>>>
>>>
>>>
 >>>
 >>>



found_coins = 20
magic_coins = 70
stolen_coins = 3
coins = found_coins
for week in range(1, 53):
coins = coins + magic_coins — stolen_coins
print('Неделя %s = %s' % (week, coins))

В строке  мы присваиваем переменной coins значение переменной
found_coins (найденные монеты, ваш стартовый капитал). В строке 
начинается цикл for, который будет выполнять команды из блока, состоящего из строк  и . При каждом повторе цикла в переменную week
будет попадать номер очередной недели — с первой по 52-ю.
Строка  посложнее. Для каждой недели нам нужно добавлять количество монет, созданных волшебным образом, и вычитать монеты,
украденные вороной. Представьте, что переменная coins — это нечто
вроде сундука с сокровищами, в который каждую неделю попадают
новые монеты. Так что эта строка означает: заменить значение переменной coins суммой ее нынешнего значения и количества монет,
полученных за неделю. Знак «равно» здесь словно указывает: посчитать то, что справа, и сохранить полученное значение в стоящей слева
переменной.
Строка  состоит из команды print, которая с помощью строки
с метками %s печатает номер недели и количество монет, накопленных
на данный момент (если вам непонятно, о чем я, перечитайте раздел «Переменные внутри строк» на стр. 36). Итак, запустив программу, вы увидите что-то вроде:

Week — неделя

6. Пришло время зациклиться

77

Цикл while
Цикл for — не единственный вид циклов в языке Python. Есть также цикл
while, который используется, если нужное количество повторов заранее
неизвестно, тогда как for расчитан на определенное число повторов.
Представьте себе лестницу с 20 ступеньками. Это внутренняя лестница в помещении, и вы знаете, что запросто преодолеете ступеньки. Таков и цикл for.
Step — шаг

>>> for step in range(0, 20):
print(step)

А теперь вообразите лестницу на горе. Гора высокая, и вы можете лишиться сил прежде, чем доберетесь до вершины. К тому же погода может
испортиться, и тогда придется прекратить подъем. На такую лестницу
похож цикл while.

78

Часть I. Учимся программировать

step = 0
while step < 10000:
print(step)
if tired == True:
break
elif badweather == True:
break
else:
step = step + 1

Tired — уставший
Break — перерыв
Bad weather —
плохая погода

Если вы попробуете запустить этот код, возникнет
ошибка. Почему? Потому что мы не создали переменные
tired (признак усталости) и badweather (признак плохой погоды). Для работающей программы здесь не хватает кода, зато это наглядный пример использования цикла
while.
Сперва мы создаем переменную step (ступенька),
присваивая ей значение 0. Затем — цикл while с условием, которое проверяет, меньше ли значение step 10000
(step < 10000), это полное количество ступеней от подножия до вершины горы. И до тех пор, пока это условие
будет давать Истину, остальные строки программы будут
выполняться циклически.
Команда print(step) выводит номер ступеньки, далее мы с помощью if проверяем значение tired на равенство True (Тrue в языке
Python обозначает Истину и является булевым значением; что это такое,
мы выясним в главе 8.) Если tired == True, мы выходим из цикла с помощью команды break. Команда break — это способ немедленного выхода из цикла (иными словами, его завершение), который подходит как
для while, так и для for (при этом программа продолжает выполняться
со строк, идущих после цикла и его блока, впрочем, в нашем примере
таких строк нет).
В строке elif badweather == True: переменная badweather проверяется на равенство True. Если это так, команда break завершит цикл.
И наконец, если ни tired, ни badweather не равны True, выполнится
строчка после else, где мы прибавим 1 к значению step (step = step + 1),
после чего цикл перейдет к следующему повтору.
Итак, цикл while выполняет следующие действия:
1. Проверяет условие.
2. Выполняет код в блоке.
3. Повторяет все сначала.

6. Пришло время зациклиться

79

Часто в цикле while используют не одно условие, а несколько.
Например, так:

And — и

 >>> x = 45
 >>> y = 80
 >>> while x < 50 and y < 100:
x = x + 1
y = y + 1
print(x, y)

В строке  мы создаем переменную x, дав ей значение 45, а в строке  — переменную y со значением 80. Цикл в строке  проверяет два
условия: верно ли, что x меньше 50, и верно ли, что y меньше 100. До тех
пор, пока оба условия дают Истину, будут выполняться следующие строки, где каждая из переменных увеличивается на 1, а затем значения x и y
выводятся на экран.
46
47
48
49
50

81
82
83
84
85

Понимаете, что здесь происходит?
Мы начинаем считать со значения 45 для x и со значения 80 для y,
а затем увеличиваем их на 1 при каждом повторе цикла. Цикл будет выполняться, пока x меньше 50, а y меньше 100. После пяти повторов (при
каждом из которых каждая из двух переменных увеличивалась на 1) значение x достигло 50. Первое условие (x < 50) перестало быть истинным,
и Python завершил цикл.
Еще цикл while часто применяется в качестве условно бесконечного
цикла, который выполняется до тех пор, пока код внутри него не завершит цикл командой break. Примерно так:

Some value —
какое-нибудь
значение

while True:
много кода
много кода
много кода
if some_value == True:
break

В условии цикла while стоит просто True, то есть Истина, а значит, код внутри блока будет выполняться всегда, поэтому цикл

80

Часть I. Учимся программировать

бесконечный. Он будет завершен с помощью break, если переменная
some_value примет значение True. Более удачный пример такого подхода
есть в разделе «Использование randint» на стр. 133, но прежде чем его
изучать, стоит прочесть главу 7.

Что мы узнали
В этой главе мы научились использовать для повторяющихся задач циклы, чтобы избежать утомительных вводов вручную. Группировали
команды, которые нужно дублировать, в блоки кода и помещали их
в циклы. Применяли два вида циклов: for и while. Они похожи, но используются по-разному. Также мы узнали, что ключевое слово break
служит для принудительного завершения циклов.

6. Пришло время зациклиться

81

Упражнения
Вот несколько задач на использование циклов для самостоятельного
выполнения.

#1. Цикл с приветом
Как вы считаете, что делает эта программа? Сперва придумайте вариант
ответа, а потом запустите код и проверьте, угадали ли вы.
>>> for x in range(0, 20):
print('привет %s' % x)
if x < 9:
break

#2. Четные числа
Создайте цикл, который печатает четные числа до тех пор, пока не выведет ваш возраст. Если ваш возраст — нечетное число, создайте цикл, который печатает нечетные числа до совпадения с возрастом. Программа
должна выводить на экран нечто подобное:
2
4
6
8
10
12
14

#3. Пять любимых ингредиентов
Создайте список с пятью разными ингредиентами для бутерброда, наподобие:
Ingredients —
ингредиенты

>>> ingredients = ['слизни', 'пиявки', 'катышки из пупка гориллы',
'брови гусеницы', 'пальцы многоножки']

Теперь создайте цикл, который печатает список ингредиентов с нумерацией:
1 слизни
2 пиявки
3 катышки из пупка гориллы

82

Часть I. Учимся программировать

4 брови гусеницы
5 пальцы многоножки

#4. Ваш лунный вес
Если бы вы сейчас были на Луне, ваш вес составил бы 16,5 процентов от
земного. Чтобы узнать, сколько это, умножьте свой земной вес на 0,165.
Если бы каждый год в течение следующих 15 лет вы прибавляли
по одному килограмму веса, каким бы оказался ваш лунный вес в каждый из ежегодных визитов на Луну вплоть до 15-го года? Напишите программу, которая с помощью цикла for печатает на экране ваш лунный
вес в каждом году.

7
ПОВТОРНОЕ ИСПОЛЬЗОВАНИЕ
КО Д А С ПО М ОЩ ЬЮ ФУ НК Ц ИЙ
И М О Д УЛЕ Й

Подумайте о мусоре, который вы изо дня в день выкидываете на помойку: бутылках и банках, пакетах из-под чипсов, оберточной бумаге, газетах, журналах и так далее. А теперь представьте, что будет,
если свалить весь этот мусор огромной кучей на дороге перед вашим
домом.
Наверное, вы постараетесь как-то избавиться от этого хлама, потому что никому не нравится преодолевать мусорные горы по дороге
в школу. Если отправить все это на переработку, мы сможем заново использовать вещи, которые просто загрязняли бы планету.
В мире программирования повторное использование также играет очень важную роль.
Конечно, ваша программа не будет валяться
на свалке. Однако, если не применять в новых
программах части старого кода, со временем
пальцы сточатся о клавиатуру. Кроме того, повторное использование кода делает программы
короче и понятнее.
Python предлагает несколько способов повторного использования кода.

84

Применение функций
С некоторыми случаями повторного использования кода вы уже знакомы. Например, в прошлой главе с помощью функций range и list мы
получили список с последовательно идущими значениями.
>>> list(range(0, 5))
[0,1,2,3,4]

Конечно, не проблема создать подобный список вручную, но чем
длиннее список, тем больше символов придется вводить. Однако с помощью функций можно за один раз создать список в тысячу чисел.
Вот пример создания такого списка при помощи функций list
и range:
>>> list(range(0, 1000))
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16...,997,998,999]

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

Строение функции
Функция состоит из трех частей: имени, аргументов и тела. Вот пример
простой функции:
>>> def testfunc(myname):
print('Привет, %s' % myname)

Имя этой функции — testfunc. У нее есть единственный аргумент — myname, а ее тело — это блок кода, идущий сразу после строки,
которая начинается с def (сокращение от define — определить). Аргумент — это специальная переменная, которая существует, только пока
функция выполняется.
Функцию testfunc можно запустить (или, как говорят программисты, вызвать), указав ее имя, а после него, в скобках, значение аргумента:

Test func — от test
function — тестовая функция
My name — мое
имя
Def — от define —
определить

85

>>> testfunc('Мэри')
Привет, Мэри

Также можно создать функцию, которая принимает не один, а два,
три или иное количество аргументов (либо, напротив, не принимает аргументы). Например, вот функция testfunc с двумя аргументами:
>>> def testfunc(fname, lname):
print('Привет, %s %s' % (fname, lname))

При вызове функции значения аргументов следует писать через
запятую:
>>> testfunc('Мэри', 'Смит')
Привет, Мэри Смит

В качестве аргументов можно указывать переменные (которые перед
этим нужно создать):
First name — имя
Last name —
фамилия

Return — вернуть

Savings —
сбережения

Pocket money —
карманные
деньги
Paper route —
выручка
за доставку газет
Spending — расходы

>>> firstname = 'Джо'
>>> lastname = 'Робертсон'
>>> testfunc(firstname, lastname)
Привет, Джо Робертсон

Зачастую из функции полезно вернуть какое-то значение. Это делается с помощью команды return. Например, представьте такую функцию
для расчета сбережений:
>>> def savings(pocket_money, paper_route, spending):
return pocket_money + paper_route – spending

Эта функция принимает три аргумента. Вычисляя результат, она
складывает первые два аргумента — pocket_money и paper_route, —
а затем вычитает из полученного значения третий аргумент — spending.
Команда return возвращает результат вычислений в ту часть кода, откуда функция была вызвана, и его можно сохранить в переменной (обычным способом, с помощью знака "=") либо вывести на экран:
>>> print(savings(10, 10, 5))
15

86

Часть I. Учимся программировать

Переменные и область видимости
Переменные, созданные в теле функции, нельзя использовать после того,
как эта функция завершит работу, поскольку они существуют только
во время ее выполнения. В таких случаях программисты говорят, что область видимости переменных ограничена функцией.
Рассмотрим простую функцию, которая использует внутренние переменные, но не принимает аргументы:
 >>> def variable_test():
first_variable = 10
second_variable = 20

return first_variable * second_variable

Здесь в строке  мы создали функцию с именем variable_test, которая в строке  перемножает переменные first_variable и second_
variable и возвращает результат.

Variable test —
тестирование
переменной
First variable —
первая
переменная
Second
variable — вторая
переменная

>>> print(variable_test())
200

Вызвав эту функцию с помощью print, мы получили результат: 200.
Однако, если попытаться за пределами функции вывести на экран значение first_variable (или second_variable), Python выдаст сообщение
об ошибке:
>>> print(first_variable)
Traceback (most recent call last):
File "", line 1, in
print(first_variable)
NameError: name 'first_variable' is not defined

У переменных, созданных вне тела функции, область видимости другая. Например, давайте создадим перед определением нашей функции
переменную, а затем используем ее в теле функции:

 >>> another_variable = 100
>>> def variable_test2():
first_variable = 10
second_variable = 20

return first_variable * second_variable * another_variable

7. Повторное использование кода с помощью функций и модулей

87

Another
variable — другая
переменная

Хотя переменные first_variable и second_variable вне тела
функции недоступны, переменную another_variable (созданную
за пределами функции — в строке ) можно использовать и в теле функции — в строке .
Вот что получится при вызове этой функции:
>>> print(variable_test2())
20000

Теперь представьте, что вы строите звездолет из экономичных материалов, например банок из-под газировки.
Вы планируете сооружать его постепенно, расплющивая
по 2 банки в неделю, а всего потребуется около 500 банок.
Мы можем написать функцию для расчета времени, которое
понадобится, чтобы расплющить 500 банок, если считать,
что в неделю вы справляетесь с двумя.
Пусть наша функция выводит общее количество расплющенных банок для каждой недели от начала строительства
звездолета в течение года. Количество банок в неделю мы будем передавать в аргументе:

Spaceship
building — строительство космического корабля
Cans — банки
Total cans —
общее количество банок
Week — неделя

>>> def spaceship_building(cans):
total_cans = 0
for week in range(1, 53):
total_cans = total_cans + cans
print('Неделя %s, банок: %s' % (week, total_cans))

В первой строке этой функции мы создаем переменную total_cans,
присваивая ей значение 0. Затем мы делаем цикл по неделям в году,
на каждом шаге прибавляя к total_cans количество банок, расплющенных за неделю. Весь этот блок кода и есть тело нашей функции. При
этом в функции есть еще один блок, находящийся внутри первого: это
две последние строки кода, составляющие тело цикла for.
Введем код этой функции в окне оболочки и попробуем вызывать ее
с разными значениями аргумента (для разного количества расплющенных банок в неделю):
>>> spaceship_building(2)
Неделя
Неделя
Неделя
Неделя

88

Часть I. Учимся программировать

1,
2,
3,
4,

банок:
банок:
банок:
банок:

2
4
6
8

Неделя
Неделя
Неделя
Неделя
Неделя
Неделя
(и так

5, банок: 10
6, банок: 12
7, банок: 14
8, банок: 16
9, банок: 18
10, банок: 20
далее...)

>>> spaceship_building(13)
Неделя 1, банок: 13
Неделя 2, банок: 26
Неделя 3, банок: 39
Неделя 4, банок: 52
Неделя 5, банок: 65
(и так далее...)

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

Применение модулей
Модули нужны для группировки функций, переменных и других фрагментов Python-кода. Одни модули идут в комплекте с Python, а другие нужно
скачивать из интернета. Существуют модули, которые помогают создавать
игры (например, идущий с Python tkinter или PyGame, который нужно
отдельно скачивать), модули для работы с изображениями (например,
PIL) и модули для трехмерной графики (к примеру, Panda3D).
С помощью модулей можно решать самые разные задачи. Например,
если вы разрабатываете игру-симулятор и хотите, чтобы игровой мир
реалистично изменялся, можете использовать для расчета текущей даты
и времени модуль time:

tkinter —
от Toolkit
interface —
интерфейс
инструментов
разработки

Time — время

>>> import time

Здесь команда import указывает Python, что
мы собираемся работать с модулем time.
Теперь можно через символ «точка» обращаться к функциям, которые содержатся в этом модуле. (Вспомните вызовы функций для работы с черепашкой из главы 4, такие как t.forward(50)).
Например, вызвать функцию asctime из модуля
time можно следующим образом:

7. Повторное использование кода с помощью функций и модулей

89

>>> print(time.asctime())
'Mon Nov 5 12:40:27 2016'

Sys —
от system —
система

Функция asctime — часть модуля time, которая
возвращает текущие дату и время в виде строки.
А теперь представьте, что у пользователя вашей
программы нужно запросить некое значение, скажем,
возраст или дату рождения. Для этого можно воспользоваться командой print для вывода сообщения с вопросом, а также модулем sys, где находятся инструменты для взаимодействия с интерпретатором Python.
Первым делом нужно импортировать модуль sys:
>>> import sys

Stdin —
от standard
input — стандартный ввод
Read line — прочесть строку

В модуле sys имеется особый объект под названием stdin, для которого задана очень полезная функция — readline. Эта функция считывает строку набранного на клавиатуре текста вплоть до нажатия Enter.
(О том, как устроены объекты, мы поговорим в главе 8.) Давайте проверим работу readline, введя в оболочке следующий код:
>>> import sys
>>> print(sys.stdin.readline())

Если теперь ввести какой-нибудь текст и нажать Enter, этот текст
отобразится в оболочке.
Вернемся к примеру использования конструкции if из главы 5:
Age — возраст

>>> if age >= 10 and age >> def silly_age_joke(age):
if age >= 10 and age >> silly_age_joke(9)
Что-что?
>>> silly_age_joke(10)
13 + 49 + 84 + 155 + 97: что получится? Головная боль!

Ура, работает! Теперь изменим функцию так, чтобы она запрашивала
возраст у пользователя. Менять код функций или добавлять в них новый
код можно сколько угодно раз.
>>> def silly_age_joke():
print('Сколько вам лет?')

age = int(sys.stdin.readline())

if age >= 10 and age >> silly_age_joke()
Сколько вам лет?
10
13 + 49 + 84 + 155 + 97: что получится? Головная боль!
>>> silly_age_joke()
Сколько вам лет?
15
Что-что?

7. Повторное использование кода с помощью функций и модулей

91

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

92

Часть I. Учимся программировать

Упражнения
Вот несколько упражнений по созданию ваших собственных функций.

#1. Функция лунного веса
Одним из заданий к главе 6 было создание цикла for для
расчета вашего веса на Луне в течение 15 лет. Этот цикл
можно оформить в виде функции. Создайте функцию, которая принимает начальный вес и величину, на которую
вес увеличивается каждый год. Вызывать эту новую функцию нужно будет примерно так:
Moon weight —
лунный вес

>>> moon_weight(30, 0.25)

#2. Функция лунного веса и количество лет
Измените функцию из предыдущего задания так, чтобы с ее помощью
можно было рассчитывать вес для разного количества лет, например 5
или 20 лет. Пусть эта функция принимает три аргумента: начальный вес,
прибавку веса в год и количество лет:
>>> moon_weight(90, 0.25, 5)

#3. Программа для лунного веса
Вместо простой функции, принимающей значения в виде аргументов,
можно написать мини-программу, которая будет запрашивать эти значения с помощью sys.stdin.readline(). Тогда этой функции вообще
не нужны аргументы:
>>> moon_weight()

Функция должна запросить начальный вес, потом прибавку веса
в год и количество лет. Тогда работа с программой будет происходить
примерно так:
Введите ваш нынешний земной вес
45
Введите ежегодный прирост вашего веса
0.4

7. Повторное использование кода с помощью функций и модулей

93

Введите количество лет
12

Не забудьте импортировать модуль sys, прежде чем вводить код
функции:
>>> import sys

8
К А К П О Л Ь З О В АТ Ь С Я К Л А С С А М И
И О Б Ъ Е К ТА М И

Чем жираф похож на тротуар? Тем, что и жираф, и тротуар — сущности,
которые в разговорном языке являются именами существительными,
а в языке Python — объектами.
Концепция объектов имеет важное значение в мире программирования. Объекты — это способ организации кода в программе, а также
способ разделения сложных задач на более простые, что облегчает их
решение. (Кстати, в главе 4 нам уже доводилось использовать объект
Pen (ручка) для рисования линий.)
Чтобы как следует разобраться, что такое объекты в Python,
нужно поговорить об их типах. Начнем с жирафов и тротуаров.
Жираф — это тип (или вид, как говорят биологи) млекопитающих, а млекопитающие, в свою очередь, являются одним из типов
животных. Кроме того, жираф — одушевленный объект, поскольку он живой.
Теперь займемся тротуаром. Главное, что можно про него сказать, — он неживой, а значит, относится к неодушевленным объектам. Понятия «млекопитающее», «животное», «одушевленный»
и «неодушевленный» — это способы классификации сущностей.

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

95

Сущности

Неодушевленные

Одушевленные

Тротуары

Животные

Млекопитающие

Жирафы

Class — класс
Things — сущности, вещи

Основной класс — это Сущности. Он имеет два подкласса — Неодушевленные и Одушевленные. Класс Неодушевленные содержит подкласс
Тротуары, а класс Одушевленные — подкласс Животные, у которого есть
подкласс Млекопитающие, а у него, в свою очередь, подкласс Жирафы.
Классы можно использовать и для организации фрагментов кода
в Python-программе. Например, возьмем модуль turtle. Все действия,
которые может выполнять этот модуль — перемещения черепашки вперед и назад, повороты направо и налево и так далее, — являются функциями класса Pen. Объект же является конкретной сущностью, принадлежащей этому классу. Для одного класса можно создать множество
объектов, чем мы скоро и займемся.
А пока давайте создадим такой же набор классов, как на нашей диаграмме, начиная сверху. Чтобы определить класс, нужно ввести ключевое слово class, а затем указать имя класса. Поскольку класс Сущности
(по-английски — Things) — наиболее общий из всех, с него и начнем:
>>> class Things:
pass

Мы дали классу имя Things и использовали конструкцию pass, обозначающую, что больше никакой информации мы указывать не будем.
Pass — команда, с помощью которой можно создавать классы или функции, поначалу не программируя их поведение.

96

Часть I. Учимся программировать

Дальше мы добавим остальные классы и зададим некоторые связи
между ними.

Потомки и предки
Когда один класс является частным случаем (подклассом) другого класса, говорят, что первый класс — потомок, а второй — предок. Один и тот
же класс может быть как потомком некоторых классов, так и предком для
других классов. На нашей диаграмме класс, находящийся прямо над другим классом, — его предок, а класс под другим классом — его потомок.
Например, классы Inanimate и Animate — потомки класса Things, который является их предком.
Для обозначения того, что создаваемый класс является потомком
другого класса, нужно указать имя класса-предка в скобках после имени
нового класса. Вот так:

Inanimate —
неодушевленные
Animate — одушевленные
Things — сущности

>>> class Inanimate(Things):
pass
>>> class Animate(Things):
pass

Здесь мы создали класс Inanimate, указав, что его предком является
класс Things, а затем создали класс Animate, также сделав Things его
предком.
Теперь давайте создадим класс Sidewalks, указав его предком класс
Inanimate:

Sidewalks — тротуары

>>> class Sidewalks(Inanimate):
pass

И наконец, аналогичным образом создадим классы Animals,
Mammals и Giraffes, не забыв указать в скобках имена классов-предков:

>>> class Animals(Animate):
pass

Animals —
животные
Mammals — млекопитающие
Giraffes —
жирафы

>>> class Mammals(Animals):
pass
>>> class Giraffes(Mammals):
pass

8. Как пользоваться классами и объектами

97

Создаем объекты для классов
Теперь, когда у нас есть набор классов, пора создать принадлежащие
им сущности. Предположим, у нас есть жираф по имени Реджинальд.
Мы знаем, что он относится к классу Giraffes. Как именно описать
в программе конкретного жирафа, которого зовут Реджинальд? Будем
считать Реджинальда (reginald) объектом (или, как порой говорят,
экземпляром) класса Giraffes. Чтобы «познакомить» Python с нашим
Реджинальдом, нужно написать следующий код:
>>> reginald = Giraffes()

Этот код означает: создать объект класса Giraffes и присвоить его
переменной reginald. После имени класса ставятся скобки, как после
имени функции. Позже в этой главе мы выясним, как создавать объекты,
используя указанные в этих скобках аргументы.
Что может делать объект reginald? Пока ничего. Чтобы объекты
класса могли решать какие-то задачи, при создании этого класса нужно определить функции, с помощью которых объекты будут делать свое
дело. Таким образом, вместо ключевого слова pass после определения
класса мы можем описать принадлежащие ему функции.

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

This is a normal
function — это
нормальная
функция
This is my silly
class — это мой
глупый класс
This is a class
function — это
функция класса
This is also a class
function — это
тоже функция
класса

98

>>> def this_is_a_normal_function():
print('Я — обычная функция')

А вот несколько функций, принадлежащих классу:

>>> class ThisIsMySillyClass:
def this_is_a_class_function():
print('Я – функция класса')
def this_is_also_a_class_function():
print('Я тоже функция класса, понятно?')

Часть I. Учимся программировать

Используем функции для задания характеристик класса
Рассмотрим классы-потомки класса Animate, которым мы дали определение на стр. 97. Можно задать каждому из них характеристики (описания, что это за класс и что он может делать). Характеристики — это
особенности, присущие всем объектам данного класса, а также объектам
классов-потомков.
Например, что общего у всех животных? Они дышат, двигаются
и едят. А у млекопитающих? Они вскармливают своих детенышей молоком, а также дышат, двигаются и едят. Жирафы, как известно, объедают
листья с верхушек деревьев и, как прочие млекопитающие, кормят детенышей молоком, дышат, двигаются и едят. Если добавить эти характеристики к нашей диаграмме, получится вот что:
Дышать

Животные

Двигаться
Есть

Млекопитающие

Жирафы

Кормить детенышей молоком

Объедать листья с деревьев

Данные характеристики можно представить какдействия, или функции — то, что объект или класс может делать.
Для добавления функций класса мы используем ключевое слово def,
поэтому класс Animals будет выглядеть примерно так:
>>> class Animals(Animate):
def breathe(self):
pass
def move(self):
pass
def eat_food(self):
pass

Breathe — дышать
Move —
двигаться
Eat food — есть
еду

В первой строке мы определили класс — так, как делали это раньше. Однако следующей строкой вместо pass дали определение функции
breathe с одним аргументом self. Аргумент self дает функции класса
возможность вызывать другие функции этого класса (а также классовпредков). Об использовании этого аргумента мы поговорим немного
позже.

8. Как пользоваться классами и объектами

99

Feed young with
milk — кормить
детенышей
молоком
Eat leaves from
trees — есть
листья деревьев

Ключевое слово pass на следующей строке говорит о том, что мы не собираемся больше ничего
сообщать о функции breathe — она пока не выполняет никаких действий. Затем идут определения
функций move и eat_food, которые тоже пока ничего не делают. Скоро мы перепишем наши классы
и добавим в функции подобающий код. Это довольно типичный подход к разработке программ. Часто
программисты создают классы с функциями, которые ничего не делают, чтобы лучше представить,
какими должны быть эти классы, прежде чем переходить к реализации
отдельных функций.
Давайте создадим функции и для двух других классов, а именно
функцию feed_young_with_milk для класса Mammals и функцию eat_
leaves_from_trees для класса Giraffes. Каждый класс будет иметь
доступ к характеристикам (то есть к функциям) своего предка. Следовательно, ни к чему описывать все особенности класса в нем самом, перегружая его сложным кодом: функции могут располагаться в классахпредках, к которым они логически относятся. Таким образом можно
создавать простые и легко читаемые классы.
>>> class Mammals(Animals):
def feed_young_with_milk(self):
pass
>>> class Giraffes(Mammals):
def eat_leaves_from_trees(self):
pass

Зачем нужны классы и объекты?
Мы снабдили классы функциями, однако зачем нужны классы и объекты, если можно было написать обычные функции с именами breathe,
move, eat_food и так далее?
Прояснить этот вопрос нам поможет жираф Реджинальд, которого
мы создали как объект класса Giraffes:
>>> reginald = Giraffes()

Поскольку reginald является объектом, мы можем вызывать функции, определенные в его классе (Giraffes) и в его классах-предках.
Чтобы вызвать такую функцию для объекта, нужно после имени объекта ввести точку, а затем имя функции. Соответственно, можно дать

100

Часть I. Учимся программировать

Реджинальду команду двигаться или есть, вызывая функции таким
образом:
>>> reginald = Giraffes()
>>> reginald.move()
>>> reginald.eat_leaves_from_trees()

Теперь предположим, что у Реджинальда есть друг — жираф, которого зовут Гарольд. Давайте создадим еще один объект класса Giraffes
с именем harold:
>>> harold = Giraffes()

Поскольку мы используем объекты и классы, при вызове функции
move можно указать, к какому жирафу этот вызов относится. Например, если мы хотим, чтобы Гарольд передвинулся, а Реджинальд остался
на месте, нужно вызвать move для объекта harold. Вот так:
>>> harold.move()

И тогда двигаться будет только Гарольд.
Чтобы это увидеть, слегка изменим код наших классов — вместо
pass используем в теле каждой функции команду print:
>>> class Animals(Animate):
def breathe(self):
print('дышит')
def move(self):
print('двигается')
def eat_food(self):
print('ест')
>>> class Mammals(Animals):
def feed_young_with_milk(self):
print('кормит детенышей молоком')
>>> class Giraffes(Mammals):
def eat_leaves_from_trees(self):
print('ест листья')

Теперь, когда мы создадим объекты reginald и harold и станем вызывать для них функции, будет видно, что происходит:

8. Как пользоваться классами и объектами

101

>>> reginald = Giraffes()
>>> harold = Giraffes()
>>> reginald.move()
двигается
>>> harold.eat_leaves_from_trees()
ест листья

В первых двух строках кода мы создали переменные reginald
и harold, которые являются объектами класса Giraffes. Затем вызываем для reginald функцию move, и в следующей строке Python пишет
«двигается». Аналогичным образом вызываем функцию eat_leaves_
from_trees для harold, и Python пишет «ест листья». Если бы это были
настоящие жирафы, а не объекты Python, один из них двигался бы, а другой ел.

Объекты и классы в картинках
Как насчет более наглядного, графического подхода к объектам
и классам?
Давайте вернемся к модулю turtle, с которым мы упражнялись
в главе 4. При вызове функции turtle.Pen() Python создает для нас
объект класса Pen из модуля turtle (аналогично тому, как мы создавали объекты reginald и harold класса Giraffe в предыдущем разделе).
Так же, как мы создавали двух жирафов, можно создать двух черепашек.
Назовем их Эвери (Avery) и Кейт (Kate):
>>> import turtle
>>> avery = turtle.Pen()
>>> kate = turtle.Pen()

Каждый из объектов-черепашек (avery и kate) принадлежит к классу Pen.
Теперь объекты покажут нам свою мощь, ведь после того как объекты-черепашки созданы, можно вызывать функции каждого объекта
по отдельности, чтобы черепашки передвигались и рисовали независимо
друг от друга.
>>> avery.forward(50)
>>> avery.right(90)
>>> avery.forward(20)

Эта последовательность команд переместит Эвери на 50 пикселей вперед, повернет на 90 градусов вправо и переместит вперед на 20 пикселей.

102

Часть I. Учимся программировать

В итоге черепашка будет смотреть вниз. Помните, что вначале черепашки всегда развернуты вправо.
Теперь настала очередь Кейт.
>>> kate.left(90)
>>> kate.forward(100)

Мы развернули Кейт на 90 градусов влево и передвинули вперед
на 100 пикселей. Она будет смотреть вверх.
У нас получилась линия с двумя стрелочками, направленными в разные стороны, причем каждая стрелочка соответствует одному из объектов-черепашек: Эвери смотрит вниз, а Кейт — вверх.

Теперь добавим еще одну черепашку — Джейкоба (Jacob) и переместим его, не беспокоя Эвери и Кейт.
>>> jacob = turtle.Pen()
>>> jacob.left(180)
>>> jacob.forward(80)

8. Как пользоваться классами и объектами

103

Создаем новый объект класса Pen с именем jacob, разворачиваем
его на 180 градусов и перемещаем вперед на 80 пикселей. Теперь у нас
три черепашки, а картинка выглядит так:

Не забывайте, что каждый раз при создании черепашки с помощью
turtle.Pen() в программе возникает новый самостоятельный объект. Каждый из таких объектов принадлежит к классу Pen, и для каждого из них мы можем вызывать одни и те же функции. Однако действия одной черепашки не связаны с действиями остальных: подобно
нашим жирафам (Реджинальду и Гарольду), черепашки Эвери, Кейт
и Джейкоб — независимые объекты. Также обратите внимание: если
мы создадим новый объект, сохранив его в переменной, где до этого
был другой объект, это не означает, что прежний объект тут же исчезнет. Попробуйте сами создать еще одну черепашку Кейт и подвигать ее
по холсту.

Другие полезные свойства объектов и классов
Классы и объекты позволяют удобно группировать функции. Также они
помогают представлять программу как набор небольших фрагментов
кода.
Представьте действительно большую компьютерную программу —
видеоигру или текстовый процессор. Если воспринимать такую программу как неделимое целое, очень сложно будет понять, как она работает,
поскольку объем кода слишком велик. Но стоит разбить эту гигантскую
программу на части — и вы разберетесь, что делает каждая из частей (разумеется, если знаете язык, на котором программа написана).
Кроме того, если большую программу создавать по частям, становится проще распределять работу между разными программистами. Над
наиболее сложными программами (такими как веб-браузер, например)
трудятся целые команды программистов по всему миру, одновременно
работая над разными частями кода.

104

Часть I. Учимся программировать

Допустим, вам нужно доработать некоторые из созданных в этой главе классов (Animals, Mammals и Giraffes),
но времени не хватает, и вы обратились за помощью к друзьям. Тогда работу несложно поделить на части: один человек
займется классом Animals, другой — классом Mammals,
а кому-то достанется Giraffes.

Унаследованные функции
Наверное, вы уже поняли (если читали внимательно), что программисту, который будет дорабатывать класс Giraffes, крупно повезло,
ведь в этом классе можно пользоваться функциями классов Animals
и Mammals, которые написаны другими людьми. Класс Giraffes наследует функции класса Mammals, который, в свою очередь, наследует
функции класса Animals. Иными словами, создав объект-жирафа, мы
получим доступ к функциям класса Giraffes, а также классов Mammals
и Animals. Аналогично, создав объект-млекопитающее, мы сможем
пользоваться функциями классов Mammals и Animals.
Посмотрите еще раз на связь между классами Animals, Mammals и Giraffes. Класс
Animals является предком класса Mammals,
Животные
а он, в свою очередь, — предком класса
Giraffes.
Хоть reginald — объект класса Giraffes,
для него можно вызвать функцию move (двиМлекопитающие
гаться), определенную в классе Animals, так
как функции, определенные в классах-предках, доступны и классам-потомкам:

Mammals — млекопитающие

Дышать
Двигаться
Есть
Я тоже могу
вызывать
эти функции

>>> reginald = Giraffes()
>>> reginald.move()
двигается

Действительно, все функции, которые мы определили для классов
Animals и Mammals, можно вызвать для объекта reginald, поскольку
он наследует эти функции:
>>> reginald = Giraffes()
>>> reginald.breathe()
дышит
>>> reginald.eat_food()
ест
>>> reginald.feed_young_with_milk()
кормит детенышей молоком

8. Как пользоваться классами и объектами

105

Функции, вызывающие другие функции
Вызывая функцию объекта, мы используем имя переменной, в которой этот объект хранится. Например, так мы вызывали для жирафа
Реджинальда функцию move:
>>> reginald.move()

Find food — найти
еду

Если же требуется вызвать функцию move из другой функции, определенной в классе Giraffes, вместо имени переменной следует использовать аргумент self. Таким способом можно вызвать любую функцию
класса (или классов-предков) из другой функции класса. Например, добавим в класс Giraffes функцию find_food:
>>> class Giraffes(Mammals):
def find_food(self):
self.move()
print("Я нашел еду!")
self.eat_food()

Мы создали функцию, которая вызывает две другие функции. Это
весьма распространенный прием программирования — зачастую, создав
полезную функцию, удобно вызывать ее из еще одной функции (и мы
займемся этим в главе 13 при создании игры, для которой нам понадобятся более сложные функции).
Добавим в класс Giraffes еще несколько функций, использующих
self:
>>> class Giraffes(Mammals):
def find_food(self):
self.move()
print("Я нашел еду!")
self.eat_food()
def eat_leaves_from_trees(self):
self.eat_food()
def dance_a_jig(self):
self.move()
self.move()
self.move()
self.move()

Dance a jig — танцевать джигу

106

При создании функций eat_leaves_from_trees и dance_a_
jig мы использовали функции eat_food и move, принадлежащие

Часть I. Учимся программировать

классу-предку Animals. Это допустимо, поскольку функции наследуются. Таким образом можно создавать (а затем вызывать для конкретных объектов класса) функции, которые выполняют несколько действий
подряд. Смотрите, что произойдет при вызове dance_a_jig, — наш
жираф передвинется 4 раза (сообщение «двигается» будет напечатано
четырежды):
>>> reginald = Giraffes()
>>> reginald.dance_a_jig()
двигается
двигается
двигается
двигается

Инициализация объектов
При создании объекта иногда нужно задать какие-нибудь значения
(их также называют свойствами), которые понадобятся для работы
с этим объектом. Подготовка объекта к использованию называется его
инициализацией.
Например, мы хотим задавать количество пятен на шкуре жирафа при создании каждого объекта класса Giraffes (то есть во время
инициализации объекта). Для этого нужно создать функцию с именем
__init__ (обратите внимание, что в начале и в конце стоят по два знака
подчеркивания). Функция с таким названием имеет особое значение для
классов — позволяет задать свойства объекта при его создании, поскольку для каждого нового объекта она вызывается автоматически. Вот как
пользоваться этой функцией:
>>> class Giraffes:
def __init__(self, spots):
self.giraffe_spots = spots

Введя def __init__(self, spots):, мы создали функцию инициализации, которая принимает два аргумента — self и spots. Как
и остальные функции классов, функция инициализации должна принимать значение self первым аргументом. В теле функции строка
self.giraffe_spots = spots присваивает значение аргумента spots
свойству объекта giraffe_spots (свойство — это принадлежащая объекту переменная). Таким образом, эта строка означает «Взять значение
аргумента spots и поместить его в переменную объекта (свойство объекта) с именем giraffe_spots». Как и в случае вызова одной функции
класса из другой, для доступа к свойствам используется аргумент self.

Init —
от initialize —
установить
начальное
состояние
Spots — пятна

8. Как пользоваться классами и объектами

107

Теперь испытаем функцию инициализации, создав еще пару объектов — тоже жирафов (назовем их Освальд и Гертруда) — и проверив,
сколько у них пятен:
>>>
>>>
>>>
100
>>>
150

ozwald = Giraffes(100)
gertrude = Giraffes(150)
print(ozwald.giraffe_spots)
print(gertrude.giraffe_spots)

Мы создали объект класса Giraffes, указав в скобках значение 100.
В результате была вызвана функция __init__ с аргументом spots, равным 100. Затем мы создали еще один объект класса Giraffes, на этот
раз указав для аргумента spots значение 150. И наконец, напечатав значения свойств giraffe_spots для обоих объектов, мы получили 100
и 150. Ура, работает!
Запомните, что после создания объекта (такого как объект ozwald
в этом примере) для обращения к его функциям и свойствам используются точка и имя переменной (например, ozwald.giraffe_spots). Однако при написании функций класса обращаться к этим же свойствам
и функциям нужно через аргумент self (self.giraffe_spots).

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

108

Часть I. Учимся программировать

Упражнения
Чтобы как следует разобраться в классах и объектах, нужно начать ими пользоваться. Постарайтесь выполнить эти задания, не подглядывая в подсказки.

#1. Жирафий танец
Добавьте в класс Giraffes функции, при вызове которых жираф переставлял бы правую или левую ногу вперед либо назад. Назвать их можно так: left_foot_forward, left_foot_back, right_foot_forward
и right_foot_back. Функция, которая ставит левую ногу жирафа вперед, может выглядеть примерно так:
>>> def left_foot_forward(self):
print('левая нога впереди')

Теперь создайте функцию dance, которая научит Реджинальда танцевать (вызывая четыре только что созданные функции для передвижения ног). В результате должен получиться несложный танец:
>>> reginald = Giraffes()
>>> reginald.dance()
левая нога впереди
левая нога сзади
правая нога впереди
правая нога сзади
левая нога сзади
правая нога сзади
правая нога впереди
левая нога впереди

#2. Черепашьи вилы
При помощи четырех черепашек (объектов класса Pen) изобразите вилы,
как на этой картинке (длину линий выберите на свой вкус). Не забудьте
первым делом импортировать модуль turtle!

Left foot forward —
левая нога
вперед
Left foot back —
левая нога назад
Right foot
forward — правая
нога вперед
Right foot back —
правая нога
назад
Dance —
танцевать

9
В С Т Р О Е ННЫЕ ФУ НК Ц ИИ PY T H O N

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

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

Функция abs

Abs —
от absolute —
абсолютный

110

Функция abs возвращает абсолютное значение (модуль) числа, то есть
само число без знака. Например, абсолютное значение 10 равно 10, а абсолютное значение –10 тоже равно 10.
При вызове функции abs нужно передать число или переменную таким образом:

>>> print(abs(10))
10
>>> print(abs(-10))
10

Эту функцию можно использовать, к примеру, для получения абсолютной величины перемещения персонажа в игре
независимо от направления его движения. Скажем, персонаж
сделал три шага вправо (положительное значение 3), а затем
10 шагов влево (отрицательное значение –10). Если не обращать внимания на направление, абсолютные значения этих
перемещений будут равны 3 и 10. Этим можно воспользоваться
в настольной игре, где вы бросаете пару кубиков, а потом делаете необходимое количество ходов (которые определяются
суммой очков, выпавших на обоих кубиках) в любом направлении. Если поместить количество ходов в переменную, с помощью приведенного ниже кода можно узнать, будет персонаж
двигаться или нет. Предположим, когда игрок сделает выбор,
мы хотим отобразить сообщение (в данном случае просто напечатать «Персонаж двигается»):
>>> steps = -3
>>> if abs(steps) > 0:
print('Персонаж двигается')

Steps — шаги

Если бы мы не пользовались abs, конструкция if выглядела бы примерно так:
>>> steps = -3
>>> if steps < 0 or steps > 0:
print('Персонаж двигается')

Как видите, применение abs делает выражение после if немного короче и понятнее.

Функция bool
Название функции bool — это сокращение от термина boolean, то есть
«булево значение». Так программисты называют данные, у которых может
быть лишь одно из двух значений: True или False.

Bool —
от boolean —
булево значение
True — истина
False — ложь

111

Функция bool принимает один аргумент и в зависимости от его значения возвращает True или False. Если аргумент числовой, функция
вернет False для значения 0 и True во всех остальных случаях. Вот примеры использования bool с разными числами:
>>> print(bool(0))
False
>>> print(bool(1))
True
>>> print(bool(1123.23))
True
>>> print(bool(-500))
True

None —
отсутствует

При использовании функции bool с другими типами данных, например со строками, она вернет False для пустого значения (иначе говоря,
для значения None или пустой строки). В остальных случаях она вернет
True:
>>> print(bool(None))
False
>>> print(bool('a'))
True
>>> print(bool(' '))
True
>>> print(bool('Как назвать свинью на соревнованиях по карате? 
Свиная отбивная!'))
True

Также функция bool вернет False для списков, кортежей или словарей, которые не содержат значений (и True в противном случае):

My silly list — мой
глупый список

>>> my_silly_list = []
>>> print(bool(my_silly_list))
False
>>> my_silly_list = ['s', 'i', 'l', 'l', 'y']
>>> print(bool(my_silly_list))
True

Функция bool пригодится, если нужно определить, задано значение
или нет. Например, если мы запросим у пользователя программы год рождения, можно использовать if совместно с bool для проверки введенного значения:

112

Часть I. Учимся программировать

>>> year = input('Год рождения: ')
Год рождения:
>>> if not bool(year.rstrip()):
print('Вам следует ввести год своего рождения')
Вам следует ввести год своего рождения

Year — год

В первой строке кода мы с помощью функции input
запрашиваем ввод значения с клавиатуры, сохраняя его
в переменной year. Если в ответ нажать только клавишу Enter (не вводя перед этим ничего), в переменной
year окажется пустая строка. (В главе 7 мы пользовались другим способом ввода с клавиатуры — sys.
stdin.readline().)
В следующей строке кода мы с помощью if проверяем значение переменной, которое перед этим обрабатывается функцией rstrip (она удаляет все пробелы
в конце строки, если пользователь их введет). В нашем
примере пользователь не ввел значение, поэтому функция bool вернет False. Поскольку в конструкции if
здесь используется операция not (не), что означает
«если функция bool не вернет True», на экране появится сообщение «Вам следует ввести год своего рождения».

Функция dir
Функция dir выдает информацию о любом переданном ей значении.
В сущности, она сообщает, какие функции можно использовать с этим
значением, перечисляя их имена в алфавитном порядке.
Например, чтобы получить имена функций, которые можно использовать со списком, введите:
>>> dir(['это', 'короткий', 'список'])
['__add__', '__class__', '__contains__', '__delattr__',
'__delitem__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__getitem__', '__gt__', '__hash__',
'__iadd__', '__imul__', '__init__', '__iter__', '__le__',
'__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__reversed__', '__rmul__',
'__setattr__', '__setitem__', '__sizeof__', '__str__',
'__subclasshook__', 'append', 'count', 'extend', 'index',
'insert', 'pop', 'remove', 'reverse', 'sort']

Функция dir работает практически с любыми типами значений,
включая строки, числа, функции, модули, объекты и классы. Однако

9. Встроенные функции Python

113

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

>>> dir(1)
['__abs__', '__add__', '__and__', '__bool__', '__ceil__',
'__class__', '__delattr__', '__divmod__', '__doc__', '__eq__',
'__float__', '__floor__', '__floordiv__', '__format__', '__ge__',
'__getattribute__', '__getnewargs__', '__gt__', '__hash__',
'__index__', '__init__', '__int__', '__invert__', '__le__',
'__lshift__', '__lt__', '__mod__', '__mul__', '__ne__',
'__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__',
'__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__',
'__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__',
'__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__',
'__rsub__', '__rtruediv__', '__rxor__', '__setattr__',
'__sizeof__', '__str__', '__sub__', '__subclasshook__',
'__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate',
'denominator', 'imag', 'numerator', 'real']

Popcorn —
попкорн

Используйте функцию dir, чтобы оперативно узнать, как быть с той
или иной переменной. Например, передав dir переменную popcorn,
содержащую строковое значение, вы увидите набор функций строкового класса str (все строки в Python являются объектами строкового
класса):

>>> popcorn = 'Я люблю попкорн!'
>>> dir(popcorn)
['__add__', '__class__', '__contains__', '__delattr__',
'__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__getnewargs__', '__gt__', '__hash__',
'__init__', '__iter__', '__le__', '__len__', '__lt__', '__mod__',
'__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', 'capitalize', 'center', 'count',
'encode', 'endswith', 'expandtabs', 'find', 'format',
'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal',
'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable',
'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower',
'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex',
'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines',
'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper',
'zfill']

114

Часть I. Учимся программировать

Теперь можно воспользоваться функцией help и получить краткую справку по любой функции из этого списка. Например, справка для
функции upper:
>>> help(popcorn.upper)
Help on built-in function upper:

Help — помощь
Upper — здесь
«заглавный
регистр
символов»

upper(...)
S.upper() -> str
Return a copy of S converted to uppercase.

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

Функция eval
Функция eval принимает в качестве аргумента строку и выполняет
ее, считая, что это код на языке Python. Например, в результате вызова
eval('print("вау!")') будет выполнена команда print("вау!").

Eval —
от evaluate —
вычислить,
выполнить

Функция eval работает только с простыми выражениями вроде
такого:
>>> eval('10*5')
50

9. Встроенные функции Python

115

Выражения, состоящие из нескольких строк кода (например, конструкции if), выполнить, как правило, не удастся:
>>> eval('''if True:
print("это не сработает")''')
Traceback (most recent call last):
File "", line 2, in
print("this won't work at all")''')
File "", line 1
if True:
^
SyntaxError: invalid syntax

Функция eval часто используется, чтобы обработать ввод пользователя как Python-выражение. Например, можно написать простую программу-калькулятор, которая запрашивает математическое выражение
и с помощью eval вычисляет результат.
Введенное пользователем выражение считывается как строка, и для
его вычисления нужно преобразовать строку в числа и операторы. Функция eval сделает это автоматически:
>>> your_calculation = input('Введите выражение: ')
Введите выражение: 12*52
>>> eval(your_calculation)
624

Your calculation —
ваш расчет

Мы использовали input для считывания введенной пользователем
строки и ее сохранения в переменной your_calculation. В качестве
выражения мы ввели 12*52 (предположим, это ваш возраст, умноженный
на количество недель в году). Затем вызвали функцию eval, которая вычислила результат: 624.

Функция exec
Exec —
от execute —
выполнять

My small
program — моя
маленькая
программа

116

Функция exec похожа на eval, но с ее помощью можно выполнять более
сложный код. Кроме того, exec, в отличие от eval, не возвращает значения. Например:
>>> my_small_program = '''print('бутерброд')
print('с колбасой')'''
>>> exec(my_small_program)
бутерброд
с колбасой

Часть I. Учимся программировать

Мы сначала создали переменную my_small_program, поместив
туда строку с двумя командами print, разделенными символом новой
строки, а затем вызвали функцию exec для выполнения кода, хранящегося в my_small_program.
Функция exec может пригодиться для запуска небольших программ,
которые главная Python-программа считывает из файлов, то есть для выполнения программ внутри другой программы. Это нужно при разработке больших и сложных приложений. Скажем, можно написать игру
«Дуэль роботов», в которой два робота перемещаются по экрану, стараясь
атаковать друг друга. При этом каждый игрок вместо того, чтобы управлять своим роботом напрямую, создает для него короткую Python-программу. Игра могла бы считывать такие программки и выполнять их
с помощью exec.

Функция float
Функция float преобразует строку или число в вещественное число, то есть в формат с десятичной запятой. Например, число 10 — это целое число, однако
10.0, 10.1 и 10.253 — вещественные числа (не забывайте, что в Python при записи десятичных дробей
используется точка, а не запятая). В отличие от целых, вещественные числа подходят для вычислений,
связанных с деньгами. Также они используются
в графических программах (в частности, в трехмерных играх) для определения, как и где рисовать изображения на экране.
Преобразовать строку в вещественное число можно так:
>>> float('12')
12.0

В строке может быть и десятичная точка:
>>> float('123.456789')
123.456789

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

9. Встроенные функции Python

117

>>> your_age = input('Введите ваш возраст: ')
Введите ваш возраст: 20
>>> age = float(your_age)
>>> if age > 13:
print('Вы на %s лет старше, чем положено' % (age - 13))
Вы на 7.0 лет старше, чем положено

Функция int
Функция int служит для преобразования строки или числа в целое
число, при этом знаки после запятой (если они есть) отбрасываются.
Преобразовать вещественное число в целое можно так:
>>> int(123.456)
123

А так — преобразовать в целое число строку:
>>> int('123')
123

Однако при попытке воспользоваться функцией int для преобразования строки с вещественным числом в целое вы получите ошибку:
>>> int('123.456')
Traceback (most recent call last):
File "", line 1, in
int('123.456')
ValueError: invalid literal for int() with base 10: '123.456'

Как видите, Python вывел сообщение об ошибке — ValueError.

Функция len
Len — от length —
длина

Функция len возвращает «длину» объекта, то есть количество элементов
в нем. Если это строка, функция вернет количество символов. Например,
так можно узнать длину строки «это тестовая строка»:
>>> len('это тестовая строка')
19

118

Часть I. Учимся программировать

Если передать в функцию len список
или кортеж, результатом будет количество
элементов в этом списке или кортеже:

>>> creature_list = ['единорог', 'циклоп', 'фея', 'эльф', 'дракон',
'тролль']
>>> print(len(creature_list))
6

Creature list —
список существ

Для словаря len также вернет количество элементов:
>>> enemies_map = {'Бэтмен' : 'Джокер',
'Супермен' : 'Лекс Лютор',
'Человек-паук' : 'Зеленый гоблин'}
>>> print(len(enemies_map))
3

Enemies map —
карта врагов

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

Fruit — фрукт

>>> fruit = ['яблоко', 'банан', 'клементин', 'питайя']
 >>> length = len(fruit)
 >>> for x in range(0, length):

print('фрукт с индексом %s: %s' % (x, fruit[x]))
фрукт
фрукт
фрукт
фрукт

с
с
с
с

индексом
индексом
индексом
индексом

0:
1:
2:
3:

яблоко
банан
клементин
питайя

В строке с меткой  мы сохранили длину списка в переменной
length, затем в строке  использовали это значение как аргумент функции range при создании цикла. В строке  в цикле перебираем элементы
списка, печатая индекс каждого элемента и его значение. Также с помощью функции len можно напечатать каждый второй или каждый третий
элемент из списка строк.

Функции max и min
Функция max возвращает наибольший элемент списка, кортежа или
строки. Например, для списка чисел:

Max —
от maximum —
наибольший

9. Встроенные функции Python

119

>>> numbers = [5, 4, 10, 30, 22]
>>> print(max(numbers))
30

Можно также найти наибольший символ в строке:
>>> strings = 'строкаСТРОКА'
>>> print(max(strings))
т

Как видно из этого примера, буквы сравниваются по их
позициям в алфавите — чем ближе буква к концу алфавита, тем она больше, при этом строчные буквы всегда больше
прописных, из-за чего наибольший символ здесь «т», а не «Т».
Однако не обязательно передавать в функцию max переменную, где хранится список, кортеж или словарь. Можно
просто указать значения через запятую:
>>> print(max(10, 300, 450, 50, 90))
450

Min —
от minimum —
наименьший

Функция min похожа на max, только возвращает она наименьший
элемент списка, кортежа или строки. Вот тот же пример со списком чисел, где вместо max используется min:
>>> numbers = [5, 4, 10, 30, 22]
>>> print(min(numbers))
4

Представьте, что вы играете в «Угадай число» против команды из четырех игроков, каждый из которых должен назвать число, меньше загаданного вами. Если хотя бы один из ваших оппонентов назовет число
больше, все четверо проиграют, но если все назовут числа меньше, проиграете вы. С помощью max можно быстро проверить, меньше ли все варианты ваших оппонентов загаданного вами числа:
Guess this
number — угадать
число
Player guesses —
угадывает игрок

120

>>> guess_this_number = 61
>>> player_guesses = [12, 15, 70, 45]
>>> if max(player_guesses) > guess_this_number:
print('Бабах! Вы проиграли')

Часть I. Учимся программировать

else:
print('Вы победили')
Бабах! Вы проиграли

Число, которое загадали вы, хранится в переменной guess_this_
number, а варианты ваших противников — в списке player_guesses.
Конструкция if сравнивает максимальное из названных вашими
противниками чисел с guess_this_number, и если хоть один вариант окажется больше вашего, будет напечатано сообщение «Бабах!
Вы проиграли».

Функция range
Как вы уже знаете, функция range используется
в основном в циклах, чтобы выполнить блок кода
определенное количество раз. Первые два аргумента range называются старт и стоп. Пример
использования range с этими двумя аргументами
я уже приводил, когда рассказывал об использовании len с циклами.
Последовательность чисел, которую генерирует range, начинается со значения, переданного в первом аргументе, и заканчивается числом,
которое на единицу меньше второго аргумента.
Например, вот что мы увидим, напечатав числа,
сгенерированные функцией range с аргументами 0 и 5:
>>> for x in range(0, 5):
print(x)
0
1
2
3
4

На самом деле range возвращает специальный объект, называемый итератором, который несколько раз повторяет некое действие.
В данном случае он при каждом обращении выдает очередное число
из последовательности.
Итератор можно преобразовать в список (с помощью функции list).
Напечатав такой список, вы увидите все значения, которые вернул итератор:

List — список

9. Встроенные функции Python

121

>>> print(list(range(0, 5)))
[0, 1, 2, 3, 4]

Функция range может принимать и третий аргумент, называемый
шагом (если этот аргумент не указан, шаг считается равным 1). Что же
будет, если передать в качестве шага число 2? А вот что:
Count by twos —
считать
двойками

>>> count_by_twos = list(range(0, 30, 2))
>>> print(count_by_twos)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28]

Как видите, каждый последующий элемент списка больше предыдущего на 2. И заканчивается список числом 28, которое на 2 меньше стопзначения — числа 30. Можно указать и отрицательный шаг:
Count down
by twos — считать двойками
в обратную
сторону

>>> count_down_by_twos = list(range(40, 10, -2))
>>> print(count_down_by_twos)
[40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 18, 16, 14, 12]

Функция sum
Sum — сумма,
складывать
My list
of numbers — мой
список чисел

Функция sum складывает элементы списка, возвращая их сумму. Пример:
>>> my_list_of_numbers = list(range(0, 500, 50))
>>> print(my_list_of_numbers)
[0, 50, 100, 150, 200, 250, 300, 350, 400, 450]
>>> print(sum(my_list_of_numbers))
2250

В первой строке мы создали список чисел в диапазоне от 0 до 500,
используя range с шагом 50, и вывели этот список на экран. Затем мы
передали список функции sum и напечатали результат — 2250.

Работа с файлами

Open — открыть

122

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

Часть I. Учимся программировать

Создание файла
Мы будем экспериментировать с текстовым файлом под названием
test.txt. Выполните перечисленные далее шаги для той операционной системы, которую вы используете.

Создание нового файла в Windows
Выполните следующие шаги для создания файла test.txt:
1. Выберите Start ▶ All Programs ▶ Accessories ▶ Notepad (Пуск ▶ Все
программы ▶ Стандартные ▶ Блокнот).
2. Введите несколько строк текста.
3. Выберите в меню File ▶ Save (Файл ▶ Сохранить).
4. В диалоговом окне выберите диск C: дважды кликнув My Computer (Компьютер), а затем дважды кликнув Local Disk (C:) (Локальный диск (С:)).
5. Дважды кликните по папке Users (Пользователи), а затем по вашему имени пользователя.
6. В поле ввода File name (Имя файла), которое находится внизу
окна, введите test.txt.
Нажмите кнопку Save (Сохранить).

9. Встроенные функции Python

123

Создание нового файла в Mac OS X
Выполните следующие шаги для создания файла test.txt:
1. Кликните по значку Spotlight в меню вверху экрана.
2. В появившейся строке поиска введите TextEdit.
3. В секции Applications должно появиться приложение TextEdit,
кликните по нему (также TextEdit можно найти в Finder, в папке
Applications).
4. Введите несколько строк текста.
5. Выберите Format ▶ Make Plain Text.
6. Выберите File ▶ Save.
7.

В строке ввода Save As введите test.txt.

8. В списке Places кликните по вашему имени пользователя — имени, под которым вы вошли в систему, или имени человека, которому принадлежит этот компьютер.
9.

124

Нажмите кнопку Save.

Часть I. Учимся программировать

Создание нового файла в Ubuntu
Выполните следующие шаги для создания файла test.txt:
1. Откройте текстовый редактор, который обычно называется Text
Editor. Если вы не пользовались им прежде, поищите его в меню
Applications.
2. Введите несколько строк текста.
3. Выберите File ▶ Save.
4. В строке ввода Name введите test.txt. Скорее всего, ваша домашняя директория уже выбрана в строке Save in Folder. Если нет,
найдите ее в списке Places и кликните по ней. (Название вашей
домашней директории соответствует имени пользователя, под
которым вы вошли в систему.)
5. Кликните по кнопке Save.

Открытие файла в Python
С помощью встроенной функции open можно открыть файл в оболочке
Python и вывести его содержимое на экран. Этой функции нужно сообщить, где находится файл. Как это сделать, зависит от вашей операционной системы. Ознакомьтесь с примером открытия файла в Windows,
а затем прочитайте параграфы, посвященные Mac и Ubuntu, если вы используете одну из этих систем.

9. Встроенные функции Python

125

Открытие файла в Windows
Для открытия файла test.txt введите:
Test file — пробный файл

>>> test_file = open('c:\\Users\\\\
test.txt')
>>> text = test_file.read()
>>> print(text)


В первой строке кода мы вызываем функцию open, которая возвращает
файловый объект, содержащий функции для работы с файлом. В качестве
аргумента для open мы передаем строку со сведениями о местонахождении файла (так называемый путь к файлу). Поскольку ваша система —
Windows и вы сохранили файл в своей пользовательской папке на диске C:,
путь выглядит так: c:\\Users\\\\test.txt.
Двойные знаки «обратный слеш» означают, что это просто «слеш»,
а не специальная команда. (В главе 3 мы обсуждали, что в строках обратный слеш имеет особое значение.) Полученный файловый объект мы
сохраняем в переменной test_file.
Далее мы вызываем функцию файлового объекта read, чтобы получить содержимое файла и сохранить это содержимое в переменной text.
И наконец выводим полученные данные на экран.

Открытие файла в Mac OS X
Путь к файлу test.txt в первой строке кода также должен содержать имя
пользователя, которое вы выбрали при записи файла. Например, если
имя пользователя — sarahwinters, функцию open нужно вызывать так:
>>> test_file = open('/Users/sarahwinters/test.txt')

Открытие файла в Ubuntu
Если вы используете Ubuntu, путь к файлу test.txt в первой строке кода,
как и в предыдущих двух случаях, должен содержать имя пользователя.
Например, если имя пользователя — jacob, функцию open нужно вызывать так:
>>> test_file = open('/home/jacob/test.txt')

126

Часть I. Учимся программировать

Запись в файл
Файловый объект, который возвращает функция open, предоставляет
и другие функции помимо read (читать). Начнем с того, что при вызове
open можно создать новый, пустой файл. Для этого вторым аргументом
следует передать строку 'w':
My file — мой
файл

>>> test_file = open('c:\\myfile.txt', 'w')

Аргумент 'w' означает, что мы собираемся записывать данные в наш
файл, а не читать их.
Теперь можно записать в файл что-нибудь, воспользовавшись функцией write:
>>> test_file = open('c:\\myfile.txt', 'w')
>>> test_file.write('это – тестовый файл')
20

Write — здесь
«записать
(в файл)»

И наконец, нужно сообщить Python, что мы закончили писать
в файл, — вызвать функцию close:

Close — закрыть

>>> test_file = open('c:\\myfile.txt', 'w')
>>> test_file.write('Что это – зеленое и крякает? Жабокряк!')
>>> test_file.close()

Если теперь открыть файл в текстовом редакторе, вы должны увидеть текст «Что это — зеленое и крякает? Жабокряк!». Также можно прочитать файл в оболочке Python:
>>> test_file = open('c:\\myfile.txt')
>>> print(test_file.read())
Что это – зеленое и крякает? Жабокряк!

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

9. Встроенные функции Python

127

Упражнения
Поэкспериментируйте с некоторыми из встроенных функций Python, выполнив эти упражнения.

#1. Таинственный код
Что выведет на экран следующий код? Попробуйте угадать, а затем запустите код и проверьте вашу догадку.
>>>
>>>
>>>
>>>

a = abs(10) + abs(-10)
print(a)
b = abs(-10) + -10
print(b)

#2. Зашифрованное сообщение
Help — помощь,
поддержка

Постарайтесь с помощью функций dir и help узнать, как можно разбить
строку на отдельные слова, а затем напишите небольшую программу, которая печатает слова из следующей строки через одно, начиная с первого
слова («этот»):
"этот если способ вы плохо это подходит читаете для что-то 
шифрования пошло важных не сообщений так"

#3. Копирование файла
Напишите программу для копирования файла. (Подсказка: нужно открыть файл, который вы собираетесь скопировать, считать из него данные, создать новый файл-копию и записать туда считанные данные.)
Проверьте результат работы программы, напечатав содержимое файлакопии на экране.

10
ПО ЛЕ ЗНЫЕ М О ДУЛИ PY T H O N

Как вы уже знаете из главы 7, Python-модуль — это комплект функций,
классов и переменных, собранных вместе для удобства использования.
Например, модуль turtle, с которым мы имели дело в предыдущих главах, объединяет функции и классы для создания холста и рисования с помощью черепашки.
После того как модуль будет импортирован в программу, можно
использовать все содержащиеся в нем элементы. Например, после импортирования модуля turtle в главе 4 мы получили доступ к классу
Pen (ручка) и создали объект этого класса для рисования на экране:
>>> import turtle
>>> t = turtle.Pen()

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

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

129

Species — виды
Number of legs —
количество ног
Сolor — цвет

Допустим, у нас есть класс Animal (животное) с функцией __init__,
которая принимает аргументы species, number_of_legs и color.
>>> class Animal:
def __init__(self, species, number_of_legs, color):
self.species = species
self.number_of_legs = number_of_legs
self.color = color

Теперь можно создать новый объект класса Animal. Пусть это будет
розовый гиппогриф с шестью ногами по имени Гарри (harry).
>>> harry = Animal('гиппогриф', 6, 'розовый')

Copy —
копировать

Если нам нужна стайка шестиногих гиппогрифов, можно несколько
раз повторить предыдущий код, а можно использовать функцию copy
из модуля copy:
>>> import copy
>>> harry = Animal('гиппогриф', 6, 'розовый')
>>> harriet = copy.copy(harry)
>>> print(harry.species)
гиппогриф
>>> print(harriet.species)
гиппогриф

Мы создали объект, сохранив его в переменной harry, а затем —копию этого объекта, сохранив ее в переменной harriet (Гарриет). Данные объекты не зависят друг от друга, хотя и обладают одинаковыми
свойствами.
Таким же образом можно создать и скопировать список объектов
класса Animal.

Carrie — Кэрри
Billy — Билли
My animals — мои
животные
More animals —
больше
животных

130

>>> harry = Animal('гиппогриф', 6, 'розовый')
>>> carrie = Animal('химера', 4, 'в зеленый горошек')
>>> billy = Animal('богл', 0, 'узорчатый')
>>> my_animals = [harry, carrie, billy]
>>> more_animals = copy.copy(my_animals)
>>> print(more_animals[0].species)
гиппогриф
>>> print(more_animals[1].species)
химера

Часть I. Учимся программировать

В первых трех строках кода мы создали три объекта класса
Animal, сохранив их в переменных harry, carrie и billy.
В четвертой строке мы добавили их в список my_animals.
Затем с помощью copy создали новый список more_animals
и напечатали значения свойств species первых двух объектов ([0] и [1]) из этого списка. Обратите внимание: эти значения такие же, как у объектов из первоначального списка.
То есть мы создали копию списка, не пересоздавая хранящиеся в нем объекты.
Однако, если заменить свойство species объекта «гиппогриф» из первоначального списка на «вампир», Python поменяет это свойство и у объекта из списка more_animals!
>>> my_animals[0].species = 'вампир'
>>> print(my_animals[0].species)
вампир
>>> print(more_animals[0].species)
вампир

Мы обращались к списку my_animals. Почему же изменились объекты в обоих списках?
Дело в том, что функция copy создает поверхностную копию — когда
в копируемом объекте содержатся другие объекты, их копий она не делает. В данном случае copy создала копию списка, но не его элементов:
список more_animals содержит те же три объекта, что и my_animals.
В то же время, если мы добавим новое животное в первый список
(my_animals), оно не появится в списке-копии (more_animals). Чтобы
в этом убедиться, после добавления животного выведем длину каждого
из списков на экран:
>>>
>>>
>>>
4
>>>
3

Sally — Салли

sally = Animal('сфинкс', 4, 'песочный')
my_animals.append(sally)
print(len(my_animals))
print(len(more_animals))

Как видите, добавление объекта в список my_animals не повлияло
на его копию — список more_animals. Функция len показала, что в первом списке четыре элемента, тогда как во втором — всего три.
В модуле copy есть другая функция — deepcopy, которая создает копии и для всех объектов внутри копируемого. Если скопировать список

Deep copy — глубокая копия

10. Полезные модули Python

131

my_animals с помощью этой функции, мы получим новый список с копиями всех объектов, и тогда изменение элементов первоначального
списка не повлияет на новый список. Например:
>>> more_animals = copy.deepcopy(my_animals)
>>> my_animals[0].species = 'дракон'
>>> print(my_animals[0].species)
дракон
>>> print(more_animals[0].species)
вампир

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

Ключевые слова и модуль keyword
Keyword — ключевое слово
Is keyword —
является ключевым словом
Kwlist —
от keyword list —
список ключевых
слов

В Python ключевым словом называется слово, являющееся частью языка (например, if, else или for). В модуле keyword есть функция
iskeyword (которая принимает строку и возвращает True, если в ней
находится ключевое слово), а также переменная kwlist, в которой хранится список всех ключевых слов Python.
В следующем примере функция iskeyword возвращает True для
строки if и False — для строки ozwald. При печати переменной kwlist
мы видим полный список ключевых слов. Это может быть важно, поскольку в разных версиях Python ключевые слова могут различаться.

>>> import keyword
>>> print(keyword.iskeyword('if'))
True
>>> print(keyword.iskeyword('ozwald'))
False
>>> print(keyword.kwlist)
['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class',
'continue', 'def', 'del', 'elif', 'else', 'except', 'finally',
'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda',
'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while',
'with', 'yield']

Описание всех ключевых слов можно найти в разделе «Приложение»
на стр. 283.

132

Часть I. Учимся программировать

Генерация случайных чисел с помощью модуля random
В модуле random содержится набор функций для генерации случайных
чисел. Это примерно как попросить компьютер загадать число. Среди
наиболее полезных — функции randint, choice и shuffle.

Random — случайный
Choice — выбор
Shuffle — перетасовка

Использование randint
Функция randint возвращает случайное число из заданного диапазона
значений, скажем, от 1 до 100 или от 1000 до 5000. Например:
>>> import random
>>> print(random.randint(1, 100))
58
>>> print(random.randint(100, 1000))
861
>>> print(random.randint(1000, 5000))
3795

С помощью randint и цикла while можно написать простую игру
«Угадай число»:
>>> import random
>>> num = random.randint(1, 100)
 >>> while True:

print('Угадайте число от 1 до 100')

guess = input()

i = int(guess)

if i == num:
print('Правильно!')

break

elif i < num:
print('Загаданное число больше')

elif i > num:
print('Загаданное число меньше')

Мы импортировали модуль random и сохранили в переменной num
случайное число в диапазоне от 1 до 100, которое вернула функция
randint. Затем в строке с меткой  запустили бесконечный цикл while
(точнее, он будет выполняться до тех пор, пока игрок не угадает число).
В строке  печатаем сообщение «Угадайте число», в строке  с помощью input считываем ответ пользователя, сохраняя его в переменной guess (догадка). В строке  с помощью int преобразуем введенную
строку в целое число, а в строке  сравниваем его со случайным значением num.

Num —
от number —
число

10. Полезные модули Python

133

Если введенное и случайно сгенерированное значения равны, печатаем «Правильно!» и выходим из цикла в строке . В противном случае
в строке  проверяем, не меньше ли введенное число, чем загаданное,
а в строке , — не больше ли оно, выводя соответствующие сообщения.
Этот код не такой уж короткий, и у вас может возникнуть желание
ввести его в новом окне оболочки либо создать новый текстовый файл
с кодом, сохранить его и запустить в IDLE. Давайте вспомним, как открыть и запустить сохраненную программу:
1. Запустите IDLE и выберите File ▶ Open.
2. Найдите папку, где сохранен файл с программой, и кликните
по имени файла.
3. Кликните Open.
4. Когда откроется новое окно, выберите в меню Run ▶ Run Module.
Запустив код последнего примера, вы должны увидеть приблизительно следующее:

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

134

Часть I. Учимся программировать

>>> import random
>>> desserts = ['мороженое', 'блинчики', 'кекс', 'печенье',
'конфеты']
>>> print(random.choice(desserts))
кекс

Desserts —
десерты

Перетасовка списка с помощью shuffle
Функция shuffle перетасовывает (случайным образом перемешивает)
элементы списка. Если параллельно с чтением книги вы запускаете примеры в IDLE и уже импортировали модуль random, а также создали список desserts из предыдущего примера, можете сразу переходить к команде random.shuffle:
>>> import random
>>> desserts = ['мороженое', 'блинчики', 'пирог', 'печенье',
'конфеты']
>>> random.shuffle(desserts)
>>> print(desserts)
['блинчики', 'печенье', 'пирог', 'конфеты', 'мороженое']

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

Управление оболочкой с помощью модуля sys
Модуль sys содержит средства для взаимодействия с самим интерпретатором Python. Мы поговорим об использовании функции exit, объектов
stdin и stdout, а также переменной version.

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

Exit — выход
Yes — да

>>> import sys
>>> sys.exit()

10. Полезные модули Python

135

Однако это сработает только для модифицированной версии IDLE,
про установку которой говорилось в главе 1, иначе вы увидите сообщение об ошибке:
>>> import sys
>>> sys.exit()
Traceback (most recent call last):
File "", line 1, in
sys.exit()
SystemExit

Ввод данных и объект stdin
Stdin —
от standard
input — стандартный ввод
Stdout —
от standard
output — стандартный вывод

Объект stdin из модуля sys служит для ввода информации в программу. Как нам известно из главы 7, у этого объекта есть функция readline,
позволяющая ввести строку текста с клавиатуры — примерно как функция input, которую мы использовали в игре «Угадай число». Например,
введите:

>>> import sys
>>> v = sys.stdin.readline()
Тот, кто смеется последним, медленнее соображает

Python сохранит строку «Тот, кто смеется последним, медленнее соображает» в переменной v. Чтобы в этом убедиться, напечатаем содержимое v:

>>> print(v)
Тот, кто смеется последним, медленнее соображает

Одно из различий между input и readline состоит в том, что для
readline можно задать ограничение количества символов. Например:

>>> v = sys.stdin.readline(13)
Тот, кто смеется последним, медленнее соображает
>>> print(v)
Тот, кто смее

136

Часть I. Учимся программировать

Вывод данных и объект stdout
В отличие от stdin объект stdout предназначен для вывода сообщений в оболочке или консоли. Он позволяет делать то же, что и функция
print, однако stdout — файловый объект, и у него есть файловые функции, о которых мы говорили в главе 9. Например, write:

>>> import sys
>>> sys.stdout.write("У какого слона нет хобота? У шахматного!")
У какого слона нет хобота? У шахматного!40

Функция write возвращает количество напечатанных символов,
поэтому после сообщения и стоит число 40. Можно при каждом вызове
write приплюсовывать это значение к переменной, чтобы всегда знать,
сколько символов мы уже вывели на экран.

Какую версию Python я использую?
Переменная version содержит информацию о версии
Python. Ее значение может пригодиться, в частности, для
проверки, что на компьютере установлена последняя версия
языка. Некоторые программисты предпочитают выводить
информацию о версии Python при старте программы или отображать ее в окне «О программе»:

>>> import sys
>>> print(sys.version)
3.1.2 (r312:79149, Mar 21 2013, 00:41:52) [MSC v.1500 32 bit
(Intel)]

Version — версия

Работа со временем и модуль time
В модуле time есть функции для отображения времени, хотя порой результат их работы может вас удивить:
>>> import time
>>> print(time.time())
1300139149.34

Time — время

10. Полезные модули Python

137

Функция time вернула количество секунд, прошедших
от полуночи 1 января 1970 года до настоящего момента.
Само по себе это число не кажется особо полезным, однако оно может пригодиться, например, для замера времени
выполнения функции. Сохраним значение time до вызова
функции и сразу после, а затем сравним эти числа. Давайте
посмотрим, сколько времени займет печать всех чисел от 0 до 999.
Создадим функцию такого вида:
>>> def lots_of_numbers(max):
for x in range(0, max):
print(x)

Lots of numbers —
много чисел

Проверим ее работу, передав 1000 в качестве аргумента max:
>>> lots_of_numbers(1000)

А теперь, чтобы узнать время работы функции, добавим в ее код вызовы time:
>>> def lots_of_numbers(max):
t1 = time.time()
for x in range(0, max):
print(x)

t2 = time.time()

print('Прошло %s секунд' % (t2-t1))




Запустив функцию еще раз, получим следующий результат (у вас он
может быть другим, поскольку зависит от мощности компьютера):
>>> lots_of_numbers(1000)
0
1
2
3
.
.
.
997
998
999
Прошло 7.231045246124268 секунд

138

Часть I. Учимся программировать

Вот как это работает: вызвав функцию time в первый раз, мы сохранили значение, которое она вернула, в переменной t1 (строка с меткой ).
Затем в цикле, который начинается со строки , напечатали числа от 0
до 999. После цикла, в строке , снова вызвали time, сохранив результат
в переменной t2. Поскольку работа цикла занимает определенное время, значение переменной t2 (количество секунд, прошедших с 1 января
1970 года) будет больше, чем значение t1. Вычтя t1 из t2 в строке , мы
узнали, сколько секунд потребовалось на печать всех чисел.

Преобразование дат с помощью asctime
Функция asctime принимает дату, заданную в виде кортежа, и преобразует ее в более понятный вид (напомню, что кортеж похож на список,
но его элементы нельзя менять). Как мы уже видели в главе 7, вызов
asctime без аргументов возвращает текущие дату и время в читаемом
виде.
>>> import time
>>> print(time.asctime())
Mon Mar 11 22:03:41 2013

Чтобы вызвать asctime с аргументом, создадим кортеж с параметрами даты и времени, сохранив его в переменной t:
>>> t = (2020, 2, 23, 10, 30, 48, 6, 0, 0)

Значения в кортеже соответствуют году, месяцу, дню, часам, минутам, секундам, дню в неделе (0 — понедельник, 1 — вторник и так далее),
дню в году (мы указали 0 в качестве «заглушки») и режиму летнего времени (0 — нет, 1 — да). Передав этот кортеж функции asctime, получим:
>>>
>>>
>>>
Sun

Asc time — узнать
время

Mon Tue Wed Thu
Fri Sat Sun — дни
недели (первые
три буквы),
начиная с понедельника
Jan Feb Mar Apr
May Jun Jul Aug
Sep Oct Nov
Dec — месяцы
(первые три
буквы), начиная
с января

import time
t = (2020, 2, 23, 10, 30, 48, 6, 0, 0)
print(time.asctime(t))
Feb 23 10:30:48 2020

Получаем дату и время с помощью localtime
Функция localtime возвращает текущие дату и время в виде объекта,
содержащего значения примерно того же вида, что и кортеж, который
принимает функция asctime. Напечатав объект, мы увидим имя класса, к которому он принадлежит, а также перечень значений, помеченных

Local time — местное время

10. Полезные модули Python

139

Year — год
Month — месяц

как tm_year (год), tm_mon (месяц), tm_mday (день месяца), tm_hour
(час) и так далее.

Day — день
Hour — час
Minute — минута
Second —
секунда

>>> import time
>>> print(time.localtime())
time.struct_time(tm_year=2020, tm_mon=2, tm_mday=23, tm_hour=22,
tm_min=18, tm_sec=39, tm_wday=0, tm_yday=73, tm_isdst=0)

Чтобы напечатать только текущие год и месяц, нужно получить соответствующие значения по их индексу (аналогично индексам в кортеже
для asctime). Год идет первым (индекс = 0), а месяц вторым (индекс = 1).
Следовательно, мы можем написать: year = t[0], month = t[1]:
>>> t = time.localtime()
>>> year = t[0]
>>> month = t[1]
>>> print(year)
2020
>>> print(month)
2

И видим, что сейчас второй месяц 2020 года.

Делаем передышку с помощью sleep
Sleep — сон

Функция sleep нужна, чтобы замедлить выполнение программы или
приостановить ее. Например, для
печати чисел от 1 до 60 можно использовать такой цикл:

>>> for x in range(1, 61):
print(x)

Этот код быстро напечатает все числа. Однако мы можем задать секундную паузу после вывода каждого числа. Вот так:
>>> for x in range(1, 61):
print(x)
time.sleep(1)

140

Часть I. Учимся программировать

Числа будут выводиться раз в секунду. В главе 12 мы воспользуемся функцией sleep для создания реалистичной анимации.

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

Pickle — букв.
засолить

>>> game_data = {
'позиция-игрока' : 'С23 В45',
'карманы' : ['ключи', 'карманный нож', 'гладкий камень'],
'рюкзак' : ['веревка', 'молоток', 'яблоко'],
'деньги' : 158.50
}

Game data — данные игры

Мы создали словарь, в котором содержится позиция игрока в нашей воображаемой игре, список предметов, которые находятся у игрока
в кармане и рюкзаке, а также количество денег. Теперь можно сохранить
этот словарь в файл, открыв этот файл для записи и воспользовавшись
функцией dump из модуля pickle:
 >>> import pickle
 >>> game_data = {
'позиция-игрока' : 'С23 В45',
'карманы' : ['ключи', 'карманный нож', 'гладкий камень'],
'рюкзак' : ['веревка', 'молоток', 'яблоко'],
'деньги' : 158.50
}
 >>> save_file = open('save.dat', 'wb')
 >>> pickle.dump(game_data, save_file)
 >>> save_file.close()

В строке  мы импортировали модуль pickle, в строке  создали словарь с данными игры. В строке  открываем для записи файл
save.dat, указав аргумент wb, который означает, что мы хотим записывать
данные в бинарном режиме (возможно, файл потребуется создать в пользовательской папке, указав первым аргументом open путь вроде /Users/
malcolmozwald/save.dat, /home/susanb/save.dat или C:\\Users\JimmyIpswich\
save.dat, как мы делали в главе 9). В строке  вызываем функцию dump,
передавая ей два аргумента: наш словарь и переменную с файловым объектом. В строке  закрываем файл, поскольку больше с ним ничего делать не надо.

10. Полезные модули Python

141

!

Load — загрузить
Load file — загрузить файл
Loaded game
data — загруженные данные игры
Rb — от read
binary — прочитать в бинарном
режиме

В текстовых файлах содержатся символы, понятные человеку.
Однако изображения, аудио-, видеофайлы, а также объекты Python,
сохраненные с помощью pickle, обычно содержат информацию,
которую человек прочитать не может. Их называют бинарными
(двоичными) файлами. Если вы откроете файл save.dat в текстовом
редакторе, то увидите, что он не похож на текстовый файл, а представляет собой беспорядочную смесь текста и специальных символов.

Объекты, записанные с помощью pickle, можно снова загрузить.
Для этого понадобится pickle-функция load. Данные из файла будут
преобразованы обратно в значения, которыми может оперировать наша
программа. В целом load используется примерно так же, как dump:
>>> load_file = open('save.dat', 'rb')
>>> loaded_game_data = pickle.load(load_file)
>>> load_file.close()

Открываем файл с аргументом rb, что означает чтение файла в бинарном режиме. Вызываем функцию load, передавая ей файловый объект, а результат ее работы сохраняем в переменной loaded_game_data
и закрываем файл.
Теперь можно убедиться, что данные загрузились без ошибок, напечатав значение переменной:
>>> print(loaded_game_data)
{'позиция-игрока': 'С23 В45', 'карманы': ['ключи', 'карманный
нож', 'гладкий камень'], 'деньги': 158.5, 'рюкзак': ['веревка',
'молоток', 'яблоко']}

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

142

Часть I. Учимся программировать

Упражнения
Попрактикуйтесь в использовании модулей Python, выполнив эти
задания.

#1. Копирование
Что выведет на экран этот код?
>>> import copy
>>> class Car:
pass
>>>
>>>
>>>
>>>
>>>

car1 = Car()
car1.wheels = 4
car2 = car1
car2.wheels = 3
print(car1.wheels)

>>> car3 = copy.copy(car1)
>>> car3.wheels = 6
>>> print(car1.wheels)

Car — машина

Wheels — колеса

Что по
явится
на экр
ане?
Что по
явится
на экр
ане?

#2. Запись и загрузка
Создайте список ваших любимых вещей, а затем с помощью pickle запишите его в файл favorites.dat. Закройте оболочку Python, запустите ее
снова и напечатайте содержимое вашего списка, загрузив его из файла.

Favorites —
любимые

11
И С Н О В А Ч Е Р Е П А Ш Ь Я Г РА Ф И К А

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

Начнем с обычного квадрата
Мы уже знаем, как рисовать линии с помощью черепашки. Нужно импортировать модуль turtle и создать объект Pen:

>>> import turtle
>>> t = turtle.Pen()

Вспомните код для рисования квадрата из главы 4:

>>>
>>>
>>>
>>>
>>>
>>>
>>>

144

t.forward(50)
t.left(90)
t.forward(50)
t.left(90)
t.forward(50)
t.left(90)
t.forward(50)

В главе 6 мы узнали о циклах, и теперь можем упростить этот состоящий из набора одинаковых команд код, воспользовавшись циклом for.
Вот так:
>>> t.reset()
>>> for x in range(1, 5):
t.forward(50)
t.left(90)

Устанавливаем объект Pen (черепашку) в начальную позицию командой reset. Задаем цикл от 1 до 4
с помощью range(1, 5). На каждом повторе цикла перемещаем черепашку вперед на 50 пикселей и разворачиваем ее на 90 градусов влево. Благодаря циклу код
стал заметно короче: если не считать вызов reset, он
занимает три строки вместо шести.

Рисуем звезды
Можно изобразить кое-что поинтереснее, немного изменив цикл.
Введите следующий код:
>>> t.reset()
>>> for x in range(1, 9):
t.forward(100)
t.left(225)

И получится восьмиконечная звезда:

145

Этот код очень похож на код для квадрата, но есть отличия:


вместо четырех повторов (range(1, 5)) делаем восемь (range(1, 9));



перемещаем черепашку не на 50, а на 100 пикселей вперед;



разворачиваем черепашку на 225 градусов, а не на 100.

Теперь давайте изобразим звезду с множеством лучей. Для этого достаточно указать угол в 175 градусов и сделать в цикле 37 повторов:
>>> t.reset()
>>> for x in range(1, 38):
t.forward(100)
t.left(175)

Вот результат работы этого кода:

И раз уж мы занялись звездами, вот код для рисования спиралевидной звезды:
>>> t.reset()
>>> for x in range(1, 20):
t.forward(100)
t.left(95)

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

146

Часть I. Учимся программировать

С помощью однотипного кода, где меняется лишь пара значений,
можно нарисовать немало фигур — от квадрата до спиралевидной звезды. Благодаря циклу for это несложно, а без цикла пришлось бы много
раз вводить одинаковые команды.
Теперь изобразим звезду другого типа, воспользовавшись конструкцией if для управления поворотами черепашки. В этом примере черепашка при
четных повторах цикла разворачивается на 175 градусов, а при нечетных — на 225.
>>> t.reset()
>>> for x in range(1, 19):
t.forward(100)
if x % 2 == 0:
t.left(175)
else:
t.left(225)

Мы задали цикл, тело которого повторяется 18 раз (range(1, 19)). При каждом повторе
перемещаем черепашку на 100 пикселей вперед
(t.forward(100)). Однако теперь в цикле используется конструкция
if (if x % 2 == 0:), в условии которой мы с помощью операции взятия остатка от деления (%) проверяем, содержит ли переменная х четное
число.
Выражение x % 2 означает: что будет в остатке, если мы разделим
число, хранящееся в переменной x, пополам? Например, если поделить

11. И снова черепашья графика

147

Остаток

5

2

2

5 мячиков на две равные части, получится два раза по 2 мячика (всего 4)
и еще один уйдет в остаток, как показано на рисунке.
А если делить на две части 13 мячиков, получится 2 раза по 6 мячиков и один в остатке:
Остаток

13

6

6

Вычисляя, равен ли нулю остаток от деления x на 2, мы, по сути, проверяем, можно ли поделить x на две части без остатка. Это удобный способ выяснить, является ли содержимое переменной четным числом, ведь
четные числа всегда без остатка делятся на 2.
Итак, если значение x четное (if х % 2 == 0:), даем черепашке команду развернуться на 175 градусов влево (t.left(175)). Если нечетное
(else), то на 225 градусов (t.left(225)).
И вот что мы получим, запустив наш код:

148

Часть I. Учимся программировать

Рисуем машину
Черепашка может рисовать не только звезды и простые геометрические
фигуры. Давайте изобразим простенькую, но симпатичную машинку.
Сначала нарисуем кузов. Выберите в меню IDLE File ▶ New File и введите
в новом окне следующий код:
import turtle
t = turtle.Pen()
t.reset()
t.color(1,0,0)
t.begin_fill()
t.forward(100)
t.left(90)
t.forward(20)
t.left(90)
t.forward(20)
t.right(90)
t.forward(20)
t.left(90)
t.forward(60)
t.left(90)
t.forward(20)
t.right(90)
t.forward(20)
t.left(90)
t.forward(20)
t.end_fill()

Теперь добавим переднее колесо:
t.color(0,0,0)
t.up()
t.forward(10)
t.down()
t.begin_fill()
t.circle(10)
t.end_fill()

И заднее колесо:
t.setheading(0)
t.up()
t.forward(90)
t.right(90)
t.forward(10)
t.setheading(0)

11. И снова черепашья графика

149

t.begin_fill()
t.down()
t.circle(10)
t.end_fill()

Выберите File ▶ Save As и назовите файл car.py. Теперь выберите Run ▶
Run Module, чтобы запустить программу. И вот она, наша машинка:

Наверное, вы заметили, что в этом коде появилось несколько новых
команд для черепашки:
Colоr — цвет



с помощью colоr можно задать цвет рисования;

Begin fill — начать
заполнение



команды begin_fill и end_fill позволяют заполнить цветом область на холсте;



сircle рисует окружность указанного размера;



setheading разворачивает черепашку так, чтобы она смотрела
в указанном направлении.

End fill — закончить заполнение
Сircle — круг
Set heading —
здесь «установить
направление»

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

Возьмемся за краски
Функция color принимает три аргумента. Первый определяет количество красного цвета, второй — зеленого, а третий синего. Например,

150

Часть I. Учимся программировать

чтобы раскрасить кузов машины в ярко-красный, мы использовали команду
color(1,0,0), что означает 100-процентную насыщенность красного цвета.
Этот способ смешивания цветов на основе красного, зеленого и синего называется цветовой моделью RGB. Так отображает цвета монитор вашего компьютера: разные пропорции красного, зеленого и синего позволяют получить остальные цвета (примерно так же, как смешение синей
и красной краски дает фиолетовую или как из желтой и красной выходит
оранжевая). Красный, зеленый и синий цвета называют основными, поскольку из них получают остальные цвета.
Хотя для отображения цвета на экране монитора используется не краска, а свет, представим, что RGB-модель состоит из трех банок с краской: красной, зеленой и синей. Каждая банка наполнена до краев. Будем считать, что
полной банке соответствует число 1 (или 100 процентов). Теперь берем всю
красную краску и всю зеленую, смешиваем и получаем желтый цвет (1 и 1,
или по 100 процентов каждого цвета).
Вернемся к программному коду. Чтобы нарисовать желтую окружность, нам нужно по 100 процентов красного и зеленого цвета, а синий
не нужен:
>>>
>>>
>>>
>>>

RGB — от red,
green, blue —
красный, зеленый, синий

t.color(1,1,0)
t.begin_fill()
t.circle(50)
t.end_fill()

Числа 1, 1, 0 в первой строке соответствуют 100 процентам красного,
100 процентам зеленого и 0 процентам синего. В следующей строке мы
говорим, что будем заполнять этим RGB-цветом контуры, которые нарисует черепашка (t.begin_fill), затем даем команду нарисовать окружность (t.circle). Команда end_fill в последней строке указывает, что
окружность нужно заполнить выбранным RGB-цветом.

Функция для рисования заполненной окружности
Чтобы экспериментировать с цветом было проще, оформим код для рисования заполненной окружности в виде отдельной функции:
>>> def mycircle(red, green, blue):
t.color(red, green, blue)
t.begin_fill()
t.circle(50)
t.end_fill()

My circle — мой
круг

Чтобы изобразить ярко-зеленый круг, достаточно дать такую команду:

11. И снова черепашья графика

151

>>> mycircle(0, 1, 0)

А для рисования темно-зеленого круга используем половину (0.5) зеленой краски. Вот так:
>>> mycircle(0, 0.5, 0)

Продолжим исследовать RGB-цвета. Изобразим круг, используя всю
красную краску (1), затем половину (0.5), потом всю синюю, и наконец,
половину синей:
>>>
>>>
>>>
>>>

!

mycircle(1, 0, 0)
mycircle(0.5, 0, 0)
mycircle(0, 0, 1)
mycircle(0, 0, 0.5)

С помощью команды t.reset() холст очищается от старых рисунков. И не забывайте, что черепашку можно перемещать без рисования линий: используйте t.up(), чтобы отключить рисование,
и t.down() — чтобы включить.

Различные комбинации красного, зеленого и синего цвета позволяют
получить всевозможные оттенки, например золотой:
>>> mycircle(0.9, 0.75, 0)

Или светло-розовый:
>>> mycircle(1, 0.7, 0.75)

А вот два оттенка оранжевого:
>>> mycircle(1, 0.5, 0)
>>> mycircle(0.9, 0.5, 0.15)

Попробуйте посмешивать цвета сами!

152

Часть I. Учимся программировать

Получение черного и белого цвета
Что будет, если посреди ночи выключить свет? Все станет черным.
Так же и на экране монитора: нет света — не будет и цвета. Поэтому,
указав 0 для всех основных цветов, мы получим черный:
>>> mycircle(0, 0, 0)

Вот результат:

Если же смешать по 100 процентов всех основных цветов, результат
будет противоположным — получится белый цвет. Введите следующий
код, и белый круг сотрет с холста нарисованный ранее черный:
>>> mycircle(1, 1, 1)

Функция рисования квадрата
Для рисования заполненных цветом фигур нужно включить режим заполнения командой begin_fill и рисовать фигуры. Однако заполнение
начнется только при вызове функции end_fill. Давайте еще немного
поэкспериментируем с рисованием и заполнением. Возьмем функцию
рисования квадрата из начала этой главы и сделаем так, чтобы она принимала размер стороны квадрата в качестве аргумента.
>>> def mysquare(size):
for x in range(1, 5):
t.forward(size)
t.left(90)

My square — мой
квадрат
Size — размер

11. И снова черепашья графика

153

Проверим работу функции, вызвав ее с аргументом 50:
>>> mysquare(50)

Получится квадратик:

Посмотрим, что выйдет, если передавать в нашу функцию разные
значения. Следующий код изобразит пять вложенных квадратов со сторонами 25, 50, 75, 100 и 125.
>>>
>>>
>>>
>>>
>>>
>>>

t.reset()
mysquare(25)
mysquare(50)
mysquare(75)
mysquare(100)
mysquare(125)

Вот что должно получиться:

154

Часть I. Учимся программировать

Рисуем заполненные квадраты
Изобразим заполненный квадрат. Очистим холст, включим режим заполнения и вызовем функцию еще раз:
>>> t.reset()
>>> t.begin_fill()
>>> mysquare(50)

Получившийся квадратик будет пустым, пока мы не вызовем функцию end_fill:
>>> t.end_fill()

В результате квадрат станет таким:

Изменим функцию так, чтобы одним ее вызовом можно было нарисовать либо заполненный квадрат, либо только контур. Для этого придется
добавить еще один аргумент и проверять его значение в теле функции,
так что ее код станет чуть сложнее:
Filled — закрашен

>>> def mysquare(size, filled):
if filled == True:
t.begin_fill()
for x in range(1, 5):
t.forward(size)
t.left(90)
if filled == True:
t.end_fill()

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

11. И снова черепашья графика

155

аргумент filled значению True (filled == True). Если равен, вызываем
функцию begin_fill, которая включает режим заполнения. Затем в четырех повторах цикла (for x in range(0, 4)) рисуем четыре стороны
квадрата (каждый раз перемещая черепашку вперед и разворачивая влево). Проверяем filled на равенство True, вызывая t.end_fill, если это
так — в результате контур закрасится, а режим заполнения отключится.
Теперь, чтобы нарисовать закрашенный квадрат, достаточно одной
команды:
>>> mysquare(50, True)

Или так, чтобы изобразить пустой контур:
>>> mysquare(150, False)

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

И это еще не всё. Рисовать и заполнять цветом можно разные фигуры.

Рисуем закрашенные звезды
В качестве завершающего примера снова изобразим звезду, но заполненную цветом. Наш прежний код выглядел так:
for x in range(1, 19):
t.forward(100)
if x % 2 == 0:
t.left(175)
else:
t.left(225)

156

Часть I. Учимся программировать

Создадим функцию mystar, принимающую размер звезды и признак ее заполнения, использовав в коде две конструкции if из функции
mysquare:

My star — моя
звезда

>>> def mystar(size, filled):
if filled == True:
t.begin_fill()
for x in range(1, 19):
t.forward(size)
if x % 2 == 0:
t.left(175)
else:
t.left(225)
if filled == True:
t.end_fill()

В первых двух строках кода проверяем filled на равенство True
и включаем режим заполнения. Аналогичная проверка выполняется
и в последних двух строках, где мы завершаем заполнение, если filled
равно True. Так же, как и для функции mysquare, размер звезды передаем в аргументе size, используя это значение при вызове t.forward.
Включим золотой цвет рисования (90 процентов красного, 75 — зеленого, 0 — синего) и вызовем нашу функцию:
>>> t.color(0.9, 0.75, 0)
>>> mystar(120, True)

Черепашка нарисует заполненную звезду:

Обведем ее по контуру, включив черный цвет и вызвав функцию снова (на этот раз без заполнения):

11. И снова черепашья графика

157

>>> t.color(0,0,0)
>>> mystar(120, False)

Получится золотая звезда с черной обводкой:

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

158

Часть I. Учимся программировать

Упражнения
Выполните упражнения на рисование фигур с помощью черепашки.

#1. Рисуем восьмиугольник
Мы уже умеем рисовать звезды, квадраты и прямоугольники. А теперь
создадим функцию для рисования восьмиугольника. (Подсказка: для поворота черепашки используйте угол 45 градусов.)

#2. Заполненный восьмиугольник
Измените функцию для рисования восьмиугольника так, чтобы она изображала восьмиугольник заполненным. Попробуйте обвести его контур,
как мы это делали раньше со звездой.

11. И снова черепашья графика

159

#3. Еще одна функция для рисования звезд
Создайте функцию для рисования звезд, которая принимает два аргумента: размер и количество точек, между которыми проведены линии,
составляющие фигуру. Определение этой функции будет начинаться
примерно так:
Draw star — нарисовать звезду
Points — точки

def draw_star(size, points):

12
Б О Л Е Е С О В Е Р Ш Е Н Н А Я Г РА Ф И К А
С М О Д УЛЕ М T K I N T E R

Рисование с помощью черепашки имеет один недостаток: черепашки…
передвигаются... очень… медленно. Даже рекордная черепашья скорость
оставляет желать лучшего. Черепахам это особых неудобств не доставляет, зато сильно ограничивает возможности компьютерной графики.
Компьютерная графика, особенно в играх, требует быстрой отрисовки.
Если у вас есть игровая приставка или вы играете в видеоигры на компьютере, подумайте о том изображении, которое видите на экране. В двухмерных
(2D) играх изображение плоское, персонажи двигаются в основном вверх,
вниз, вправо и влево — как в большинстве игр для Nintendo DS, PlayStation
Portable (PSP) и мобильных телефонов. В псевдотрехмерных играх, которые выглядят почти объемными, изображение более реалистичное, но персонажи обычно
перемещаются в одной плоскости (это называется изометрической графикой). И наконец, есть трехмерные игры,
графика в которых стремится к максимальной реалистичности. Однако все игры — двухмерные, псевдотрехмерные и трехмерные — имеют общую черту: изображения
на экран выводятся очень быстро.
Если вы никогда не занимались анимацией, попробуйте сделать вот что:
1. Возьмите чистый блокнот и нарисуйте что-нибудь в нижнем углу
первой страницы, (например, человечка).
2. В углу следующей страницы нарисуйте такого же человечка почти в той же позе, но слегка сдвиньте одну его ногу.

161

3. На следующей странице снова нарисуйте человечка, сдвинув его
ногу еще немного.
4. Страница за страницей рисуйте в нижнем углу человечка, каждый раз чуть-чуть изменяя его позу.
Когда закончите, быстро пролистайте страницы, глядя на человечка,
и увидите, как он движется. Этот способ лежит в основе любой анимации — телевизионной или компьютерной. На экран выводится картинка, потом выводится снова, но с небольшими изменениями, и так далее.
Возникает иллюзия движения, при этом нужно, чтобы картинки (кадры
анимации) сменяли друг друга очень быстро.
Есть разные способы работы с графикой в языке Python. Помимо модуля turtle можно использовать внешние модули (которые устанавливаются отдельно) или модуль tkinter, который по умолчанию ставится
вместе с Python. Этот модуль позволяет создавать полноценные приложения, вроде несложного текстового редактора, а также работать с графикой. В данной главе мы узнаем, как создавать изображения и анимации
средствами tkinter.

Создаем кнопку
В качестве первого примера воспользуемся tkinter для создания простейшего приложения с одной кнопкой. Введите следующий код:

From — из

>>>
>>>
>>>
>>>

from tkinter import *
tk = Tk()
btn = Button(tk, text="нажми меня")
btn.pack()

В первой строке мы импортировали содержимое модуля tkinter. Конструкция from import *
позволяет обращаться к содержимому модуля, не указывая каждый раз его имя. Вспомните, как, используя
import turtle в предыдущих примерах, мы обращались к функциям модуля через имя turtle:
import turtle
t = turtle.Pen()

Если воспользоваться import *, то не нужно писать turtle.Pen,
как мы делали в главах 4 и 11. В случае с turtle особых преимуществ
это не дает, но данный способ удобен при использовании модулей,

162

Часть I. Учимся программировать

содержащих множество классов и функций, так как позволяет вводить
меньше кода.
from turtle import *
t = Pen()

Во второй строке примера с кнопкой (tk = Tk()) мы создали переменную и сохранили в ней объект класса Tk (аналогично созданию объекта Pen для черепашки). Объект tk создает пустое окно, в которое можно добавлять кнопки, строки ввода, холсты для рисования и так далее.
Это основной класс модуля tkinter. Без создания объекта класса Tk работать с графикой или анимацией с помощью этого модуля невозможно.
В третьей строке мы создали кнопку вызовом btn = Button, передав
первым аргументом переменную tk, а вторым — строку "нажми меня"
(текст, который нужно отобразить на кнопке). Несмотря на то что мы
добавили кнопку в окно, она не появится на экране до ввода команды
btn.pack(), которая включает ее отображение. Также эта команда
управляет выравниванием кнопок и других графических элементов
в окне. В результате получится примерно следующее:

Button — кнопка

От кнопки нажми меня не слишком много пользы — чтобы при нажатии на нее что-то происходило, код нужно изменить. (Перед этим не забудьте закрыть созданное ранее окно!)
Создадим функцию, которая выводит сообщение:
>>> def hello():
print('привет')

Hello — привет

Изменим код примера, пользуясь этой функцией:
>>>
>>>
>>>
>>>

from tkinter import *
tk = Tk()
btn = Button(tk, text="нажми меня", command=hello)
btn.pack()

Command —
команда

12. Более совершенная графика с модулем tkinter

163

Обратите внимание: мы лишь слегка изменили предыдущий код, добавив аргумент command, указывающий, что при клике мышкой по кнопке нужно вызывать функцию hello.
Если теперь кликнуть по кнопке, в окне оболочки появится сообщение «привет». Оно будет выводиться при каждом клике. На картинке
ниже видно, что я нажал кнопку пять раз.

В этом примере мы впервые использовали именованные аргументы,
поэтому поговорим об этом подробнее.

Именованные аргументы

Person — человек
Width — ширина
Height — высота

Именованные аргументы не отличаются от обычных, но чтобы определить, какое значение при вызове функции к какому аргументу относится, нужно использовать не очередность (первое значение — первый аргумент, второе — второй и так далее), а имена аргументов. Тогда порядок
передачи значений роли уже не играет.
Некоторые функции принимают множество аргументов, причем некоторые из них указывать не обязательно. Именованные аргументы позволяют указать значения только для тех аргументов, которые мы хотим
задать.
Допустим, у нас есть функция person, принимающая два аргумента:
width и height.

>>> def person(width, height):
print('Моя ширина - %s, а высота - %s' % (width, height))

164

Часть I. Учимся программировать

Обычно мы вызываем подобные функции так:
>>> person(4, 3)
Моя ширина – 4, а высота - 3

Именованные аргументы позволяют вызвать эту функцию, указывая
для каждого значения имя соответствующего аргумента:
>>> person(height=3, width=4)
Моя ширина – 4, а высота - 3

Чем ближе мы будем знакомиться с модулем tkinter, тем полезнее
будут для нас именованные аргументы.

Создаем холст для рисования
Кнопки — полезные элементы управления. Однако, если мы хотим нарисовать что-то на экране, толку от них немного. Чтобы создать новое
изображение, нужен другой элемент, а именно холст — объект класса
Canvas, который тоже входит в модуль tkinter.
Для создания холста нужно указать его ширину (width) и высоту
(height). В остальном код аналогичен созданию кнопки. Например:
>>>
>>>
>>>
>>>

Canvas — холст

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=500, height=500)
canvas.pack()

Как и в примере с кнопкой, при
вводе строки tk = Tk() на экране
появится окно. В последней строке кода мы вызываем функцию

canvas.pack(), после чего
холст примет размеры 500 пикселей в ширину и 500 в высоту, как
указано в третьей строке кода.
Аналогично примеру с кнопкой, функция pack размещает
холст внутри окна. Без вызова
этой функции содержимое окна
не будет отображаться правильно.

Pack — упаковать, разместить

12. Более совершенная графика с модулем tkinter

165

Рисование линий
В tkinter для рисования линий на холсте используются координаты
в пикселях. Координаты — это два числа, которые определяют, насколько
пиксель (точка) отстоит от левого края холста по горизонтали и от верхнего края холста по вертикали.
Поскольку наш холст занимает 500 пикселей в ширину и 500 в высоту, его правому нижнему углу соответствуют координаты (500, 500).
Чтобы изобразить линию, показанную на рисунке ниже, нужно начать
рисование с координат (0, 0) и закончить координатами (500, 500).

Create line —
создать линию

Эти координаты нужно передать функции create_line, которая рисует линию на холсте. Вот так:

>>>
>>>
>>>
>>>
>>>
1

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=500, height=500)
canvas.pack()
canvas.create_line(0, 0, 500, 500)

Функция create_line вернула число 1 (это идентификатор, и мы
поговорим об этом позже). Чтобы нарисовать такую же линию с помощью
черепашки, нам пришлось бы написать следующий код:

166

Часть I. Учимся программировать

>>>
>>>
>>>
>>>
>>>
>>>
>>>

import turtle
turtle.setup(width=500, height=500)
t = turtle.Pen()
t.up()
t.goto(-250, 250)
t.down()
t.goto(500, -500)

Go to — перейти к

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

Рисование прямоугольников
Раньше мы рисовали прямоугольники, двигая черепашку
вперед, поворачивая, затем снова двигая вперед, опять поворачивая и так далее. Размеры прямоугольника или квадрата зависели от того, на какие расстояния перемещалась
черепашка.
С помощью модуля tkinter нарисовать прямоугольник гораздо проще. Все, что вам нужно знать, — это координаты его углов. Вот пример (окна, оставшиеся от предыдущих примеров, можно закрыть):
>>>
>>>
>>>
>>>
>>>

from tkinter import *
tk = Tk()
canvas = Canvas(tk,width=400, height=400)
canvas.pack()
canvas.create_rectangle(10, 10, 50, 50)

Create rectangle —
создать
прямоугольник

Мы создали холст размером 400 на 400 пикселей, а затем нарисовали
в левом верхнем углу окна квадрат. Вот такой:

12. Более совершенная графика с модулем tkinter

167

Аргументы, которые мы передали функции canvas.create_
rectangle в последней строке кода, — это координаты левого верхнего
и правого нижнего углов квадрата. Первые два значения соответствуют
верхнему левому углу (10 пикселей вправо от левого края и 10 пикселей
вниз от верхнего), а вторые два — правому нижнему углу (50 пикселей
от левого края и 50 — от верхнего).
Назовем эти две координаты x1, y1 и x2, y2. Чтобы вместо квадрата получился вытянутый прямоугольник, можно изменить координаты правого нижнего угла, увеличив значение x2. Вот так:
>>>
>>>
>>>
>>>
>>>

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
canvas.create_rectangle(10, 10, 300, 50)

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

Сделать из квадрата прямоугольник можно и по-другому — увеличив
расстояние от верхнего края холста до правого нижнего угла (увеличив
значение y2). Вот так:
>>>
>>>
>>>
>>>
>>>

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
canvas.create_rectangle(10, 10, 50, 300)

Вызывая функцию create_rectangle, мы говорим примерно
следующее:
• отступить на 10 пикселей вправо от левого края холста;

168

Часть I. Учимся программировать

• отступить на 10 пикселей вниз от верхнего края холста (это
левый верхний угол прямоугольника);
• рисовать прямоугольник шириной 50 пикселей…
• ...и высотой 300 пикселей.
Вот что должно получиться:

Рисуем множество прямоугольников
Заполним холст прямоугольниками разных размеров. Для этого импортируем модуль random, а затем создадим функцию, которая рисует прямоугольник, используя для координат углов случайные
числа.
Воспользуемся функцией randrange из модуля random. Эта функция возвращает случайное число в диапазоне от 0 до значения, которое мы передадим ей в качестве аргумента (но не включая это значение). Например, вызов randrange(10) вернет число от 0 до 9, а вызов
randrange(100) — число от 0 до 99 и так далее.
Используем randrange в функции рисования прямоугольника следующим образом. Откройте новое окно, выбрав в меню File ▶ New File,
и введите такой код:

Random —
случайный,
произвольный

Randrange —
от random
range —
произвольный
диапазон

from tkinter import *
import random

12. Более совершенная графика с модулем tkinter

169

tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
def random_rectangle(width, height):
x1 = random.randrange(width)
y1 = random.randrange(height)
x2 = x1 + random.randrange(width)
y2 = y1 + random.randrange(height)
canvas.create_rectangle(x1, y1, x2, y2)
Random
rectangle —
произвольный
прямоугольник

Мы определили функцию random_rectangle, принимающую два
аргумента: максимальную ширину (width) и максимальную высоту
(height). Создали переменные x1 и y1 для левого верхнего угла прямоугольника, получив значение каждой из них из функции randrange,
в которую передали ширину (для x1) и высоту (для y1). Вторая строка
нашей функции означает: создать переменную x1 и поместить в нее случайное число в диапазоне от 0 до аргумента width.
В следующих двух строках создаем переменные x2 и y2 для правого
нижнего угла. Берем для этого координаты левого верхнего угла (x1 и y1
соответственно) и прибавляем к ним случайные числа. Третья строка нашей функции означает: создать переменную x2 и поместить в нее сумму
случайного числа и значения переменной x1.
Вызываем функцию canvas.create_rectangle, передавая ей значения x1, y1, x2 и y2, чтобы изобразить прямоугольник на холсте.
Проверим работу функции random_rectangle, передав ей ширину
и высоту холста. Введите этот код после функции, которую мы только что
создали:

random_rectangle(400, 400)

Сохраните код (выберите File ▶ Save и введите имя файла, например
randomrect.py), а затем выберите Run ▶ Run Module. Убедившись, что
функция random_rectangle работает, заполним экран прямоугольниками, многократно вызывая ее в цикле, скажем, 100 раз. Добавьте этот
код после предыдущего, сохраните файл и снова запустите программу:

for x in range(0, 100):
random_rectangle(400, 400)

170

Часть I. Учимся программировать

Получится вот такая мешанина:

Рисование в цвете
Мы хотим использовать в рисунках различные цвета. Давайте изменим
функцию random_rectangle так, чтобы она принимала цвет прямоугольника в качестве дополнительного аргумента с именем fill_color.
Введите в новом окне следующий код и сохраните его под именем
colorrect.py:
from tkinter import *
import random
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()

Fill color — цвет
заливки
Colorrect —
от color
rectangle —
цветной
прямоугольник

def random_rectangle(width, height, fill_color):
x1 = random.randrange(width)
y1 = random.randrange(height)
x2 = random.randrange(x1 + random.randrange(width))
y2 = random.randrange(y1 + random.randrange(height))
canvas.create_rectangle(x1, y1, x2, y2, fill=fill_color)

Теперь функция create_rectangle принимает аргумент fi ll_
color со значением цвета, которым будет заполнен прямоугольник.

12. Более совершенная графика с модулем tkinter

171

В нашу функцию можно передавать названия разных
цветов, как показано ниже (для холста 400 на 400 пикселей), и получится набор разноцветных прямоугольников.
Вводя код этого примера, имеет смысл воспользоваться копированием и вставкой текста, чтобы не набирать по многу раз однотипные команды. Для этого выделите фрагмент
текста для копирования, нажмите Ctrl-C, кликните мышкой по пустой
строке и вставьте ранее скопированный текст, нажав Ctrl-V. Добавьте этот
код в окно с файлом colorrect.py следом за функцией random_rectangle:
Green — зеленый
Red — красный
Blue — синий
Orange —
оранжевый
Yellow — желтый
Pink — розовый
Purple —
сиреневый
Violet —
фиолетовый
Magenta —
пурпурный
Cyan — здесь
голубой

random_rectangle(400,
random_rectangle(400,
random_rectangle(400,
random_rectangle(400,
random_rectangle(400,
random_rectangle(400,
random_rectangle(400,
random_rectangle(400,
random_rectangle(400,
random_rectangle(400,

400,
400,
400,
400,
400,
400,
400,
400,
400,
400,

'green')
'red')
'blue')
'orange')
'yellow')
'pink')
'purple')
'violet')
'magenta')
'cyan')

Вводя некоторые из названий цветов на английском, вы можете получить вместо ожидаемого результата ошибку — это зависит от того, какую
операционную систему вы используете (Windows, Mac OS X или Linux).
Как быть с цветами, которые не соответствуют ни одному из названий? Вспомните, как в главе 11 мы задавали цвет пера черепашки, используя насыщенность красного, зеленого и синего цветов в процентах.
Задать насыщенность основных цветов (красного, зеленого и синего) для
создания смешанного цвета в tkinter несколько сложнее. Сейчас мы
с этим разберемся.
Используя модуль turtle, мы задавали золотой цвет, смешивая
90 процентов красного, 75 процентов зеленого и не добавляя синий.
В tkinter такой же цвет можно задать следующим образом:
random_rectangle(400, 400, '#ffd800')

Символ решетки (#) перед значением ffd800 означает, что это число
в шестнадцатеричной системе счисления. Шестнадцатеричная система — это способ представления чисел, который широко используется
в программировании. В этой системе счисления основание — 16 (цифры
от 0 до 9 и буквы от A до F), а не 10 (цифры от 0 до 9), как в привычной нам
десятичной системе. Десятичное число можно преобразовать в шестнадцатеричное с помощью метки формата %x внутри строки (см. раздел

172

Часть I. Учимся программировать

«Переменные внутри строк» на стр. 36). Например, чтобы преобразовать
число 15 из десятичной системы в шестнадцатеричную, введите:
>>> print('%x' % 15)
f

Если требуется выводить не менее двух знаков числа, метку формата
можно слегка изменить:
>>> print('%02x' % 15)
0f

В модуле tkinter есть инструмент, с помощью которого несложно
узнать шестнадцатеричное значение цвета. Добавьте следующий код
в файл colorrect.py (вызовы функции random_rectangle из предыдущего примера можно удалить).
from tkinter import *
colorchooser.askcolor()

При запуске этого кода откроется диалог выбора цвета:

Color chooser —
средство выбора
цвета
Ask color — спросить цвет

Выбрав цвет и кликнув ОК, вы увидите в окне оболочки кортеж, содержащий другой кортеж с тремя числами внутри, а также строку:
>>> colorchooser.askcolor()
((235.91796875, 86.3359375, 153.59765625), '#eb5699')

12. Более совершенная графика с модулем tkinter

173

Три числа — это насыщенность красной, зеленой и синей составляющих цвета. В tkinter насыщенность основных цветов обозначается числами от 0 до 255 (а не от 0 до 1, как в модуле turtle). Строка в кортеже
содержит шестнадцатеричное представление этих трех чисел.
Можно скопировать и вставить это значение в код, а можно сохранить кортеж в переменной и обращаться к шестнадцатеричному значению по его индексу.
Посмотрим, как это работает на примере функции
random_rectangle:
>>> c = colorchooser.askcolor()
>>> random_rectangle(400, 400, c[1])

Вот результат:

Рисование дуг

Create arc —
создать дугу

Extent — здесь
«размах» или
«разворот»
Style — стиль

174

Дуга — это сегмент окружности или эллипса. Чтобы
изобразить дугу с помощью
tkinter, нужно вызвать функцию create_arc, передав ей
координаты углов прямоугольника, в который будет вписана
эта дуга. Вот так:
canvas.create_arc(10, 10, 200, 100, extent=180, style=ARC)

Часть I. Учимся программировать

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

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
canvas.create_arc(10, 10, 200, 100, extent=180, style=ARC)

Левый верхний угол описывающего прямоугольника будет помещен
в точку с координатами (10, 10), что соответствует расстоянию в 10 пикселей от верхнего края холста и 10 пикселей от его левого края, а правый
нижний угол — в точку с координатами (200, 100). Далее указан аргумент extent, в котором передается угол разворота дуги в градусах. Как
мы знаем из главы 4, с помощью градусов можно измерять угол. Вот две
дуги, разворот первой равен 45 градусам, а второй — 270 градусам.

90˚

270˚

Нарисуем несколько дуг — одну под другой. Так будет видно, что происходит при передаче в функцию create_arc разных значений угла.
>>>
>>>
>>>
>>>

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()

12. Более совершенная графика с модулем tkinter

175

>>>
>>>
>>>
>>>
>>>

!

canvas.create_arc(10,
canvas.create_arc(10,
canvas.create_arc(10,
canvas.create_arc(10,
canvas.create_arc(10,

10, 200, 80, extent=45, style=ARC)
80, 200, 160, extent=90, style=ARC)
160, 200, 240, extent=135, style=ARC)
240, 200, 320, extent=180, style=ARC)
320, 200, 400, extent=359, style=ARC)

В качестве полного оборота используем угол 359 градусов, а не 360,
поскольку tkinter считает, что угол 360 градусов равен углу 0 градусов, и ничего не нарисует.

Рисование многоугольников
Многоугольник — это любая фигура с тремя или более углами, контур
которой замкнут. Многоугольники бывают правильными (у которых все
стороны и углы равны) и неправильными (с разными величинами сторон
и углов).
Чтобы нарисовать многоугольник с помощью tkinter, нужно указать координаты точек, соответствующих всем его углам. Изобразить
треугольник можно так:

Polygon — многоугольник
Outline — контур
Black — черный

176

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
canvas.create_polygon(10, 10, 100, 10, 100, 110, fill="",
outline="black")

Часть I. Учимся программировать

Получится треугольник, контур которого соединяет точку с координатами (10, 10) с точкой (100, 10) и точкой (100, 110):

Добавим еще один неправильный многоугольник (с неравными сторонами и неравными углами), введя следующий код:
canvas.create_polygon(200, 10, 240, 30, 120, 100, 140, 120,
fill="", outline="black")

Получится фигура, контур которой соединяет точку с координатами
(200, 10) с точкой (240, 30), точкой (120, 100) и точкой (140, 120); tkinter
автоматически замкнет контур, проведя линию обратно к первой точке,
и получится вот что:

Отображение текста
Помимо рисования фигур на холсте, можно печатать сообщения с помощью функции create_text, которая принимает две координаты
(x- и y-позиции надписи), а также именованный аргумент со строкой
текста. В следующем примере мы создаем холст так же, как и прежде,
а затем печатаем строку в позиции (150, 100). Сохраните этот код в файле text.py.

Create text —
создать текст

12. Более совершенная графика с модулем tkinter

177

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
canvas.create_text(150, 100, text='Был один человек из Тулузы,')

Функция create_text может принимать и другие полезные аргументы, например цвет надписи. В следующей строке кода вызываем
create_text, передавая координаты (130, 120), сообщение для печати,
а также цвет (красный):
canvas.create_text(130, 120, text='Что сидел на огромном арбузе.',
fill='red')

Font — шрифт

В аргументе font можно передать кортеж, который содержит название и размер шрифта выводимого на экран сообщения. Например, для
шрифта Times размером 20 пунктов кортеж будет таким: ('Times', 20).

!

Ра з мер шрифта здес ь у ка зываетс я
в пунктах, а не в пикселях. Используемый
в компьютерной графике пункт соответствует 0,3527 мм. В tkinter можно
указать размер шрифта и в пикселях.
Для этого используются отрицательные
значения. Например, для шрифта Times
размером 20 пикселей: ('Times', −20).

В следующем примере строки текста выводятся шрифтом Times размера 15, шрифтом Helvetica размера 20 и шрифтом Courier размера 22,
а затем размера 30.
canvas.create_text(150, 150, text='Он сказал: "Это ужас,',
font=('Times', 15))
canvas.create_text(200, 200, text='Но бывает и хуже:',
font=('Helvetica', 20))
canvas.create_text(220, 250, text='Вон мой братец сидит',
font=('Courier', 22))
canvas.create_text(220, 300, text='На медузе".', font=('Courier',
30))

Вот результат всех этих вызовов create_text с разными шрифтами
разных размеров:

178

Часть I. Учимся программировать

Вывод изображений
Чтобы с помощью tkinter вывести на холст изображение, его сначала
нужно загрузить, а затем вызвать функцию create_image.
Файл с изображением должен находиться в папке, к которой у Python
есть доступ. Допустим, изображение test.gif находится в папке C:\\, то есть
корневой директории диска C: (хотя его можно положить и в другое место).

Create image —
создать
изображение

12. Более совершенная графика с модулем tkinter

179

Если вы используете Mac OS или Linux, можете поместить изображение в свою домашнюю директорию. Если в корень диска C: не получается
скопировать файл, можете поместить его на рабочий стол.

!

Средствами tkinter можно загружать только изображения формата GIF (файлы с расширением .gif). Чтобы вывести изображение
другого типа, скажем, PNG (.png) или JPG (.jpg), придется воспользоваться другим модулем, например Python Imaging Library (http://
www.pythonware.com/products/pil/).
Вывести изображение test.gif на экран можно так:
from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
my_image = PhotoImage(file='c:\\test.gif')
canvas.create_image(0, 0, anchor=NW, image=my_image)

Photo Image —
фотоизображение

В первых четырех строках мы создали холст так же, как в предыдущих примерах. В пятой строке загрузили изображение в переменную
my_image. Если ваше изображение находится на рабочем столе, нужно
передать в функцию PhotoImage другой путь, например такой:
my_image = PhotoImage(file='C:\\Users\\Joe Smith\\Desktop\\test.gif')

NW — сокращение
от northwest —
северо-запад

180

Когда изображение загружено, команда canvas.
create_image(0, 0,
anchor=NW, image=my_
image) выводит его на экран. Координаты (0, 0)
определяют позицию изображения, аргумент anchor=NW
означает, что изображение
должно выводиться с левого
верхнего угла (иначе за отправную точку считался бы
центр изображения). Последний именованный аргумент — image — указывает
на переменную с загруженным изображением. Вот что
должно получиться:

Часть I. Учимся программировать

Создание простой анимации
До сих пор мы занимались только статичными, неизменяющимися рисунками. Пора переходить к анимации.
Модуль tkinter не ориентирован на создание анимации, но чтонибудь простое с его помощью сделать можно. Например, следующий
код рисует заполненный треугольник, который движется по экрану слева направо (не забудьте выбрать File ▶ New File, сохранить код на диск
и затем запустить его, выбрав Run ▶ Run Module):

import time
from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=200)
canvas.pack()
canvas.create_polygon(10, 10, 10, 60, 50, 35)
for x in range(0, 60):
canvas.move(1, 5, 0)
tk.update()
time.sleep(0.05)

После запуска вы увидите, как треугольник движется по экрану вправо и останавливается:

Как это работает? В первых трех строках кода после импортирования
tkinter мы, как обычно, создаем и настраиваем холст. В четвертой строке создаем треугольник с помощью вызова create_polygon:
canvas.create_polygon(10, 10, 10, 60, 50, 35)

12. Более совершенная графика с модулем tkinter

181

!

Если ввести эту строку в оболочке IDLE, на экране появится число —
идентификатор нашего треугольника, который можно использовать для обращения к созданной фигуре.

Задаем простой цикл for, который считает от 0 до 59
(команда for x in range(0, 60)). Выполняющийся в этом
цикле блок кода служит для перемещения треугольника по экрану. Функция canvas.move двигает любой нарисованный
ранее графический объект, изменяя значения его x- и y-координат на указанные величины смещения. В частности, команда canvas.move(1, 5, 0) сдвинет объект, идентификатор
которого равен 1 (это наш треугольник), на 5 пикселей вправо
и 0 пикселей вниз. А для возвращения треугольника на прежнее место подойдет команда canvas.move(1, –5, 0).
Функция tk.update() служит для принудительного обновления (перерисовки) изображения на экране. Без этой команды tkinter обновил
бы экран лишь после окончания цикла и вместо плавной анимации мы
бы увидели треугольник сразу в конечной точке движения. А последняя
команда в теле цикла, time.sleep(0.05), задает 0,05-секундную паузу.
Предположим, мы хотим, чтобы треугольник двигался по диагонали вправо и вниз. Для этого можно изменить код, использовав команду
move(1, 5, 5). Закройте окно с холстом, создайте новый файл (File ▶
New File) и введите:
import time
from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
canvas.create_polygon(10, 10, 10, 60, 50, 35)
for x in range(0, 60):
canvas.move(1, 5, 5)
tk.update()
time.sleep(0.05)

Здесь два отличия от предыдущего примера с треугольником:
1. Задаем высоту холста 400 пикселей (а не 200) с помощью
команды canvas = Canvas(tk, width=400, height=400).
2. Прибавляем 5 не только к x-, но и к y-координате треугольника,
вызывая canvas.move(1, 5, 5).
Если вы сохраните программу, запустите ее и дождетесь окончания
работы цикла, треугольник окажется здесь:

182

Часть I. Учимся программировать

Чтобы переместить треугольник по диагонали обратно, в начальную
позицию, можно использовать такой же цикл со смещениями –5, –5 (добавьте этот код в конец файла):
for x in range(0, 60):
canvas.move(1, -5, -5)
tk.update()
time.sleep(0.05)

Реакция объектов на события
Можно сделать так, чтобы треугольник реагировал на нажатия клавиш.
Для этого служит так называемая привязка к событиям. События —
то, что происходит во время работы программы, например при передвижении мышки, нажатии клавиш или работе с окнами. Можно попросить
tkinter следить за такими событиями и реагировать на них.
Для обработки события нужно создать функцию, а затем сообщить
tkinter, что ее следует привязать к определенному событию, иначе говоря, что она должна вызываться, когда это событие произойдет.
Пусть треугольник будет двигаться при нажатии клавиши ENTER.
Создадим для этого такую функцию:
def movetriangle(event):
canvas.move(1, 5, 0)

Move triangle —
подвинуть
треугольник
Event — событие

12. Более совершенная графика с модулем tkinter

183

Bind all — здесь
назначить для
всех (элементов)

Наша функция принимает единственный аргумент (event), в котором tkinter передает информацию о событии. Теперь нужно, чтобы
tkinter вызывал эту функцию при нажатии ENTER. Используем для
этого функцию bind_all. Весь код будет выглядеть так:
from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
canvas.create_polygon(10, 10, 10, 60, 50, 35)
def movetriangle(event):
canvas.move(1, 5, 0)
canvas.bind_all('', movetriangle)

Первый аргумент функции bind_all описывает событие, за которым нужно наблюдать. В данном случае оно называется , что соответствует нажатию клавиши Enter или Return.
С помощью второго аргумента мы указываем, что при возникновении
события нужно вызывать функцию
movetriangle. Запустите этот код,
кликните мышкой по холсту и понажимайте ENTER на клавиатуре.
Если мы хотим менять направление движения треугольника в зависимости от нажатий на разные
клавиши, скажем, на клавиши-стрелки, нужно изменить код функции
movetriangle:
def movetriangle(event):
if event.keysym == 'Up':
canvas.move(1, 0, -3)
elif event.keysym == 'Down':
canvas.move(1, 0, 3)
elif event.keysym == 'Left':
canvas.move(1, -3, 0)
else:
canvas.move(1, 3, 0)

Keysym — здесь
имя клавиши

184

Объект event, который передается в функцию movetriangle, содержит набор свойств (переменных объекта). В одном из них, keysym,
хранится значение, соответствующее нажатой клавише. Строка if
event.keysym == 'Up': означает, что, если в свойстве keysym находится значение 'Up', нужно выполнить следующую строку кода: вызвать
canvas.move с аргументами (1, 0, –3). Если же в keysym содержится

Часть I. Учимся программировать

'Down' (elif event.keysym == 'Down':), нужно вызвать canvas.
move с аргументами (1, 0, 3), и так далее.
Напоминаю: первый аргумент move — это идентификатор графического объекта на холсте, второй — значение, на которое следует изменить координату x (позицию по горизонтали), а третий — значение,
на которое нужно изменить координату y (позицию по вертикали).
Осталось сообщить tkinter, что функцию movetriangle нужно
использовать для обработки четырех событий: нажатий клавиш-стрелок
«вверх», «вниз», «влево» и «вправо». Вот как будет выглядеть код (его будет гораздо проще вводить, создав новый файл (File ▶ New File)). Перед
запуском сохраните файл — например, под именем movingtriangle.py.










from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
canvas.create_polygon(10, 10, 10, 60, 50, 35)
def movetriangle(event):
if event.keysym == 'Up':
canvas.move(1, 0, -3)
elif event.keysym == 'Down':
canvas.move(1, 0, 3)
elif event.keysym == 'Left':
canvas.move(1, -3, 0)
else:
canvas.move(1, 3, 0)
canvas.bind_all('', movetriangle)
canvas.bind_all('', movetriangle)
canvas.bind_all('', movetriangle)
canvas.bind_all('', movetriangle)

В функции movetriangle в строке  проверяем, содержит ли переменная keysym значение 'Up'. Если содержит, перемещаем треугольник
вверх, вызывая в строке  функцию move с аргументами 1, 0, –3. Первый аргумент move — идентификатор треугольника, второй — величина
сдвига вправо (нам не нужно горизонтальное смещение, поэтому указываем значение 0), а третий — величина сдвига вниз (–3 пикселя).
В строке  проверяем, не содержит ли keysym значения 'Down',
и если содержит, в строке  сдвигаем треугольник вниз. В строке  идет
последняя проверка — на значение 'Left'. Если это подтверждается,
в строке  сдвигаем треугольник влево (–3 пикселя). Если же ни одна
из проверок не сработала, в строке  выполнится вариант else и в строке  треугольник сдвинется вправо.
При нажатии любой из клавиш-стрелок треугольник будет перемещаться в соответствующем направлении.

12. Более совершенная графика с модулем tkinter

185

Для чего еще нужен идентификатор
Функции холста, имена которых начинаются с create_ (создать), такие
как create_polygon или create_rectangle, при каждом вызове возвращают число-идентификатор, который можно использовать с другими
функциями холста, например функцией move (двигать), которую мы использовали ранее:
>>>
>>>
>>>
>>>
>>>
1
>>>

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
canvas.create_polygon(10, 10, 10, 60, 50, 35)
canvas.move(1, 5, 0)

В этом коде есть одна проблема — create_polygon может вернуть
не 1, а иное значение. Например, если до этого мы уже создавали какие-то
фигуры, она может вернуть число 2, 3 или даже 100 (в зависимости от количества созданных фигур). Однако, если мы доработаем программу так,
чтобы возвращаемое значение сохранялось в переменной и она использовалась как идентификатор (вместо числа 1), код будет работать независимо от того, какое именно значение было возвращено:
>>> mytriangle = canvas.create_polygon(10, 10, 10, 60, 50, 35)
>>> canvas.move(mytriangle, 5, 0)

Item config —
от item
configuration —
конфигурация
элемента

Функция move позволяет перемещать графические объекты по экрану с помощью их идентификаторов. Но есть и другие функции холста,
которые также способны менять созданные ранее объекты. Например,
функцию itemconfig можно использовать для изменения некоторых
свойств фигуры, таких как цвет заполнения и цвет обводки.
Положим, у нас есть красный треугольник, созданный таким образом:
>>> from tkinter import *
>>> tk = Tk()
>>> canvas = Canvas(tk, width=400, height=400)
>>> canvas.pack()
>>> mytriangle = canvas.create_polygon(10, 10, 10, 60, 50, 35,
fill='red')

Можно изменить цвет этого треугольника, вызвав функцию
itemconfi g с его идентификатором в качестве первого аргумента.

186

Часть I. Учимся программировать

Следующий код означает: изменить цвет заполнения объекта, идентификатор которого находится в переменной mytriangle, на синий (blue).
>>> canvas.itemconfig(mytriangle, fill='blue')

Можно поменять цвет обводки треугольника на, допустим, красный
цвет (опять же, передавая идентификатор первым аргументом):
>>> canvas.itemconfig(mytriangle, outline='red')

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

Что мы узнали
В этой главе с помощью модуля tkinter мы рисовали на холсте простые
геометрические фигуры, выводили изображения, а также показывали
несложную анимацию. Узнали, как, используя привязку к событиям,
«научить» рисунки на холсте реагировать на нажатия клавиш — это еще
пригодится нам для создания игры. Выяснили, что функции создания
графических объектов в tkinter возвращают идентификаторы, чтобы
эти объекты можно было изменять, например перемещать их по экрану
или менять цвет.

12. Более совершенная графика с модулем tkinter

187

Упражнения
Попрактикуйтесь в работе с модулем tkinter и несложной анимацией.

#1. Заполните экран треугольниками
Напишите программу, которая с помощью tkinter заполняет экран треугольниками. Затем модифицируйте код, чтобы треугольники были раскрашены (заполнены) различными цветами.

#2. Движущийся треугольник
Доработайте код движущегося треугольника (см. «Создание простой
анимации» на стр. 181), чтобы треугольник двигался вправо, вниз, влево
и вверх, вернувшись в итоге в первоначальную позицию.

#3. Движущаяся фотография
С помощью tkinter отобразите на экране свою фотографию. Не забывайте, что изображение должно быть в формате GIF! А теперь сделайте
так, чтобы фотография перемещалась по экрану.

ЧАС ТЬ II

Пишем игру
«Прыг-скок!»

13
Н А Ш А ПЕРВА Я ИГ РА : «ПРЫГ С КОК ! »

В предыдущих главах мы изучили основы программирования. Узнали,
как хранить данные в переменных, работать с конструкцией if с условиями и многократно выполнять код с помощью циклов. Научились
создавать функции, чтобы использовать код повторно, и разделять программу на более простые и понятные фрагменты с помощью классов.
Познакомились с основами программирования графики с использованием модулей turtle и tkinter. Пришло время применить все эти знания
на практике, написав игру.

Прыгающий мяч
Разработаем игру с прыгающим мячом
и ракеткой. Мяч будет летать по экрану, а игрок — отбивать его ракеткой.
Если мяч коснется нижней границы
экрана, игра завершится. На рисунке
справа показано, как будет выглядеть
законченная игра.
Хотя на первый взгляд игра довольно проста, ее код будет сложнее,
чем все, что мы писали до сих пор,
поскольку программа должна выполнять множество разных действий.
К примеру, нужно анимировать ракетку и мяч, а также обрабатывать
столкновения мяча с ракеткой и границами игрового поля.

193

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

Создаем игровой холст
Первым делом откроем новый файл в оболочке Python (выберите File ▶
New File). Затем импортируем tkinter и создадим холст для рисования:

Resizable — изменяемый размер
Attributes —
атрибуты

from tkinter import *
import random
import time
tk = Tk()
tk.title("Игра")
tk.resizable(0, 0)
tk.wm_attributes("-topmost", 1)
canvas = Canvas(tk, width=500, height=400, bd=0,
highlightthickness=0)
canvas.pack()
tk.update()

Этот код несколько отличается от кода предыдущих примеров. Сначала помимо tkinter импортируем модули time и random, (import
random и import time) — они нам понадобятся немного позже.
Вызовом tk.title("Игра")
задаем заголовок игрового окна
(для этого и служит функция
title ранее созданного объекта tk). Вызываем функцию
resizable, чтобы сделать
размер окна фиксированным.
Аргументы 0, 0 означают: размер окна должен быть неизменным как по горизонтали,
так и по вертикали. Вызываем функцию wm_attributes,
указывая, что окно с холстом
нужно разместить поверх всех
остальных окон ("–topmost").
Обратите внимание, что, создавая холст, мы передали больше именованных аргументов,
чем в предыдущих примерах.
Например, аргументы bd=0
и highlightthickness=0

194

Часть II. Пишем игру «Прыг-скок!»

нужны для того, чтобы вокруг холста не было рамки. Так наша игра будет
лучше выглядеть.
В результате вызова canvas.pack() холст изменит размер в соответствии со значениями ширины и высоты, указанными в предыдущей
строке кода. Команда tk.update() подготавливает tkinter к игровой
анимации. Без вызова update программа не будет работать так, как
задумано.
Не забывайте сохранять код по мере его написания. При первом сохранении дайте файлу имя, например paddleball.py.

Создаем класс для мяча

Paddle ball —
букв. ракетка
мяч

Теперь создадим класс для мяча и первым делом добавим в него код отрисовки мяча на холсте. Вот что нам предстоит сделать:
• создать класс под названием Ball, принимающий в качестве
аргументов функции __init__ холст и цвет мяча;

Ball — мяч

• сохранить в свойстве объекта холст, чтобы в дальнейшем рисовать на нем мяч;
• Изобразить на холсте круг, заполненный переданным в аргументе цветом;
• сохранить идентификатор, который вернет нам функция рисования круга, поскольку с его помощью мы будем перемещать
мяч по экрану;
• переместить нарисованный круг в центр холста.
Этот код нужно добавить в начало файла, после строки import time:
from tkinter import *
import random
import time
 class Ball:

def __init__(self, canvas, color):

self.canvas = canvas

self.id = canvas.create_oval(10, 10, 25, 25, fill=color)

self.canvas.move(self.id, 245, 100)

Oval — овал,
эллипс

def draw(self):
pass

13. Наша первая игра: «Прыг-скок!»

195

В строке  даем классу имя Ball. В строке  создаем функцию инициализации __init__ (см. главу 8), которая принимает в качестве аргументов холст и цвет. В строке  сохраняем
аргумент canvas в свойстве с таким же именем.
В строке  вызываем функцию create_oval для рисования круга, передавая ей пять аргументов: x- и y-координаты
левого верхнего угла описывающего прямоугольника (10 и 10),
x- и y-координаты его правого нижнего угла (25 и 25) и цвет
заполнения.
Функция create_oval возвращает идентификатор нарисованной фигуры, который мы сохраняем в свойстве id.
В строке  перемещаем круг приблизительно в центр холста
(позиция 245, 100), передав для этого в функцию move сохраненный ранее идентификатор фигуры (свойство id).
В двух последних строках определяем функцию draw (def
draw(self)), указывая вместо тела функции ключевое слово
pass (пока функция draw ничего не делает, но скоро мы это
исправим).
Итак, у нас есть класс Ball, и теперь нужно создать объект этого
класса (вспомните: класс лишь описывает, что нужно делать, а объект
выполняет конкретные действия). Чтобы создать объект — мяч красного
цвета, — добавьте в конец программы следующий код:
ball = Ball(canvas, 'red')

Если теперь запустить программу, выбрав Run ▶ Run Module, холст
на мгновение появится и тут же исчезнет. Чтобы окно не закрывалось,
нужно добавить в программу цикл игровой анимации, который называют главным циклом игры.
Главный цикл — центральный элемент программы, который управляет большей частью действий. Поначалу наш главный цикл будет только перерисовывать экран. Этот цикл бесконечный (по крайней мере он
будет выполняться до тех пор, пока мы не закроем окно), и при каждом
его повторе мы будем давать команду перерисовать экран и делать паузу
на одну сотую долю секунды. Добавьте этот код в конец программы:
ball = Ball(canvas, 'red')

Tasks — задачи

196

while 1:
tk.update_idletasks()
tk.update()
time.sleep(0.01)

Часть II. Пишем игру «Прыг-скок!»

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

Добавим движение
Класс Ball подготовлен, теперь анимируем мяч. Наша
задача — сделать так, чтобы мяч двигался и отскакивал от препятствий, меняя направление.

Перемещение мяча
Чтобы мяч двигался, первым делом изменим функцию draw таким
образом:
class Ball:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
self.canvas.move(self.id, 245, 100)
def draw(self):
self.canvas.move(self.id, 0, -1)

13. Наша первая игра: «Прыг-скок!»

197

Поскольку в функции __init__ мы сохранили холст в свойстве
canvas, теперь для вызова функции move можно обращаться к холсту
через self.canvas.
Передаем функции move три аргумента: сохраненный ранее идентификатор круга (мяча), а также числа 0 и –1. Здесь 0 означает, что перемещения по горизонтали быть не должно, а –1 — что мяч должен переместиться на 1 пиксель вверх.
Мы внесли это небольшое изменение, чтобы посмотреть, как перемещается мяч. В процессе создания программы желательно почаще проверять ее части. Только представьте, что мы написали всю программу
и вдруг обнаружили, что она не работает. Будет нелегко понять, в какую
именно часть кода вкралась ошибка.
В главный цикл игры нужно внести еще одно изменение. Добавим
в тело цикла while (это и есть главный цикл) вызов функции объектамяча draw. Вот так:
while 1:
ball.draw()
tk.update_idletasks()
tk.update()
time.sleep(0.01)

Sleep — здесь
задержка

Если теперь запустить код, мяч начнет двигаться вверх и вскоре
исчезнет за границей окна, поскольку главный цикл быстро обновляет
экран, постоянно перерисовывая его содержимое с помощью команд
update_idletasks и update.
Команда time.sleep — это вызов функции sleep из модуля time. Она
приостанавливает выполнение кода, в нашем случае — на сотую долю секунды (0.01). Это нужно для того, чтобы программа работала не слишком быстро, иначе мяч исчезнет прежде, чем мы успеем его разглядеть.
Итак, сейчас наш главный цикл немного сдвигает мяч, перерисовывает экран (после чего новое положение мяча становится видимым), делает небольшую паузу и повторяет эти действия снова и снова.

!

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

from tkinter import *
import random
import time

198

Часть II. Пишем игру «Прыг-скок!»

class Ball:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
self.canvas.move(self.id, 245, 100)
def draw(self):
self.canvas.move(self.id, 0, -1)
tk = Tk()
tk.title("Игра")
tk.resizable(0, 0)
tk.wm_attributes("-topmost", 1)
canvas = Canvas(tk, width=500, height=400, bd=0,
highlightthickness=0)
canvas.pack()
tk.update()
ball = Ball(canvas, 'red')
while 1:
ball.draw()
tk.update_idletasks()
tk.update()
time.sleep(0.01)

Отскоки мяча
Мяч, который улетает за границу холста, не очень подходит для этой
игры, поэтому давайте «научим» его отскакивать от границ. Создадим
в функции __init__ класса Ball еще несколько свойств. Вот так:

def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
self.canvas.move(self.id, 245, 100)
self.x = 0
self.y = -1
self.canvas_height = self.canvas.winfo_height()

Мы добавили еще три строки кода. Команда self.x = 0 задает свойству объекта с именем x значение 0, а self.y = –1 задает свойству y значение –1. Сохраняем в свойстве canvas_height значение, полученное
из функции холста winfo_height. Эта функция возвращает текущую
высоту холста.
Снова изменим функцию draw:

13. Наша первая игра: «Прыг-скок!»

199

def draw(self):
self.canvas.move(self.id, self.x, self.y)
pos = self.canvas.coords(self.id)
if pos[1] = self.canvas_height:
self.y = -1




Pos — позиция,
положение
Coords — координаты

В строке  мы поменяли вызов функции move, теперь передаем в нее
свойства x и y. В строке  создали переменную pos, поместив в нее значение, полученное от функции холста coords. Эта функция возвращает
x- и y-координаты любой фигуры на холсте по ее идентификатору. В данном случае мы передаем в функцию coords свойство id, где хранится
идентификатор круга (мяча).
Функция coords возвращает координаты в виде списка из четырех
чисел. Если вывести его на экран, мы увидим нечто подобное:
print(self.canvas.coords(self.id))
[255.0, 29.0, 270.0, 44.0]

Первые два числа (255.0 и 29.0) — это координаты левого верхнего
угла прямоугольника, в который вписан наш круг (x1 и y1), а вторые два
(270.0 и 44.0) — координаты правого нижнего угла прямоугольника (x2
и y2). Этими значениями мы и воспользуемся в следующих строках кода.
В строке  сравниваем координату y1 (это
верх мяча) с нулем и, если она меньше или равна
0, задаем свойству y значение 1. Таким образом
мы говорим, что если мяч достиг верхней границы холста, нужно прекратить двигать его вверх,
перестав вычитать 1 из его вертикальной координаты. Вместо этого мы будем прибавлять к этой
координате 1, чтобы мяч сменил направление.
В строке  сравниваем координату y2 (это
низ мяча) со свойством canvas_height и, если
y2 больше или равно canvas_height, снова задаем свойству y значение –1.
Запустите этот код, и вы увидите, как мяч летает вверх-вниз, отскакивая от границ, до тех пор
пока вы не закроете окно.

200

Часть II. Пишем игру «Прыг-скок!»

Меняем первоначальное направление
движения мяча
Мяча, который движется то вверх, то вниз, для нашей игры
недостаточно, поэтому добавим разнообразия, поменяв изначальное направление полета мяча, то есть угол его движения после запуска игры. Замените в функции __init__
следующие строки:
self.x = 0
self.y = -1

Вместо них введите следующий код (обратите внимание на количество пробелов в начале каждой строки — их должно быть восемь):





starts = [-3, -2, -1, 1, 2, 3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3

В строке  мы создали переменную starts, поместив туда список
из шести чисел. В строке  перемешали элементы списка с помощью
random.shuffle. В строке  поместили в свойство x значение первого
элемента списка. Теперь в x может попасть любое значение из исходного
списка, от –3 до 3.
В строке  помещаем в свойство y значение –3 (чтобы ускорить движение мяча). Затем внесем несколько правок, чтобы мяч не улетал за боковые границы холста. Добавим в конец функции __init__ следующую
строку кода, которая, получив от функции winfo_width ширину холста,
сохраняет ее в свойстве canvas_width:

Start — старт,
начало

self.canvas_width = self.canvas.winfo_width()

Это новое свойство пригодится в функции draw для проверки, не достиг ли мяч правой границы холста:
if pos[0] =
self.x =

0:
3
self.canvas_width:
-3

13. Наша первая игра: «Прыг-скок!»

201

Поскольку при достижении границ мы задаем свойству x значение 3
или –3, будем использовать такие же значения и для y, чтобы мяч всегда
двигался с одинаковой скоростью. В результате функция draw примет такой вид:
def draw(self):
self.canvas.move(self.id, self.x, self.y)
pos = self.canvas.coords(self.id)
if pos[1] = self.canvas_height:
self.y = -3
if pos[0] = self.canvas_width:
self.x = -3

Сохраним код программы и запустим ее. Мяч будет перемещаться
по холсту, отскакивая от его границ. Программа должна выглядеть так:
from tkinter import *
import random
import time
class Ball:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
self.canvas.move(self.id, 245, 100)
starts = [-3, -2, -1, 1, 2, 3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
self.canvas_height = self.canvas.winfo_height()
self.canvas_width = self.canvas.winfo_width()
def draw(self):
self.canvas.move(self.id, self.x, self.y)
pos = self.canvas.coords(self.id)
if pos[1] = self.canvas_height:
self.y = -3
if pos[0] = self.canvas_width:
self.x = -3

202

Часть II. Пишем игру «Прыг-скок!»

tk = Tk()
tk.title("Игра")
tk.resizable(0, 0)
tk.wm_attributes("-topmost", 1)
canvas = Canvas(tk, width=500, height=400, bd=0,
highlightthickness=0)
canvas.pack()
tk.update()
ball = Ball(canvas, 'red')
while 1:
ball.draw()
tk.update_idletasks()
tk.update()
time.sleep(0.01)

Что мы узнали
В этой главе мы начали писать первую игру, используя модуль tkinter.
Создали класс для мяча и анимировали мяч, «научив» его летать по экрану. Проверяя координаты, добились того, чтобы мяч отскакивал от границ холста. Воспользовались функцией shuffle из модуля random, чтобы
в начале игры мяч мог двигаться в разных направлениях. В следующей
главе мы закончим создание игры, добавив в нее ракетку.

14
Д О Д Е Л Ы В А Е М П Е Р В У Ю И Г Р У:
«ПРЫГ С КО К ! »

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

Создаем ракетку

Paddle — ракетка

Что за радость от мячика, если его нечем отбивать? Настало время создать ракетку!
Начнем с класса для ракетки (Paddle), код которого нужно ввести
сразу после класса Ball и его функции draw:
def draw(self):
self.canvas.move(self.id, self.x, self.y)
pos = self.canvas.coords(self.id)
if pos[1] = self.canvas_height:
self.y = -3
if pos[0] = self.canvas_width:
self.x = -3
class Paddle:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_rectangle(0, 0, 100, 10,
fill=color)
self.canvas.move(self.id, 200, 300)
def draw(self):
pass

Этот код очень похож на код класса Ball. Однако вместо функции
create_oval мы используем create_rectangle и перемещаем нарисованный этой функцией прямоугольник в позицию 200, 300 (200 пикселей от левого края холста и 300 пикселей от верхнего края).
Ближе к концу программы создадим объект класса Paddle и дополним игровой цикл вызовом функции draw этого объекта. Вот так:
paddle = Paddle(canvas, 'blue')
ball = Ball(canvas, 'red')
while 1:
ball.draw()
paddle.draw()
tk.update_idletasks()
tk.update()
time.sleep(0.01)

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

205

Управление ракеткой
Чтобы управлять ракеткой, двигая ее вправо
и влево, воспользуемся привязкой к событиям:
привяжем клавиши-стрелки «вправо» и «влево»
к вызовам функций класса Paddle. При нажатии стрелки «влево» будем задавать свойству x
объекта-ракетки значение –2 (для передвижения влево), а при нажатии стрелки «вправо» —
значение 2 (для передвижения вправо).
В функции __init__ класса Paddle создадим свойства x и canvas_width для хранения ширины холста (так же, как мы это делали для класса Ball):
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color)
self.canvas.move(self.id, 200, 300)
self.x = 0
self.canvas_width = self.canvas.winfo_width()

Turn — повернуть

Добавим в класс Paddle две функции: для смены направления влево
(turn_left) и вправо (turn_right). Поместим их код сразу после функции draw:
def turn_left(self, evt):
self.x = -2
def turn_right(self, evt):
self.x = 2

Для привязки этих функций к нажатиямнужных нам клавиш добавим в функцию __init__ класса Paddle еще две строки кода. Мы уже
занимались привязкой к нажатиям клавиш в разделе «Реакция объектов на события» на стр. 183. В данном случае нужно привязать функцию
turn_left к нажатию клавиши-стрелки «влево» (это событие с именем
''), а функцию turn_right — к клавише-стрелке
«вправо» (это событие ''). После доработки функция __init__ будет выглядеть так:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color)

206

Часть II. Пишем игру «Прыг-скок!»

self.canvas.move(self.id, 200, 300)
self.x = 0
self.canvas_width = self.canvas.winfo_width()
self.canvas.bind_all('', self.turn_left)
self.canvas.bind_all('', self.turn_right)

Код функции draw класса Paddle будет примерно таким же, как для
класса Ball:
def draw(self):
self.canvas.move(self.id, self.x, 0)
pos = self.canvas.coords(self.id)
if pos[0] = self.canvas_width:
self.x = 0

Для перемещения ракетки в соответствии со значением свойства x
используем функцию move — self.canvas.move(self.id, self.x, 0).
Получаем координаты ракетки (сохраняя их в переменной pos), чтобы
проверить, достигла ли ракетка левой либо правой границы холста.
В отличие от мяча ракетка при столкновении с границей должна
не отскочить от нее, а остановиться. Поэтому, если левая x-координата
(pos[0]) меньше или равна 0 (= self.canvas_width), также обнуляем x.

!

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

Проверка на столкновение мяча с ракеткой
Сейчас наш код устроен так, что мяч не сталкивается с ракеткой, а пролетает сквозь нее. Чтобы этого не происходило, мяч должен «знать» о столкновении с ракеткой так же,
как он «знает» о столкновениях с границами холста.
Эту проблему можно решить, добавив соответствующий код в функцию draw (где выполняется проверка
столкновений с границами). Однако лучше создать для
этого отдельные функции, чтобы программа состояла
из небольших частей. Дело в том, что в программе очень
сложно разобраться, если в одном месте (например,

14. Доделываем первую игру: «Прыг-скок!»

207

в одной функции) скапливается слишком много строк кода. Внесем необходимые изменения.
Добавим в функцию __init__ класса Ball еще один аргумент —
объект-ракетку:
class Ball:
 def __init__(self, canvas, paddle, color):
self.canvas = canvas

self.paddle = paddle
self.id = canvas.create_oval(10, 10, 25, 25, fill=color)
self.canvas.move(self.id, 245, 100)
starts = [-3, -2, -1, 1, 2, 3]
random.shuffle(starts)
self.x = starts[0]
self.y = -3
self.canvas_height = self.canvas.winfo_height()
self.canvas_width = self.canvas.winfo_width()

Обратите внимание, что в строке  мы изменили аргументы
__init__, добавив к ним ракетку (paddle), а в строке  сохранили значение аргумента paddle в свойстве с таким же названием.
Теперь нужно изменить код создания объекта-мяча с учетом нового аргумента — ракетки. Этот код находится в конце программы перед
главным циклом:
paddle = Paddle(canvas, 'blue')
ball = Ball(canvas, paddle, 'red')
while 1:
ball.draw()
paddle.draw()
tk.update_idletasks()
tk.update()
time.sleep(0.01)

Hit paddle — здесь
столкновение
с ракеткой

Код для проверки столкновения с ракеткой будет сложнее, чем код
проверки для границ холста. Поместим его в новую функцию hit_
paddle, добавив ее вызов в функцию draw класса Ball, рядом с проверкой на столкновение с нижней границей:
def draw(self):
self.canvas.move(self.id, self.x, self.y)
pos = self.canvas.coords(self.id)
if pos[1] = self.canvas_height:

208

Часть II. Пишем игру «Прыг-скок!»

self.y = -3
if self.hit_paddle(pos) == True:
self.y = -3
if pos[0] = self.canvas_width:
self.x = -3

Если hit_paddle возвращает True, мы меняем направление полета
мяча, задавая свойству y значение –3 (self.y = –3). Не пытайтесь сейчас
запустить игру — мы еще не создали функцию hit_paddle. Давайте это
исправим.
Добавьте код функции hit_paddle сразу перед функцией draw:
 def hit_paddle(self, pos):

paddle_pos = self.canvas.coords(self.paddle.id)

if pos[2] >= paddle_pos[0] and pos[0] = paddle_pos[1] and pos[3] = paddle_pos[0] and pos[0] = paddle_pos[1] and pos[3] co2.x1 and co1.x1 <
return True
elif co1.x2 > co2.x1 and co1.x2
return True
elif co2.x1 > co1.x1 and co2.x1
return True

elif co2.x2 > co1.x1 and co2.x2
return True

else:

return False






234

Часть III. Пишем игру «Человечек спешит к выходу»

co2.x2:
< co2.x2:
< co1.x2:
< co1.x2:

Функция within_x принимает
аргументы co1 и co2 (и тот и другой — объекты класса Coord). В строке  проверяем, находится ли левая x-координата первого объекта
(co1.x1) между левой и правой x-координатами второго объекта. Если это
так, в строке  возвращаем True.
Посмотрите на два отрезка, x-координаты которых пересекаются:
x-координаты начала каждого из отрезков — это x1, а x-координаты
конца — x2.

x1=50

co1

x2=100

x1=40

x2=150

co2

Первый отрезок на схеме (co1) начинается с позиции 50 (x1) и заканчивается в позиции 100 (x2). Второй отрезок (co2) начинается с позиции 40 и заканчивается в позиции 150. Поскольку в данном случае
координата x1 первого отрезка находится между координатами x1 и x2
второго отрезка, первая из конструкций if сработает и функция вернет
True.
В строке  проверяем, находится ли правая координата первого отрезка (co1.x2) между левой (co2.x1) и правой (co2.x2) координатами
второго отрезка. Если это так, в строке  функция возвращает значение
True. Проверки elif в строках  и  нужны примерно для этого же.
Однако теперь левая и правая координаты второго отрезка (co2) сравниваются с координатами первого отрезка (co1).
Если ни одна из этих проверок не сработает, будет выполнен вариант
else в строке  и мы вернем из функции значение False, что означает:
горизонтальные координаты этих отрезков не пересекаются.
Чтобы посмотреть на функцию within_x в действии, вернемся к схеме, где изображены два отрезка. Координаты x1 и x2 первого из них — 40
и 100, а x1 и x2 второго — 50 и 150. Вызовем функцию within_x для
этого набора координат:

>>> c1 = Coords(40, 40, 100, 100)
>>> c2 = Coords(50, 50, 150, 150)
>>> print(within_x(c1, c2))
True

16. Разработка игры

235

Функция вернула True. Это первый шаг к проверке столкновения
двух спрайтов. Теперь, создав классы для фигурки человечка и платформ,
мы сможем узнать, пересекаются ли их x-координаты.
Несколько конструкций elif, которые возвращают одно и то же значение, — не очень хороший стиль программирования. Можно сократить
код функции within_x, заключив каждое из условий в скобки и объединив их с помощью ключевого слова or. Если хотите, чтобы функция стала короче и аккуратнее, замените ее код таким:

def within_x(co1, co2):
if (co1.x1 > co2.x1 and co1.x1 < co2.x2)
or (co1.x2 > co2.x1 and co1.x2 <
or (co2.x1 > co1.x1 and co2.x1 <
or (co2.x2 > co1.x1 and co2.x2 <
return True
else:
return False

\
co2.x2) \
co1.x2) \
co1.x2):

Мы снова воспользовались символом «обратный слеш» (\), чтобы
разбить очень длинную строку с условиями на несколько частей.

Пересечение по вертикали
При определении столкновений нужно
учитывать и вертикальные координаты.
Функция within_y очень похожа на функцию within_x — мы проверяем, находится
ли координата y1 первого спрайта между
координатами y1 и y2 второго и так далее.
Добавьте код этой функции в программу
следом за функцией within_x. Напишем
короткий вариант с объединением условий
по or (или):

def within_y(co1, co2):
if (co1.y1 > co2.y1 and co1.y1 < co2.y2)
or (co1.y2 > co2.y1 and co1.y2 <
or (co2.y1 > co1.y1 and co2.y1 <
or (co2.y2 > co1.y1 and co2.y2 <
return True
else:
return False

236

Часть III. Пишем игру «Человечек спешит к выходу»

\
co2.y2) \
co1.y2) \
co1.y2):

Собираем по частям код проверки столкновений
Мы можем определить, пересекается ли одна пара x-координат с другой,
и то же самое — для y-координат. Теперь можно написать код, проверяющий, столкнулся ли один спрайт с другим и какой стороной. Создадим
для этого функции collided_left, collided_right, collided_top
и collided_bottom.

Collide — столкновение

Функция collided_left
Добавьте код функции collided_left (столкновение слева) в программу после функций within_x и within_y:
 def collided_left(co1, co2):

if within_y(co1, co2):

if co1.x1 = co2.x1:

return True

return False

Эта функция возвращает True, если один объект класса Coords
столкнулся левой стороной (координата x1) с другим объектом.
Функция принимает два аргумента: co1 (первый координатный объект) и co2 (второй координатный объект). В строке  проверяем, пересекаются ли наши объекты по вертикали. Вызываем для этого функцию
within_y. Если человечек находится над платформой, нет смысла проверять, столкнулся он с ней или нет (см. рисунок):
x1,y1

x1,y1

Нет пересечения по y
x1,y1

Платформа
x2,y2

В строке  проверяем, находится ли левая горизонтальная координата первого координатного объекта (co1.x1) между правой и левой
координатами второго объекта (co2.x2 и co2.x1), что соответствует
столкновению левой стороны первого объекта со вторым. Если это так,

16. Разработка игры

237

в строке  функция возвращает значение True.
В противном случае в строке  возвращаем
False.

Функция collided_right
Функция collided_right определяет столкновение правой стороны первого объекта со вторым и очень похожа на collided_left:






def collided_right(co1, co2):
if within_y(co1, co2):
if co1.x2 >= co2.x1 and co1.x2 = co2.y1 and y_calc 0.1:
self.last_time = time.time()
self.current_image += self.current_image_add
if self.current_image >= 2:
self.current_image_add = -1
if self.current_image 0.1:

18. Доделываем игру

255












self.last_time= time.time()
self.current_image += self.current_image_add
if self.current_image >= 2:
self.current_image_add = -1
if self.current_image 0:
if self.y != 0:
self.game.canvas.itemconfig(self.image, \
image=self.images_right[2])
else:
self.game.canvas.itemconfig(self.image, \
image=self.images_right[self.current_image])

В строке  выполняется проверка: если свойство x меньше 0, значит, фигурка движется влево, в этом случае мы переходим к блоку кода
со строки  по строку . В строке  сравниваем свойство y с 0, и если y
не равно 0 (фигурка находится в прыжке или падает), в строке  с помощью функции itemconfig меняем изображение фигурки на последний
кадр в списке изображений, повернутых влево (images_left[2]). Выбираем кадр с самым широким шагом, чтобы анимация прыжка выглядела более реалистично:

Если y равно 0, в строке  выполняется вариант else, а в строке 
с помощью itemconfig меняем текущее изображение на кадр, индекс которого находится в свойстве current_image.
В строке  проверяем, движется ли фигурка вправо (x больше 0).
Если это так, выполняется блок кода со строки  по строку . Этот код
очень похож на код для движения влево: делается проверка, находится ли
фигурка в прыжке, и так далее, но кадры выбираются из списка images_
right, где хранятся изображения фигурки, повернутой вправо.

256

Часть III. Пишем игру «Человечек спешит к выходу»

Получение позиции фигурки
Нам важно знать, где находится фигурка на игровом экране, а поскольку она движется, функция coords класса StickFigureSprite будет
отличаться от одноименной функции родительского класса Sprite.
Воспользуемся функцией холста coords, чтобы узнать положение фигурки, и в соответствии с этим выставим значения x1, y1, x2 и y2 свойства
coordinates, которое создается в функции __init__ класса Sprite.
Добавьте этот код после функции animate:
if self.x < 0:
if self.y != 0:
self.game.canvas.itemconfig(self.image, \
image=self.images_left[2])
else:
self.game.canvas.itemconfig(self.image, \
image=self.images_left[self.current_image])
elif self.x > 0:
if self.y != 0:
self.game.canvas.itemconfig(self.image, \
image=self.images_right[2])
else:
self.game.canvas.itemconfig(self.image, \
image=self.images_right[self.current_image])







def coords(self):
xy = self.game.canvas.coords(self.image)
self.coordinates.x1 = xy[0]
self.coordinates.y1 = xy[1]
self.coordinates.x2 = xy[0] + 27
self.coordinates.y2 = xy[1] + 30
return self.coordinates

Создавая в главе 16 класс Game, мы добавили в него свойство canvas,
содержащее объект-холст. В строке  вызываем функцию coords этого
холста (self.game.canvas.coords), которая возвращает x- и y-координаты изображения (идентификатор изображения хранится в свойстве
image, которое мы передаем функции в качестве аргумента).
Функция холста coords возвращает список (мы сохраняем его в переменной xy), где находятся два элемента — x- и y-координаты левого
верхнего угла изображения. В строке  сохраняем x-координату как значение x1 свойства coordinates, а в строке  — y-координату как значение y1 свойства coordinates.
Поскольку все изображения фигурки одинакового размера — 27 пикселей в ширину и 30 в высоту, — мы можем вычислить значения x2 и y2,
прибавляя ширину (в строке ) и высоту (в строке ) к координатам x и y
соответственно.

18. Доделываем игру

257

В последней строке кода возвращаем из функции свойство
coordinates.

Перемещение фигурки по экрану
Последняя из функций класса StickFigureSprite — move — отвечает
за перемещение человечка по холсту, а также обрабатывает столкновения фигурки с другими объектами или границами экрана.

Начало функции move
Вот первая часть функции move. Этот код должен располагаться после
функции coords:

def coords(self):
xy = self.game.canvas.coords(self.image)
self.coordinates.x1 = xy[0]
self.coordinates.y1 = xy[1]
self.coordinates.x2 = xy[0] + 27
self.coordinates.y2 = xy[1] + 30
return self.coordinates









def move(self):
self.animate()
if self.y < 0:
self.jump_count += 1
if self.jump_count > 20:
self.y = 4
if self.y > 0:
self.jump_count -= 1

В строке  вызываем функцию animate, созданную ранее (она переключает кадры анимации по мере необходимости). В строке  проверяем, меньше ли нуля значение y. Если да, значит фигурка находится
в прыжке, поскольку отрицательное значение y соответствует движению вверх (напоминаю: верх холста — это y-координата 0, а низ — y-координата 500).
В строке  увеличиваем jump_count на 1, а в строке  проверяем,
не стало ли значение jump_count больше 20. Если стало, в строке  задаем свойству y значение 4, чтобы фигурка начала падать.
В строке  проверяем: y больше 0? Если так, значит, фигурка падает, тогда мы уменьшаем jump_count на 1, поскольку, досчитав до 20,
нужно переходить на обратный отсчет. Чтобы представить, как работает
счетчик jump_count, медленно поднимайте руку вверх, считая до 20,
а затем опускайте ее вниз, считая от 20 до 0.

258

Часть III. Пишем игру «Человечек спешит к выходу»

В нескольких следующих строках функции move вызываем функцию
coords, которая возвращает позицию фигурки на экране, и сохраняем
эту позицию в переменной co. Затем создаем переменные left, right,
top, bottom и falling, которые нам скоро понадобятся.

Falling —
падающий

if self.y > 0:
self.jump_count -= 1
co = self.coords()
left = True
right = True
top = True
bottom = True
falling = True

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








bottom = True
falling = True
if self.y > 0 and co.y2 >= self.game.canvas_height:
self.y = 0
bottom = False
elif self.y < 0 and co.y1 = self.game.canvas_width:
self.x = 0
right = False
elif self.x < 0 and co.x1 0 and collided_right(co, sprite_co):
self.x = 0
right = False

В строке  смотрим, нужно ли обрабатывать столкновения слева (left
все еще равняется True) и движется ли фигурка влево (x меньше 0). Вызывая функцию collided_left, проверяем столкновение левой стороны

18. Доделываем игру

263

фигурки со спрайтом. Если все в порядке, в строке  обнуляем x (чтобы
остановить фигурку), а в строке  присваиваем переменной left значение
False, чтобы больше не выполнять проверок на столкновение слева.
Столкновение справа в строке  обрабатывается аналогичным
образом. При выполнении всех условий обнуляем x в строке , устанавливаем переменную right в False в строке  и больше к этому
не возвращаемся.
Полный цикл проверок (с четырех сторон) должен выглядеть так:
elif self.x < 0 and co.x1 0 and collided_bottom(self.y, \
co, sprite_co):
self.y = sprite_co.y1 - co.y2
if self.y < 0:
self.y = 0
bottom = False
top = False
if bottom and falling and self.y == 0 \
and co.y2 < self.game.canvas_height \
and collided_bottom(1, co, sprite_co):
falling = False
if left and self.x < 0 and collided_left(co, sprite_co):
self.x = 0
left = False
if right and self.x > 0 and collided_right(co, sprite_co):
self.x = 0
right = False

Осталось добавить в функцию move несколько строк (уже после
цикла):





264

if right and self.x > 0 and collided_right(co, sprite_co):
self.x = 0
right = False
if falling and bottom and self.y == 0 \
and co.y2 < self.game.canvas_height:
self.y = 4
self.game.canvas.move(self.image, self.x, self.y)

Часть III. Пишем игру «Человечек спешит к выходу»

В строке  проверяем переменные falling и bottom на равенство
True (если так, значит, перебрав все спрайты в списке, мы не обнаружили столкновений снизу). Затем еще одна проверка: нижняя y-координата
фигурки меньше высоты холста? Если так, фигурка находится над землей
(над нижней границей холста). Поскольку человечек ни с чем не соприкасается снизу и находится выше уровня земли, значит, он завис в воздухе
и ему остается только падать, потому что он выбежал за край платформы.
Чтобы этого не произошло, в строке  присваиваем свойству y значение 4.
В строке  двигаем изображение человечка по экрану в соответствии
с текущими значениями свойств x и y. Во время обработки столкновений эти
свойства могли обнулиться — тогда фигурка останется на прежнем месте.

Проверяем спрайт человечка
Класс StickFigureSprite готов к использованию. Проверим, как он
работает, добавив две строки кода перед вызовом функции mainloop:
 sf = StickFigureSprite(g)
 g.sprites.append(sf)
g.mainloop()

В строке  создаем объект класса StickFigureSprite, сохраняя
его в переменной sf. В строке  добавляем этот объект в список спрайтов так же, как делали это с платформами.
Запустите программу и убедитесь, что человечек может бегать, прыгать с платформы на платформу и падать.

18. Доделываем игру

265

Дверь
Не хватает одного элемента — выхода, то есть двери. Создадим спрайт
двери, напишем код, позволяющий человечку в нее войти, и добавим
в программу объект-дверь.

Создаем класс DoorSprite
Для двери нужен еще один класс. Назовем его DoorSprite. Вот первая
часть кода:
class DoorSprite(Sprite):
def __init__(self, game, photo_image, x, y, width, height):
Sprite.__init__(self, game)
self.photo_image = photo_image
self.image = game.canvas.create_image(x, y, \
image=self.photo_image, anchor='nw')

self.coordinates = Coords(x, y, x + (width / 2), y + height)

self.endgame = True





В строке  определяем функцию __init__ класса DoorSprite,
которая принимает семь аргументов: self, game (главный объект игры), photo_image (изображение), координаты x и y, width (ширина изображения) и height
(высота изображения). В строке  вызываем функцию
__init__ класса Sprite (так же, как вызывали ее в других классах, для которых Sprite является предком).
В строке  сохраняем аргумент photo_image в одноименном
свойстве (так же, как делали это для класса PlatformSprite).
В строке  создаем изображение на холсте с помощью функции
create_image и сохраняем полученный из этой функции идентификатор в свойстве image.
В строке  выставляем значение свойства coordinates, используя
аргументы x и y в качестве координат x1 и y1 и вычисляя значения координат x2 и y2. Чтобы получить x2, прибавляем половину ширины изображения к аргументу x. Например, если x равно 10 (соответственно, координата x1 тоже равна 10), а ширина (width) — 40 пикселям, координата
x2 примет значение 30 (10 + 40/2).
Эти вычисления нужны, чтобы человечек не уперся в дверь сбоку,
а вошел в нее. Запустив игру и добравшись до двери, вы увидите, что
получилось.
Координату y2 вычислять проще, чем х2. Достаточно прибавить высоту изображения (height) к аргументу y.
В строке  задаем свойству endgame значение True. Это признак
того, что фигурка добежала до двери и игра закончилась.

266

Часть III. Пишем игру «Человечек спешит к выходу»

Дверь и конец игры
Теперь нужно изменить код функции move класса StickFigureSprite —
ту его часть, которая обрабатывает столкновения со спрайтами справа
и слева. Вот первое изменение:
if left and self.x < 0 and collided_left(co, sprite_co):
self.x = 0
left = False
if sprite.endgame:
self.game.running = False

Проверяем, содержит ли свойство endgame спрайта, с которым фигурка столкнулась левой стороной, True. Если это так, даем свойству
running значение False (фигурка добралась до двери, и игру нужно
завершить).
Добавим в код, проверяющий столкновение справа, эти же строки:
if right and self.x > 0 and collided_right(co, sprite_co):
self.x = 0
right = False
if sprite.endgame:
self.game.running = False

Добавляем объект-дверь
Осталось добавить в игру объект класса DoorSprite, то есть дверь.
Сделать это нужно до вызова функции mainloop. Создадим объект-дверь
раньше, чем объект-фигурку, и добавим ее в список спрайтов:
g.sprites.append(platform7)
g.sprites.append(platform8)
g.sprites.append(platform9)
g.sprites.append(platform10)
door = DoorSprite(g, PhotoImage(file="door1.gif"), 45, 30, 40, 35)
g.sprites.append(door)
sf = StickFigureSprite(g)
g.sprites.append(sf)
g.mainloop()

При создании класса DoorSprite передаем следующие аргументы:
g (главный объект игры), объект PhotoImage (изображение двери, созданное в главе 15), координаты x и y (45 и 30, чтобы дверь располагалась

18. Доделываем игру

267

на платформе вверху игрового экрана), ширину и высоту изображения
(40 и 35). Затем добавляем объект door в список спрайтов аналогично
остальным спрайтам.
Добежав до двери, человечек остановится не сбоку от нее, а шагнув
внутрь:

Код игры целиком
В итоге программа должна состоять из более чем 200 строк кода. Если
ваша игра не работает, сверьте каждую функцию (и каждый класс) с этим
кодом и исправьте ошибку.
from tkinter import *
import random
import time
class Game:
def __init__(self):
self.tk = Tk()
self.tk.title("Человечек спешит к выходу")
self.tk.resizable(0, 0)
self.tk.wm_attributes("-topmost", 1)
self.canvas = Canvas(self.tk, width=500, height=500, \
highlightthickness=0)

268

Часть III. Пишем игру «Человечек спешит к выходу»

self.canvas.pack()
self.tk.update()
self.canvas_height = 500
self.canvas_width = 500
self.bg = PhotoImage(file="background.gif")
w = self.bg.width()
h = self.bg.height()
for x in range(0, 5):
for y in range(0, 5):
self.canvas.create_image(x * w, y * h, \
image=self.bg, anchor='nw')
self.sprites = []
self.running = True
def mainloop(self):
while 1:
if self.running == True:
for sprite in self.sprites:
sprite.move()
self.tk.update_idletasks()
self.tk.update()
time.sleep(0.01)
class Coords:
def __init__(self, x1=0, y1=0, x2=0, y2=0):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
def within_x(co1, co2):
if (co1.x1 > co2.x1 and co1.x1 < co2.x2)
or (co1.x2 > co2.x1 and co1.x2 <
or (co2.x1 > co1.x1 and co2.x1 <
or (co2.x2 > co1.x1 and co2.x2 <
return True
else:
return False
def within_y(co1, co2):
if (co1.y1 > co2.y1 and co1.y1 < co2.y2)
or (co1.y2 > co2.y1 and co1.y2 <
or (co2.y1 > co1.y1 and co2.y1 <
or (co2.y2 > co1.y1 and co2.y2 <
return True
else:
return False

\
co2.x2) \
co1.x2) \
co1.x2):

\
co2.y2) \
co1.y2) \
co1.y2):

def collided_left(co1, co2):
if within_y(co1, co2):
if co1.x1 = co2.x1:

18. Доделываем игру

269

return True
return False
def collided_right(co1, co2):
if within_y(co1, co2):
if co1.x2 >= co2.x1 and co1.x2 = co2.y1 and y_calc 0.1:
self.last_time = time.time()
self.current_image += self.current_image_add
if self.current_image >= 2:
self.current_image_add = -1
if self.current_image 0:
if self.y != 0:
self.game.canvas.itemconfig(self.image, \
image=self.images_right[2])
else:
self.game.canvas.itemconfig(self.image, \
image=self.images_right[self.current_image])
def coords(self):

18. Доделываем игру

271

xy = self.game.canvas.coords(self.image)
self.coordinates.x1 = xy[0]
self.coordinates.y1 = xy[1]
self.coordinates.x2 = xy[0] + 27
self.coordinates.y2 = xy[1] + 30
return self.coordinates
def move(self):
self.animate()
if self.y < 0:
self.jump_count += 1
if self.jump_count > 20:
self.y = 4
if self.y > 0:
self.jump_count -= 1
co = self.coords()
left = True
right = True
top = True
bottom = True
falling = True
if self.y > 0 and co.y2 >= self.game.canvas_height:
self.y = 0
bottom = False
elif self.y < 0 and co.y1 0 and co.x2 >= self.game.canvas_width:
self.x = 0
right = False
elif self.x < 0 and co.x1 0 and collided_bottom(self.y, \
co, sprite_co):
self.y = sprite_co.y1 - co.y2
if self.y < 0:
self.y = 0
bottom = False
top = False
if bottom and falling and self.y == 0 \
and co.y2 < self.game.canvas_height \
and collided_bottom(1, co, sprite_co):
falling = False

272

Часть III. Пишем игру «Человечек спешит к выходу»

if left and self.x < 0 and collided_left(co, sprite_co):
self.x = 0
left = False
if sprite.endgame:
self.game.running = False
if right and self.x > 0 and collided_right(co, sprite_co):
self.x = 0
right = False
if sprite.endgame:
self.game.running = False
if falling and bottom and self.y == 0 \
and co.y2 < self.game.canvas_height:
self.y = 4
self.game.canvas.move(self.image, self.x, self.y)
class DoorSprite(Sprite):
def __init__(self, game, photo_image, x, y, width, height):
Sprite.__init__(self, game)
self.photo_image = photo_image
self.image = game.canvas.create_image(x, y, \
image=self.photo_image, anchor='nw')
self.coordinates = Coords(x, y, x + (width / 2), y + height)
self.endgame = True
g = Game()
platform1 = PlatformSprite(g, PhotoImage(file="platform1.gif"), \
0, 480, 100, 10)
platform2 = PlatformSprite(g, PhotoImage(file="platform1.gif"), \
150, 440, 100, 10)
platform3 = PlatformSprite(g, PhotoImage(file="platform1.gif"), \
300, 400, 100, 10)
platform4 = PlatformSprite(g, PhotoImage(file="platform1.gif"), \
300, 160, 100, 10)
platform5 = PlatformSprite(g, PhotoImage(file="platform2.gif"), \
175, 350, 66, 10)
platform6 = PlatformSprite(g, PhotoImage(file="platform2.gif"), \
50, 300, 66, 10)
platform7 = PlatformSprite(g, PhotoImage(file="platform2.gif"), \
170, 120, 66, 10)
platform8 = PlatformSprite(g, PhotoImage(file="platform2.gif"), \
45, 60, 66, 10)
platform9 = PlatformSprite(g, PhotoImage(file="platform3.gif"), \
170, 250, 32, 10)
platform10 = PlatformSprite(g, PhotoImage(file="platform3.gif"), \
230, 200, 32, 10)
g.sprites.append(platform1)
g.sprites.append(platform2)
g.sprites.append(platform3)
g.sprites.append(platform4)
g.sprites.append(platform5)
g.sprites.append(platform6)
g.sprites.append(platform7)

18. Доделываем игру

273

g.sprites.append(platform8)
g.sprites.append(platform9)
g.sprites.append(platform10)
door = DoorSprite(g, PhotoImage(file="door1.gif"), 45, 30, 40, 35)
g.sprites.append(door)
sf = StickFigureSprite(g)
g.sprites.append(sf)
g.mainloop()

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

274

Часть III. Пишем игру «Человечек спешит к выходу»

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

#1. «Вы победили!»
Когда человечек доберется до двери, выводите сообщение «Вы победили!». (Вспомните, как делали то же самое, печатая «Конец игры» для созданной в главе 14 игры «Прыг-скок!».)

#2. Анимация двери
В главе 15 мы создали два изображения двери — открытую
и закрытую. Когда человечек в нее войдет, изображение должно поменяться (с закрытой двери на открытую). Затем человечек должен исчезнуть, а дверь закрыться. Тогда возникнет
иллюзия, что наш герой открывает дверь, заходит и закрывает ее за собой. Измените для этого код классов DoorSprite
и StickFigureSprite.

#3. Движущиеся платформы
Создайте новый класс для движущихся платформ — MovingPlatform
Sprite. Они должны непрерывно перемещаться по горизонтали (от левой стороны игрового экрана до правой и обратно), из-за чего человечку
будет сложнее добраться до выхода.

ПОС ЛЕС ЛОВИЕ:
К УД А Д В И ГАТ Ь С Я Д А Л Ь Ш Е

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

Игры и программирование графики
Если вы хотите серьезно заняться программированием игр и графики,
для этого есть немало инструментов. Вот лишь некоторые из них:
• BlitzBasic (http://www.blitzbasic.com/) — версия языка BASIC,
созданная специально для разработки игр.
• Alice (http://www.alice.org/) — среда для программирования
3D-графики.
• Scratch (http://scratch.mit.edu/) — визуальный язык программирования, подходящий для создания двухмерных игр.
• Unity3D (http://unity3d.com/) — мощная визуальная среда для
разработки двухмерных и трехмерных игр.

276

• Adobe Flash — среда для создания анимаций, работающих в веббраузере, оснащенная собственным языком программирования
ActionScript (http://www.adobe.com/devnet/actionscript.html).
В интернете вы найдете множество обучающих ресурсов по каждому
из этих инструментов.
Если же вы хотите продолжить работу с Python, вам может пригодиться специально созданная для написания игр библиотека модулей
PyGame. Рассмотрим ее подробнее ниже.

PyGame
Чтобы установить PyGame на Windows или Mac OS X, скачайте последнюю версию установочного пакета с веб-страницы http://www.pygame.
org/download.shtml. А если вы используете Ubuntu, установите PyGame
из центра приложений. С документацией к PyGame можно ознакомиться
по адресу http://www.pygame.org/docs/.
Писать игры с помощью PyGame немного сложнее, чем с tkinter.
Например, в главе 12 мы использовали tkinter для вывода изображения на экран следующим образом:
from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=400, height=400)
canvas.pack()
myimage = PhotoImage(file='c:\\test.gif')
canvas.create_image(0, 0, anchor=NW, image=myimage)

Чтобы сделать то же при помощи PyGame (но загружая .bmp-файл,
а не .gif), понадобится примерно такой код:










import sys
import time
import pygame
import pygame.image as image
import pygame.display as display
pygame.init()
img = image.load("c:\\test.bmp")
screen = display.set_mode((img.get_width(), img.get_height()))
screen.fill(pygame.Color(255, 255, 255))
screen.blit(img, (0, 0))
display.flip()
time.sleep(10)
display.quit()

277

Load — загрузить
Screen — экран
Set mode —
задать режим
Display — показать, экран

Quit — выйти

После импортирования модулей вызываем функцию init модуля
pygame в строке . Это приблизительно соответствует созданию холста и вызову функции pack в примере для tkinter. В строке  загружаем .bmp-файл с изображением, который мы скопировали или создали предварительно в той же папке, где размещается наша программа,
с помощью функции load PyGame-модуля image. В строке  создаем
объект screen, вызывая функцию set_mode PyGame-модуля display.
В строке  (без которой можно и обойтись) очищаем экран, заполняя
его белым цветом. В строке  вызываем функцию объекта-экрана blit,
которая выводит на экран изображение. Эта функция принимает само
изображение, а также кортеж с позицией, где мы хотим его вывести (отступ 0 пикселей слева и 0 пикселей сверху).
PyGame использует внеэкранный буфер (также это называют двойной
буферизацией), то есть формирует экранную картинку в памяти компьютера, где она невидима, и переносит ее на экран. Двойная буферизация
уменьшает эффект мерцания, который может возникнуть при выводе
движущихся объектов на экран. В нашем примере копирование внеэкранного буфера на экран выполняет функция flip в строке .
В строке  делаем 10-секундную паузу, поскольку, в отличие от холста tkinter, окно PyGame при завершении программы сразу же закрывается. В строке  вызываем функцию display.quit, чтобы PyGame
корректно завершила работу. PyGame, конечно, способна на большее,
но по этому примеру уже можно составить о ней первое впечатление.

Языки программирования
Среди наиболее популярных языков программирования кроме Python
можно отметить Java, C/C++, C#, PHP, Objective-C, Perl, Ruby и JavaScript.
Рассмотрим эти языки, включая код программы «Привет, мир» (аналог
Python-версии из главы 1) для каждого из них. Имейте в виду, что перечисленные языки заметно отличаются от Python и не ориентированы на начинающих программистов. Поскольку не все языки позволяют выводить
русский текст так же просто, как Python, будем печатать английское «Hello
World» вместо «Привет, мир», чтобы не усложнять код примеров.

Java
Java (http://www.oracle.com/technetwork/java/index.html) — это язык программирования средней сложности, укомплектованный обширной библиотекой
модулей, которые называются пакетами. В интернете много бесплатной документации по Java. Использовать этот язык можно практически во всех
операционных системах. Java — основной язык, на котором создаются приложения для мобильных телефонов под управлением Android.

278

Послесловие: куда двигаться дальше

Программа «Привет, мир» на языке Java выглядит так:
Hello world —
привет, мир

public class HelloWorld {
public static final void main(String[] args) {
System.out.println("Hello World");
}
}

C/C++
C (http://www.cprogramming.com/) и C++ (http://www.stroustrup/C++.
html) — это сложные языки программирования, доступные для всех операционных систем, причем есть как бесплатные, так и коммерческие
версии. В частности, многие действия, которые в Python выполняются
автоматически, в C/C++ придется программировать самостоятельно
(например, запрашивать у компьютера блок памяти для хранения объекта). Многие коммерческие игры, в том числе для игровых приставок,
написаны на том или ином диалекте C или C++.
Вот программа «Привет, мир» на языке C:
#include
int main ()
{
printf ("Hello World\n");
}

А вот «Привет, мир» на C++:
#include
int main()
{
std::cout