Глава 8. Модули
Упорство и сила духа творили чудеса во все времена.
Джордж Вашингтон
Представьте, что вы написали программу размером в 10 000 строк кода. Если бы вы поместили весь код в один файл, в нем было бы сложно разобраться. Каждый раз при возникновении ошибки или исключения вам пришлось бы пролистывать
10 000 строк кода в поисках одной-единственной проблемной строки. Програм- мисты выходят из ситуации путем разделения огромных программ на модули, — другое название файлов с кодом на языке Python — которые содержат отдельные фрагменты кода. Python позволяет использовать код из одного модуля в другом модуле. В Python также есть встроенные модули, содержа щие важную функцио- нальность. В этой главе вы узнаете о модулях и о том, как их использовать.
Импорт встроенных модулей
Чтобы использовать модуль , его сначала нужно импортировать , то есть напи- сать код, который сообщит Python, где искать модуль. Импортировать модуль можно командой с синтаксисом import _
. Замените значение _
именем модуля, который вы импортируете. Как только вы выполнили импорт модуля, вы можете использовать его переменные и функции.
У Python есть много различных модулей, включая модуль math, предостав- ляющий математический функционал. Полный перечень встроенных модулей
Python можно найти на странице docs.python.org/3/py-modindex.html. Ниже показано, как импортируется модуль math.
Python_ex211.py
1
import math
Как только вы импортировали модуль, можно использовать его код при по- мощи синтаксиса _ . , указав _ , который вы импор-
94
Часть I
тировали, и — имя желаемой функции или переменной из модуля. Ниже приведен пример импорта и использования функции pow из модуля math, при- нимающей два параметра, x и y, и возводящей x в степень y.
Python_ex212.py
1
import math
2
math.pow(2, 3)
>> 8.0
Для начала, первой строкой импортируйте модуль math. Все модули следует импортировать в верхней части файла, чтобы их было проще отслеживать. За- тем вызовите функцию pow с помощью инструкции math.pow(2, 3). Функция вернет значение 8.0.
random
— еще один встроенный модуль. Вы можете использовать его функ- цию randint для создания случайного числа: передайте функции два целых чис- ла, и она вернет выбранное случайным образом целое число в промежутке меж- ду ними.
Python_ex213.py
1
# * & 52,
2
# B !
3
import random
4
random.randint(0,100)
>> 52
Также можно использовать встроенный модуль statistics, чтобы подсчи- тать среднее значение, медиану и моду в итерируемом объекте, состоящем из чисел.
Python_ex214.py
1
import statistics
2
#
3
nums
= [1, 5, 33, 12, 46, 33, 2]
4
statistics.mean(nums)
5
#
6
statistics.median(nums)
7
#
8
statistics.mode(nums)
95
Введение в программирование
>> 18.857142857142858
>> 12
>> 33
Встроенный модуль keyword позволяет проверить, является ли строка клю- чевым словом в Python.
Python_ex215.py
1
import keyword
2
keyword.iskeyword("for")
3
keyword.iskeyword("football")
>> True
>> False
Импорт других модулей
В этом разделе вы создадите модуль, импортируете его в другой модуль и исполь- зуете его код. Сначала создайте папку tstp. В этой папке создайте файл hello.py.
Введите в созданный файл указанный ниже код и сохраните файл.
Python_ex216.py
1
def print_hello():
2
print("")
В папке tstp создайте еще один файл, project.py. Введите в файл project.py указан- ный ниже код и сохраните файл.
Python_ex217.py
1
import hello
2 hello.print_hello()
>>
В данном примере вы указали ключевое слово import, чтобы использовать код из вашего первого модуля во втором модуле.
Когда вы импортируете модуль, выполняется весь код в нем. При помощи следующего кода создайте модуль module1.py.
Python_ex218.py
1
# module1 2
print("!")
>> !
96
Часть I
Код из модуля module1.py будет выполнен, когда вы импортируете этот модуль в другой, module2.py.
Python_ex219.py
1
# module2 2
import hello
>> !
Подобное поведение может доставлять неудобства. К примеру, в вашем моду- ле может быть тестовый код, который вы бы не хотели выполнять при импорте модуля. Эта проблема решается путем добавления инструкции if __name__ ==
"__main__".
Так, код в модуле module1.py из предыдущего примера можно изме- нить следующим образом.
Python_ex220.py
1
# module1 2
if __name__ == "__main__":
3
print("!")
>> !
Когда вы запускаете эту программу, вывод остается прежним. Но когда вы осу- ществляете импорт из модуля module2.py, код из модуля module1.py больше не выпол- няется, и слово ! не выводится.
Python_ex221.py
1
# module2 2
import hello
Словарь терминов
Встроенные модули: модули, которые поставляются в составе Python и содер- жат важную функциональность.
Импортирование модуля: строка кода, которая сообщает Python, где искать нужный модуль.
Модуль: другое название файла с кодом на языке Python.
Практикум
1. Вызовите какую-нибудь другую функцию из модуля statistics.
2. Создайте модуль cubed
, содержащий функцию, которая принимает в каче- стве параметра число, возводит это число в куб и возвращает его. Импорти- руйте и вызовите функцию из другого модуля.
Решения: chap8_challenge1.py и chap8_challenge2.py.
97
Введение в программирование
Глава 9. Файлы
Я твердо убежден, что самообразование — это единственно возможное образование.
Айзек Азимов
Вы можете работать с файлами, используя Python. Например, с помощью Python можно считывать данные из файла и записывать данные в файл. Чтение дан- ных из файла означает получение доступа к этим данным. Запись данных в файл означает добавление или изменение данных файла. В этой главе вы познакоми- тесь с основами работы с файлами.
Запись в файлы
Первый шаг в работе с файлом — открыть его с помощью встроенной в Python функции open. Эта функция принимает два параметра: строку, представляю- щую путь к нужному файлу, и строку, определяющую режим, в котором нужно открыть этот файл.
Путь к файлу представляет собой место на компьютере , в котором находит- ся файл. К примеру, строка /Users/bob/st.txt — это путь к файлу st.txt. Каж- дое слово перед именем файла, отделенное слешем, указывает на имя папки, а все это вместе представляет путь к файлу. Если путь к файлу состоит лишь из име- ни файла (и нет никаких папок, отделенных слешами), Python будет искать этот файл в той папке, откуда вы запустили свою программу. Нельзя прописывать путь к файлу самостоятельно. Unix-подобные операционные системы и Windows используют в путях к файлам разное количество слешей. Чтобы избежать про- блем с работой вашей программы в разных операционных системах, пути к фай- лам всегда нужно создавать с помощью встроенного модуля Python os module.
Функция path этого модуля принимает в качестве параметра каждую папку из пути к файлу и выстраивает вам правильный путь к файлу.
Python_ex222.py
1
import os
2
os.path.join("Users",
3
"bob",
4
"st.txt")
>> 'Users/bob/st.txt'
Создание путей к файлу при помощи функции path гарантирует, что файлы будут работать в любой операционной системе. Но работа с путями к файлам все еще может вызывать трудности. Если у вас возникли проблемы, посетите сайт
theselftaughtprogrammer.io/filepaths для получения дополнительной инфор- мации.
Режим, который вы передаете функции open, определяет действия, которые можно будет совершать с открываемым файлом. Ниже представлено несколько возможных режимов открытия файла:
98Часть I
• "r"
— открывает файл только для чтения.
• "w"
— открывает файл только для записи.
Удаляет содержимое файла, если файл существует; если файл не существует, создает новый файл для записи.
• "w+"
— открывает файл для чтения и записи. Удаляет содержимое фай- ла, если файл существует; если файл не существует, создает новый файл для чтения и записи
6
Функция open возвращает так называемый
файловый объект, который ис- пользуется для чтения и/или записи в ваш файл. Когда вы используете режим "w"
, функция open создает новый файл (если он еще не существует) в каталоге , где работает ваша программа.
Затем вы можете использовать метод write на файловом объекте, чтобы осуществить запись в файл, и метод close, чтобы закрыть его. Если вы откроете файл при помощи метода open, закрыть его нужно при помощи метода close.
Если вы используете метод open на нескольких файлах и забудете закрыть их, это может вызвать проблемы с программой. Ниже приведен пример открытия файла, записи в него и закрытия.
Python_ex223.py1
st
= open("st.txt", "w")
2
st.write(" Python!")
3
st.close()
В данном примере вы используете функцию open, чтобы открыть файл, и со- храняете файловый объект, возвращаемый ей, в переменной st. Затем вы вызы- ваете метод write на переменной st, который принимает строку как параметр и записывает ее в новый файл, созданный Python. Наконец, вы закрываете файл, вызывая метод close на файловом объекте.
Автоматическое закрытие файловЕсть также второй вариант синтаксиса для открытия файлов, с ним вам не нуж- но держать в памяти необходимость закрыть файлы. Чтобы использовать этот синтаксис, поместите весь код, которому требуется доступ к файловому объекту, внутрь
with — составной инструкции, автоматически выполняющей действие после того, как Python проходит ее.
Синтаксис для открытия файла с помощью инструкции with следующий: with open(
_ _, ) as
_ : _ . Значе- ние
_ _ представляет путь к вашему файлу, затем указывается &, в котором нужно открыть файл,
_ , которой назначен файловый объект, а значение
_ обозначает код, у которого есть доступ к этой пере- менной.
Когда вы используете этот синтаксис для открытия файла, файл автоматиче- ски закрывается после того, как выполняется последняя строка тела *_ .
Ниже приведен пример из предыдущего раздела, использующий для открытия, записи и закрытия файла этот синтаксис.
6
www.tutorialspoint.com/python/python_ les_io.htm
99
Введение в программирование
Python_ex224.py
1
with open("st.txt", "w") as f:
2
f.write(" Python!")
Пока интерпретатор находится внутри инструкции with, вы можете произ- водить доступ к файловому объекту (в этом случае, f). Как только Python завер- шает выполнение всего кода в инструкции with, Python закрывает файл автома- тически.
Чтение из файлов
Если вы хотите прочесть данные из файла , то передаете "r" в качестве второго параметра в open. Затем вы вызываете метод read в своем файловом объекте, что возвращает итерируемый объект со всеми строками файла.
Python_ex225.py
1
# ,
2
# B B X
3
#
4
with open("st.txt", "r") as f:
5
print(f.read())
>> Python!
Вызвать read, не закрывая и не открывая файл заново, можно лишь один раз, так что если вам понадобится содержимое файла позже, вы должны сохра- нить его в переменной или контейнере. Ниже показано, как сохранять содержи- мое файла из предыдущего примера в списке.
Python_ex226.py
1
my_list
= list()
2
with open("st.txt", "r") as f:
3
my_list.append(f.read())
4
pr int(my_list)
>> [' Python!']
Теперь позже в программе вы сможете получить доступ к этим данным.
CSV-файлы
Python содержит встроенный модуль, позволяющий работать с CSV-файлами .
CSV-файл имеет расширение .csv и содержит данные, разделенные с помощью запятых (CSV расшифровывается как Comma Separated Values — значения, раз-
100Часть I
деленные запятыми). Программы типа Excel, обрабатывающие электронные та- блицы, часто используют CSV-файлы. Каждый фрагмент данных, отделенный за- пятой в CSV-файле, представляет собой ячейку в электронной таблице, а каждая строка файла — строку в таблице.
Разделителем выступает символ (например, запятая или вертикальная черта |), используемый для разделения данных в CSV- файле. Ниже показано содержимое CSV-файла
self_taught.csv.
, ,,,,*
Если бы вы загрузили этот файл в Excel, тогда , и заняли бы по
ячейке в первой строке электронной таблицы, а , и * — по ячейке во второй.
CSV-файл можно открыть с помощью инструкции with, но внутри нее нужно ис- пользовать модуль csv, чтобы конвертировать файловый объект в объект csv. У моду- ля csv есть метод writer, который принимает файловый объект и разделитель. Ме- тод writer возвращает объект csv с помощью метода writerow. Метод writerow принимает в качестве параметра список, и вы можете его использовать для записи в
CSV-файл. Каждый элемент в списке записывается — отделенный разделителем, ко- торый вы передали методу writer — в строку в CSV-файле. Метод writerow создает только одну строку, так что для создания двух строк его нужно вызвать дважды.
Python_ex227.py1
import csv
2
with open("st.csv", "w") as f:
3
w
= csv.writer(f,
4
delimiter
=",")
5
w.writerow([" ",
6
" ",
7
""])
8
w.writerow(["",
9
"",
10
"*"])
Эта программа создает новый файл с именем
st.csv. Если вы откроете его в текстовом редакторе, его содержимое будет выглядеть вот так:
, ,
,,*
Если вы откроете этот файл в программе Excel (или в Google Таблицы, бесплат- ной альтернативе), запятые исчезнут, и слова , и будут помещены в ячейки в первой строке, а слова , и * — в ячейки во второй строке.
Модуль csv также можно использовать для чтения содержимого файла. Что- бы выполнить чтение из CSV-файла, сначала передайте значение "r" в качестве второго параметра функции open, чтобы открыть файл для чтения. После этого внутри инструкции with вызовите метод reader, передав в него файловый объ-
101
Введение в программирование ект и запятую в качестве разделителя — это вернет итерируемый объект, с помо- щью которого можно получить доступ к каждой строке файла.
Python_ex228.py
1
# ,
2
# B B X
3
import csv
4
with open("st.csv", "r") as f:
5
r
= csv.reader(f, delimiter=",")
6
for row in r:
7
print(",".join(row))
>> , ,
>> ,,*
В этом примере вы открываете файл st.csv для чтения и конвертируете его в объект csv, используя метод reader. Затем с помощью цикла вы выполняете пе- ребор объекта csv. При каждом прохождении цикла вы вызываете метод join в запятой, чтобы добавить запятую между каждым фрагментом данных в файле, и выводите содержимое так, как оно выглядит в исходном файле (с разделяющи- ми запятыми).
Словарь терминов
CSV-файл: файл с расширением .csv, внутри которого данные разделяю тся с помощью запятых (CSV расшифровывается как Comma Separated Values — зна- чения, разделенные запятыми). Часто используется в программах наподобие
Excel, обрабатывающих электронные таблицы.
Запись: добавление или изменение данных в файле.
Инструкция with: составная инструкция, автоматически выполняющая дей- ствие после того, как интерпретатор Python проходит ее.
Путь к файлу: расположение в системе хранения данных (например, на жест- ком диске) компьютера, в котором сохранен файл.
Разделитель: символ (например, запятая), используемый для разделения дан- ных в CSV-файле.
Файловый объект: объект, который может использоваться для чтения или записи в файл.
Чтение: получение доступа к содержимому файла.
Практикум
1. Найдите у себя на компьютере файл и выведите его содержимое с помощью
Python.
2. Напишите программу, которая задает пользователю вопрос и сохраняет от- вет в файл.
102Часть I
3. Примите элементы в списке списков [["B ", "K -
", "R "], [" ", "V ", "-
"], ["W ", "Q - ", " WY"]]
и запи- шите их в CSV-файл. Да нные
каждого списка должны быть строкой в файле, при этом каждый элемент списка должен быть отделен запятой.
Решения:
chap9_challenge2.py, chap9_challenge3.py и movies.csv.
Глава 10. Практикум. Часть IВсему, что я знаю, я научился из книг.
Авраам ЛинкольнВ этой главе вы объедините все ранее полученные знания и создадите текстовую игру, классическую «Виселицу» . Если вы никогда не играли в «Виселицу», то про- читайте правила ниже:
1. Первый игрок загадывает слово и рисует черту для каждой буквы в этом слове (вы будете использовать нижнее подчеркивание ).
2. Второй игрок пытается отгадать слово по одной букве за раз.
3. Если второй игрок правильно угадывает букву, первый игрок заменяет соответствующую черту этой правильной буквой. В данной версии игры, если буква встречается в слове дважды, ее нужно отгадать дважды.
4. Если второй игрок угадал неправильно, первый игрок рисует часть пове- шенной фигурки (начиная с головы).
5. Если второй игрок отгадывает все слово прежде, чем будет полностью нарисован висельник, он побеждает. Если нет, проигрывает.
В вашей программе компьютер будет первым игроком, а отгадывающий че- ловек — вторым. Вы готовы создать игру «Виселица»?
103
Введение в программирование
Игра «Виселица»
Ниже вы видите начало кода игры «Виселица»:
Python_ex229.py
1
def hangman(word):
2
wrong
= 0 3
stages
= ["",
4
"________ ",
5
"| ",
6
"| | ",
7
"| 0 ",
8
"| /|\ ",
9
"| / \ ",
10
"| "
11
]
12
rletters
= list(word)
13
board
= ["__"] * len(word)
14
win
=
False
15
print(" & B !")
Для начала создайте функцию hangman, где будет храниться игра. Эта функ- ция принимает в качестве параметра переменную word — это слово, которое должен отгадать второй игрок. Также присутствует переменная wrong, которая будет отслеживать, сколько неправильных предположений сделал второй игрок.
Переменная stages представляет собой список со строками, которые вы бу- дете использовать, чтобы рисовать висельника. Когда Python выводит каждую строку в списке stages на новой строке, появляется рисунок висельника. Пере- менная rletters является списком, содержащим каждый символ в переменной word
, и она отслеживает, какие буквы осталось отгадать.
Переменная board является списком строк, она используется для отслежи- вания подсказок, которые отображаются для второго игрока. Например, __, если правильное слово (и второй игрок уже отгадал буквы и ). Вы исполь- зуете инструкцию ["__"] * len(word), чтобы заполнить список board (одно нижнее подчеркивание для каждого символа в переменной word). Так, если сло- во — , тогда board вначале принимает вид ["__", "__", "__"].
Также есть переменная win, вначале принимающая значение False, для отслеживания, победил ли уже второй игрок. Затем код выводит строку
& B !
Следующей частью программы является цикл, обеспечивающий работу игры.
Python_ex230.py
1
while wrong < len(stages) - 1:
2
print("\n")
104Часть I
3
msg
= " : "
4
char
= input(msg)
5
if char
in rletters:
6
cind
= rletters.index(char)
7
board[cind]
= char
8
rletters[cind]
= '$'
9
else:
10
wrong
+= 1 11
print((" ".join(board)))
12
e
= wrong
+ 1 13
print("\n".join(stages[0: e]))
14
if "__"
not in board:
15
print(" ! B : ")
16
print(" ".join(board))
17
win
= True
18
breakВаш цикл (и игра) продолжается до тех пор, пока значение переменной wrong меньше, чем len(stages) — 1. Переменная wrong отслеживает коли- чество неправильных букв,
указанных вторым игроком, так что когда второй игрок предпримет больше неудачных догадок, чем есть строк для изображения фигуры висельника (количество строк в списке stages), игра окончится. Нуж- но вычесть 1 из длины списка stages, чтобы уравновесить то, что счет в списке stages начинается с 0, а в списке wrong — с 1.
Внутри цикла сразу выведите пустую область, чтобы украсить игру при вы- воде в оболочке. Затем примите догадку второго игрока с помощью встроенной функции input и сохраните значение в переменной guess.
Если значение переменной guess содержится в rletters (списке, который отслеживает буквы, которые второй игрок еще не угадал), значит, догадка игро- ка была правильной. В таком случае нужно обновить список board, который вы позже используете для отображения оставшихся букв. Если бы второй игрок от- гадал , вы бы изменили список board на ["", "__", "__"].
Используйте метод index в списке rletters, чтобы получить первый индекс буквы, которую отгадал второй игрок, и используйте его, чтобы в списке board заменить нижнее подчеркивание, имеющее индекс правильно угаданной буквы.
Здесь есть одна проблема. Поскольку index возвращает только первый ин- декс искомого символа, ваш код не будет работать, если переменная word содер- жит повторяющиеся символы. Чтобы обойти это, измените список rletters, заменив правильно угаданный символ знаком доллара. Таким образом, при сле- дующем прохождении цикла функция index найдет следующее вхождение бук- вы (если оно есть), а не остановится на первом вхождении.
Если же игрок делает неправильную догадку, вы увеличиваете значение пере- менной wrong на 1.
105Введение в программирование
Далее вы выводите строчку с результатом угадывания и виселицу при помо- щи списков board и stages. Код для первого следующий: ' '.join(board).
Вывод висельника немного сложнее. Когда каждая из строк в списке stages выводится на новой строке, отображается весь рисунок висельника. Вы можете создать весь рисунок с помощью кода '\n'.join(stages), что добавит строкам в списке stages новую строку, чтобы каждая строка выводилась по отдельности.
Чтобы выводить висельника на каждом этапе игры, выполните срез списка stages
. Начните с 0 и закончите на индексе, соответствующем значению пере- менной wrong плюс один. Нужно прибавить один, поскольку при выполнении среза его конец не включается в результат. Этот срез дает вам лишь те строки, которые нужны для отображения текущей версии висельника.
Наконец, вы проверяете, победил ли второй игрок. Если в списке board больше нет нижних подчеркиваний, значит, игрок отгадал все буквы и победил.
Если второй игрок победил, выводится строка ! B
:
и правильно отгаданное слово. Также присвойте переменной win значе- ние True, чтобы прервать цикл.
Как
только вы прервали цикл, в случае, если победил второй игрок, игра окончена, и вы ничего не предпринимаете. Если же игрок проиграл, значение переменной win False — в этом случае, выводится рисунок висельника полно- стью и строка ! B : с указанием слова, ко- торое игрок не смог отгадать.
Python_ex231.py1
if not win:
2
print("\n".join(stages[0: wrong]))
3
print(" ! B :
4
{}.".format(word))
Код игры целиком выглядит так:
Python_ex232.py1
def hangman(word):
2
wrong
= 0 3
stages
= ["",
4
"________ ",
5
"| ",
6
"| | ",
7
"| 0 ",
8
"| /|\ ",
9
"| / \ ",
10
"| "
11
]
12
rletters
= list(word)
13
board
= ["__"]
* len(word)
106Часть I
14
win
= False
15
print(" & B !")
16
while wrong < len(stages) - 1:
17
print("\n")
18
msg
= " : "
19
char
= input(msg)
20
if char
in rletters:
21
cind
= rletters.index(char)
22
board[cind]
= char
23
rletters[cind]
= '$'
24
else:
25
wrong
+= 1 26
print((" ".join(board)))
27
e
= wrong
+ 1 28
print("\n".join(stages[0: e]))
29
if "__" not in board:
30
print(
" ! B : ")
31
print(" ".join(board))
32
win
= True
33
break
34
if not win:
35
print("\n".join(stages[0: wrong]))
36
print
(" ! B :
{}.".format(word))
37
hangman(" ")
ПрактикумИзмените игру таким образом, чтобы слово случайно выбиралось из списка слов.
Решение:
chap10_challenge1.py.