Книга Изучаем Python
Скачать 4.68 Mb.
|
ПРИМЕЧАНИЕ Модули также можно загружать из внешних источников . Соответствующие примеры встретятся вам в части II, в которой для завершения работы над проектами мы будем использовать внешние модули . УПРАЖНЕНИЯ 9-13 . Переработка с OrderedDict Rewrite: начните с упражнения 6-4 (с . 113), в котором стандартный словарь используется для представления глоссария . Перепишите программу с использованием класса OrderedDict и убедитесь в том, что порядок вывода совпадает с порядком добавления пар «ключ—значение» в словарь . 9-14 . Кубики: модуль random содержит функции для генерирования случайных чисел раз- ными способами . Функция randint() возвращает целое число в заданном диапазоне . Следу- ющий код возвращает число от 1 до 6: from random import randint x = randint(1, 6) Создайте класс Die с одним атрибутом с именем sides, который содержит значение по умол- чанию 6 . Напишите метод roll_die() для вывода случайного числа от 1 до количества сторон кубика . Создайте экземпляр, моделирующий 6-гранный кубик, и имитируйте 10 бросков . Создайте модели 10- и 20-гранного кубика . Имитируйте 10 бросков каждого кубика . 9-15 . Модуль недели: для знакомства со стандартной библиотекой Python отлично подой- дет сайт Python Module of the Week . Откройте сайт http://pymotw .com/ и просмотрите оглав- ление . Найдите модуль, который покажется вам интересным, и прочитайте про него или изучите документацию по модулям collections и random . 184 Глава 9 • Классы Оформление классов В стилевом оформлении классов есть несколько моментов, о которых стоит упо- мянуть отдельно, особенно с усложнением ваших программ. Имена классов должны записываться в «верблюжьей» схеме: первая буква каждого слова записывается в верхнем регистре, слова не разделяются пробелами. Имена экземпляров и модулей записываются в нижнем регистре с разделением слов сим- волами подчеркивания. Каждый класс должен иметь строку документации, следующую сразу же за опреде- лением класса. Строка документации должна содержать краткое описание того, что делает класс, и в ней должны соблюдаться те же соглашения по форматированию, которые вы использовали при написании строк документации в функциях. Каждый модуль также должен содержать строку документации с описанием возможных применений классов в модуле. Пустые строки могут использоваться для структурирования кода, но злоупотреб- лять ими не стоит. В классах можно разделять методы одной пустой строкой, а в модулях для разделения классов можно использовать две пустые строки. Если вам потребуется импортировать модуль из стандартной библиотеки и модуль из библиотеки, написанной вами, начните с команды import для модуля стандарт- ной библиотеки. Затем добавьте пустую строку и команду import для модуля, написанного вами. В программах с несколькими командами import выполнение этого соглашения поможет понять, откуда берутся разные модули, использованные в программе. Итоги В этой главе вы узнали, как написать собственные классы. Вы научились хра- нить информацию в классе с использованием атрибутов и наделять свои классы нужным поведением. Вы узнали, как написать методы __init__() для создания экземпляров ваших классов с нужными значениями атрибутов и как изменять атрибуты экземпляров напрямую и через методы. Также было показано, что наследование может упростить создание логически связанных классов и что эк- земпляры одного класса могут использоваться как атрибуты другого класса для упрощения кода классов. Вы узнали, что хранение классов в модулях и импортирование необходимых классов в файлы, где они будут использоваться, улучшает организацию про- ектов. Вы познакомились со стандартной библиотекой Python и рассмотрели пример, основанный на классе OrderedDict из модуля collections . Наконец, вы научились оформлять свои классы с использованием общепринятых соглашений Python. В главе 10 вы научитесь работать с файлами и сохранять результаты работы, вы- полненной в программе. Также будут рассмотрены исключения — экземпляры специального класса Python, предназначенного для передачи информации о воз- никающих ошибках. 10 Файлы и исключения Вы уже овладели основными навыками, необходимыми для создания хорошо структурированных и удобных в использовании программ; теперь пора подумать о том, как сделать ваши программы еще более удобными и полезными. В этой главе вы научитесь работать с файлами, чтобы ваши программы могли быстро анализи- ровать большие объемы данных. В этой главе вы научитесь обрабатывать ошибки, чтобы возникновение аномальных ситуаций не приводило к аварийному завершению ваших программ. Мы рассмо- трим исключения — специальные объекты, которые создаются для управления ошибками, возникающими во время выполнения программ Python. Также будет описан модуль json , позволяющий сохранять пользовательские данные, чтобы они не терялись при завершении работы программы. Работа с файлами и сохранение данных упрощают использование ваших программ. Пользователь сам выбирает, какие данные и когда нужно вводить. Он может за- пустить вашу программу, выполнить некоторую работу, потом закрыть программу и позднее продолжить работу с того момента, на котором он прервался. Умение об- рабатывать исключения поможет справиться с такими ситуациями, как отсутствие нужных файлов, а также с другими проблемами, приводящими к сбою программ. Обработка исключений повысит устойчивость ваших программ при работе с не- корректными данными — появившимися как из-за случайных ошибок, так и из-за злонамеренных попыток взлома ваших программ. Материал, представленный в этой главе, сделает ваши программы более практичными, удобными и надежными. Чтение из файла Гигантские объемы данных доступны в текстовых файлах. В них могут храниться погодные данные, социально-экономическая информация, литературные произ- ведения и многое другое. Чтение из файла особенно актуально для приложений, предназначенных для анализа данных, но оно также может пригодиться в любой ситуации, требующей анализа или изменения информации, хранящейся в фай- ле. Например, программа может читать содержимое текстового файла и пере- писывать его с форматированием, рассчитанным на отображение информации в браузере. Работа с информацией в текстовом файле начинается с чтения данных в память. Вы можете прочитать все содержимое файла или же читать данные по строкам. 186 Глава 10 • Файлы и исключения Чтение всего файла Для начала нам понадобится файл с несколькими строками текста. Пусть это будет файл с числом «пи» с точностью до 30 знаков, по 10 знаков на строку: pi_digits.txt 3.1415926535 8979323846 2643383279 Чтобы опробовать эти примеры, либо введите данные в редакторе и сохраните файл с именем pi_digits .txt , либо загрузите файл из ресурсов книги на странице https:// www.nostarch.com/pythoncrashcourse/. Сохраните файл в каталоге, в котором будут храниться программы этой главы. Следующая программа открывает этот файл, читает его и выводит содержимое на экран: file_reader.py with open('pi_digits.txt') as file_object: contents = file_object.read() print(contents) В первой строке этой программы многое заслуживает вашего внимания. Начнем с функции open() . Чтобы выполнить любые операции с файлом — даже просто вывести его содержимое, — сначала необходимо открыть файл. Функция open() получает один аргумент: имя открываемого файла. Python ищет файл с указанным именем в каталоге, в котором находится файл текущей программы. В данном при- мере выполняется программа file_reader .py , поэтому Python ищет файл pi_digits .txt в каталоге, в котором хранится file_reader .py . Функция open() возвращает объект, представляющий файл. В данном случае open('pi_digits.txt') возвращает объ- ект, представляющий файл pi_digits .txt . Python сохраняет этот объект в переменной file_object , с которой мы будем работать позднее в программе. Конструкция с ключевым словом with закрывает файл после того, как надобность в нем отпадет. Обратите внимание: в этой программе есть вызов open() , но нет вызова close() . Файлы можно открывать и закрывать явными вызовами open() и close() ; но если из-за ошибки в программе команда close() останется невыпол- ненной, то файл не будет закрыт. На первый взгляд это не страшно, но некоррект- ное закрытие файлов может привести к потере или порче данных. А если функция close() будет вызвана слишком рано, программа попытается работать с закрытым (то есть недоступным) файлом, что приведет к новым ошибкам. Не всегда можно заранее определить, когда нужно закрывать файл, но с приведенной конструкцией Python сделает это за вас. Вам остается лишь открыть файл и работать с ним так, как требуется, надеясь на то, что Python закроет его автоматически в правильный момент. После того как в программе появится объект, представляющий файл pi_digits .txt , во второй строке программы используется метод read() , который читает все содер- жимое файла и сохраняет его содержимое в одной длинной строке в переменной Чтение из файла 187 contents . При выводе значения contents на экране появляется все содержимое файла : 3.1415926535 8979323846 2643383279 Единственное различие между выводом и исходным файлом — лишняя пустая строка в конце вывода. Откуда она взялась? Метод read() возвращает ее при чте- нии, если достигнут конец файла. Если вы хотите удалить лишнюю пустую строку, включите вызов rstrip() в команду print : with open('pi_digits.txt') as file_object: contents = file_object.read() print(contents.rstrip()) Напомним, что метод rstrip() удаляет все пропуски в конце строки. Теперь вывод точно соответствует содержимому исходного файла: 3.1415926535 8979323846 2643383279 Пути к файлам Если передать функции open() простое имя файла, такое как pi_digits .txt , Python ищет файл в том каталоге, в котором находится файл, выполняемый в настоящий момент (то есть файл программы .py ). В некоторых случаях (в зависимости от того, как организованы ваши рабочие фай- лы) открываемый файл может и не находиться в одном каталоге с файлом програм- мы. Например, файл программы может находиться в каталоге python_work ; в ката- логе python_work создается другой каталог с именем text_files для текстовых файлов, с которыми работает программа. И хотя папка text_files находится в python_work , простая передача open() имени файла из text_files не подойдет, потому что Python проведет поиск файла в python_work и на этом остановится; поиск не будет продол- жен во вложенном каталоге text_files . Чтобы открыть файлы из каталога, отличного от того, в котором хранится файл программы, необходимо указать путь — то есть приказать Python искать файлы в конкретном месте файловой системы. Так как каталог text_files находится в python_work , для открытия файла из text_files можно воспользоваться относительным путем. Относительный путь приказы- вает Python искать файлы в каталоге, который задается относительно каталога, в котором находится текущий файл программы. В системе Linux и OS X это вы- глядит так: with open('text_files/имя_файла.txt') as file_object: Эта строка означает, что файл .txt следует искать в каталоге text_files ; она предпо- лагает, что каталог text_files находится в python_work (так оно и есть). В системах Windows в путях к файлам вместо слеша ( / ) используется обратный слеш ( \ ): with open('text_files\имя_файла.txt') as file_object: 188 Глава 10 • Файлы и исключения Также можно точно определить местонахождение файла в вашей системе неза- висимо от того, где хранится выполняемая программа. Такие пути называются абсолютными и используются в том случае, если относительный путь не работает. Например, если каталог text_files находится не в python_work , а в другом каталоге (скажем, в каталоге с именем other_files ), то передать open() путь 'text_files/ filename.txt' не получится, потому что Python будет искать указанный каталог только внутри python_work . Чтобы объяснить Python, где следует искать файл, не- обходимо записать полный путь. Абсолютные пути обычно длиннее относительных, поэтому их лучше сохранять в переменных, которые затем передаются open() . В Linux и OS X абсолютные пути выглядят так: file_path = '/home/ehmatthes/other_files/text_files/имя_файла.txt' with open(file_path) as file_object: В Windows они выглядят так: file_path = 'C:\Users\ehmatthes\other_files\text_files\имя_файла.txt' with open(file_path) as file_object: С абсолютными путями вы сможете читать файлы из любого каталога вашей си- стемы. Пока будет проще хранить файлы в одном каталоге с файлами программ или в каталогах, вложенных в каталог с файлами программ (таких как text_files из рассмотренного примера). ПРИМЕЧАНИЕ Иногда в системах семейства Windows слеш в пути к файлам интерпретируется правильно . Если вы используете Windows, но не получаете ожидаемых результатов, попробуйте использовать символы обратного слеша . Чтение по строкам В процессе чтения файла часто бывает нужно обработать каждую строку. Воз- можно, вы ищете некую информацию в файле или собираетесь каким-то образом изменить текст, например при чтении файла с метеорологическими данными вы обрабатываете каждую строку, у которой в описании погоды встречается слово «солнечно». Или, допустим, в новостях вы ищете каждую строку с тегом заголовка и заменяете ее специальными элементами форматирования. Для последовательной обработки каждой строки в файле можно воспользоваться циклом for : file_reader.py filename = 'pi_digits.txt' with open(filename) as file_object: for line in file_object: print(line) В точке имя файла, из которого читается информация, сохраняется в перемен- ной filename . Это стандартный прием при работе с файлами: так как переменная Чтение из файла 189 filename не представляет конкретный файл (это всего лишь строка, которая со- общает Python, где найти файл), вы сможете легко заменить 'pi_digits.txt' именем другого файла, с которым вы собираетесь работать. После вызова open() объект, представляющий файл и его содержимое, сохраняется в переменной file_object . Мы снова используем синтаксис with , чтобы поручить Python открывать и закрывать файл в нужный момент. Для просмотра содержимого все строки файла перебираются в цикле for по объекту файла . На этот раз пустых строк оказывается еще больше: 3.1415926535 8979323846 2643383279 Пустые строки появляются из-за того, что каждая строка в текстовом файле за- вершается невидимым символом новой строки. Команда print добавляет свой символ новой строки при каждом вызове, поэтому в результате каждая строка завершается двумя символами новой строки: один прочитан из файла, а другой добавлен командой print . Вызов rstrip() в команде print удаляет лишние пу- стые строки: filename = 'pi_digits.txt' with open(filename) as file_object: for line in file_object: print(line.rstrip()) Теперь вывод снова соответствует содержимому файла: 3.1415926535 8979323846 2643383279 Создание списка строк по содержимому файла При использовании with объект файла, возвращаемый вызовом open() , доступен только в пределах содержащего его блока with . Если вы хотите, чтобы содержимое файла оставалось доступным за пределами блока with , сохраните строки файла в списке внутри блока и в дальнейшем работайте с полученным списком. Одни части файла можно обработать немедленно и отложить другие для обработки в будущем. В следующем примере строки pi_digits .txt сохраняются в списке в блоке with , после чего выводятся за пределами этого блока: filename = 'pi_digits.txt' with open(filename) as file_object: lines = file_object.readlines() 190 Глава 10 • Файлы и исключения for line in lines: print(line.rstrip()) В точке метод readlines() последовательно читает каждую строку из файла и сохраняет ее в списке. Список сохраняется в переменной lines , с которой можно продолжить работу после завершения блока with . В точке в простом цикле for выводятся все элементы списка lines . Так как каждый элемент lines соответствует ровно одной строке файла, вывод точно соответствует его содержимому. Работа с содержимым файла После того как файл будет прочитан в память, вы сможете обрабатывать данные так, как считаете нужным. Для начала попробуем построить одну строку со всеми цифрами из файла без промежуточных пропусков: pi_string.py filename = 'pi_digits.txt' with open(filename) as file_object: lines = file_object.readlines() pi_string = '' for line in lines: pi_string += line.rstrip() print(pi_string) print(len(pi_string)) Сначала программа открывает файл и сохраняет каждую строку цифр в списке — точно так же, как это делалось в предыдущем примере. В точке создается пере- менная pi_string для хранения цифр числа «пи». Далее следует цикл, который добавляет к pi_string каждую серию цифр, из которой удаляется символ новой строки . В точке программа выводит строку и ее длину: 3.1415926535 8979323846 2643383279 36 Переменная pi_string содержит пропуски, которые присутствовали в начале каждой строки цифр. Чтобы удалить их, достаточно использовать strip() вместо rstrip() : filename = 'pi_30_digits.txt' with open(filename) as file_object: lines = file_object.readlines() pi_string = '' for line in lines: pi_string += line.strip() print(pi_string) print(len(pi_string)) Чтение из файла 191 В итоге мы получаем строку, содержащую значение «пи» с точностью до 30 знаков. Длина строки равна 32 символам, потому что в нее также включается начальная цифра 3 и точка: 3.141592653589793238462643383279 32 ПРИМЕЧАНИЕ Читая данные из текстового файла, Python интерпретирует весь текст в файле как строку . Если вы читаете из текстового файла число и хотите работать с ним в числовом контек- сте, преобразуйте его в целое число функцией int() или в вещественное число функцией float() . Большие файлы: миллион цифр До настоящего момента мы ограничивались анализом текстового файла, который состоял всего из трех строк, но код этих примеров будет работать и с намного большими файлами. Начиная с текстового файла, содержащего значение «пи» до 1 000 000 знаков (вместо 30), вы сможете создать одну строку, которая содержит все эти цифры. Изменять программу вообще не придется — достаточно передать ей другой файл. Также мы ограничимся выводом первых 50 цифр, чтобы не пришлось ждать, пока в терминале не прокрутится миллион знаков: pi_string.py filename = 'pi_million_digits.txt' with open(filename) as file_object: lines = file_object.readlines() pi_string = '' for line in lines: pi_string += line.strip() print(pi_string[:52] + "...") print(len(pi_string)) Из выходных данных видно, что строка действительно содержит значение «пи» с точностью до 1 000 000 знаков: 3.14159265358979323846264338327950288419716939937510... 1000002 Python не устанавливает никаких ограничений на длину данных, с которыми вы можете работать. Она ограничивается разве что объемом памяти вашей системы. |