Написание сложной программы с нуля, в котором весь код содержится в одном огромном файле, может быть невероятно долгим и трудозатратным. Гораздо эффективнее не только разбить программу на отдельные файлы (и папки), но и использовать уже готовые части кода – те, что вы ранее написали сами или те, что были разработаны и протестированы другими специалистами.
Файл с расширением .py называется модулем, а имя этого файла является именем модуля. При этом все переменные, функции и классы из одного модуля можно свободно использовать в других модулях. Если код в файле предназначен для непосредственного запуска, а не для повторного использования, то такой файл часто называют скриптом.
Набор связанных модулей, которые совместно обеспечивают определённую функциональность, называется пакетом. Он представляет собой папку, которая содержит несколько файлов с расширением .py и часто содержит специальный служебный файл __init__.py, обозначающий, что эта папка является пакетом.
Библиотека является более общим понятием, так как в программировании под ней понимают набор готового кода, который можно повторно использовать в своём проекте. Библиотека в Python может быть представлена как одним модулем, так и пакетом, который, в том числе, может содержать другие пакеты.
Списки и кортежи подходят для хранения последовательности элементов, но что, если нам удобнее обращаться к элементам по какому-то имени, а не по порядковому номеру? Для этого в Python предназначены словари. Вместо того чтобы хранить элементы по порядку, словари хранят пары «ключ-значение». Они похожи на настоящие словари, где у каждого слова (ключа) есть свое определение (значение).
Ключи словаря должны быть уникальными и представлены неизменяемым типом данных, например, числом, строкой, кортежем или даже замороженным множеством. На значения словаря никакие ограничения не накладываются.
В самом простом случае словарь создаётся с помощью фигурных скобок, внутри которых через запятую перечисляются пары ключ: значение:
phone_book = {
"Мастер": "+79315555555",
"Маргарита": "+79637777777"
}
Инкапсуляция – это один из трёх основных ООП. И как мы уже говорили, её главной идеей является сокрытие внутренней реализации объекта от внешнего мира и предоставление контролируемого доступа к его данным.
Вспомним пример с автомобилем из предыдущего параграфа. Инкапсуляция позволяет контролировать, как и когда данные объекта могут быть изменены. Так, вызов метода продажи sell() не только изменяет статус наличия автомобиля в автосалоне, но и выполняет другие необходимые действия, например, выводит сообщение о продаже. Прямое изменение атрибута не обеспечит совершение этих действий.
В отличие от некоторых других языков программирования, в Python нет строгих механизмов для полного запрета доступа к атрибутам и методам. Вместо этого используется соглашение об именовании, которое говорит разработчикам, как следует обращаться к этим данным.
Ветвление – это фундаментальный механизм в программировании, позволяющий выполнять различные действия в зависимости от условия. Это похоже на принятие решений в реальной жизни: «Если я наберу 100 очков, то перейду на следующий уровень. Иначе мне придётся сыграть ещё раз».
В Python ветвление реализуется с помощью условных операторов if (с англ. – если), elif (от англ. else if – иначе если) и else (с англ. – иначе):
if условие_1:
блок_кода_1
elif условие_2:
блок_кода_2
else:
блок_кода_3
Каждое условие – это логическое выражение, результат которого может быть либо истинным (True), либо ложным (False). Если первое условие в if истинно, то выполняется соответствующий блок кода, иначе – проверяется следующее условие в elif и так далее. Если все условия оказались ложными, то выполняется блок кода else.
Принадлежность кода к блоку if, elif или else определяется обязательным отступом (обычно 4 пробела). Отсутствие или неправильный отступ приведет к ошибке IndentationError.
Ошибки в программировании неизбежны, однако важно научиться распознавать и грамотно реагировать на них. При одних ошибках код вовсе не запустится, а при других аварийно завершится при выполнении строки с ошибкой. Однако Python – очень дружелюбный язык, и всегда старается подсказать, в чем проблема.
Самый частый гость у начинающих программистов – это синтаксические ошибки, например, опечатки или пропущенные символы. Python в этом плане очень строгий и требует, чтобы код был написан по определенным правилам. Если вы допустите такую ошибку, Python даже не запустит вашу программу, а сразу сообщит, что именно ему не понравилось.
Например, выведем сообщение на экран, но пропустим закрывающую скобку при вызове функции print():
print("Эта инструкция написана не очень правильно"
Запустив этот код, вы увидите примерно такое сообщение о синтаксической ошибке:
Traceback (most recent call last):
File "/home/irina/projects/task.py", line 2
print("Эта инструкция написана не очень правильно"
^
SyntaxError: '(' was never closed
Возможности перегрузки операторов в Python не ограничиваются базовыми арифметическими операциями и сравнением объектов, так как существуют методы, позволяющие создать свою собственную коллекцию, то есть класс, представляющий собой контейнер элементов, как список или словарь. Объекты такого класса могут быть перебраны в цикле for, использовать оператор in и функцию len(), а также синтаксис обращения по индексу или ключу через квадратные скобки.
Методы __iter__() и __next__() лежат в основе механизма итерации в Python и позволяют перебирать объекты в цикле for или использовать их в других функциях, которые принимают итерируемый объект, например, sum() или zip(). Также эти методы можно явно вызывать с помощью функций iter() и next(), как мы уже делали для встроенных типов данных, когда рассматривали работу итерируемых объектов.
Метод __iter__() превращает объект в итератор. В простейшем случае, сам итерируемый объект часто выступает в роли своего итератора, поэтому __iter__() просто возвращает self.
Строки в Python представлены типом str (от англ. string – строка) и представляют собой упорядоченные последовательности символов, заключённые в кавычки. Строки используются для хранения и обработки текстовой информации. Будь то имена, адреса, тексты книг или любые другие данные, которые можно представить в виде текста, в Python они обычно обрабатываются как строки.
Для создания строковой переменной достаточно заключить любой текст в одинарные (') или в двойные (") кавычки:
message = 'Что на ужин?'
reply_message = "" # Пустая строка – тоже строка
Строки, списки и кортежи являются упорядоченными коллекциями, то есть их элементы имеют фиксированный порядок и свои собственные порядковые номера, называемые индексами. С их помощью можно как получать отдельные элементы коллекции, так и извлекать целые последовательности элементов.
По индексу можно получить отдельные элементы строк, списков и кортежей. Например, у нас есть следующие переменные:
message_str = "Как дела?" # Строка
shopping_list = ["Еда 1", "Еда 2", "Еда 3", "Еда 4", "Еда 5"] # Список
friends_tuple = ("Друг 1", "Друг 2", "Друг 3") # Кортеж
Первый символ "К" строки "Как дела?" находится по индексу 0, второй символ "а" – по индексу 1, и так далее.
Несмотря на то, что коллекции в Python имеют свои уникальные особенности, они обладают некоторыми общими способами работы с ними. Так мы можем получить количество элементов любой коллекции и проверить принадлежность элемента ей, а также определить максимальное и минимальное значение или посчитать сумму коллекции чисел.
Мы уже встречались с функцией len(), когда говорили о переборе элементов упорядоченных коллекций по индексу. Но она позволяет узнать, сколько элементов содержится в любой встроенной коллекции Python.
Например, определим количество элементов в множестве:
weapons = ("Меч", "Лук", "Копье")
print(len(weapons))
# Вывод: 3
Программируя на Python, мы уже сталкивались как с функциями, так и с методами. Функции не привязаны к объектам и вызываются независимо от них. Например, функция id() возвращает уникальный идентификатор объекта, а функция print() выводит данные на экран.
Однако методы, напротив, принадлежат определённым типам данным (классам) и используются только совместно с объектом, к которому относятся. Например, уже рассмотренный метод dict.values() возвращает последовательность значений словаря dict.
Строки имеют большое количество методов, позволяющих совершать разные действия над ними, например, привести все символы строки к верхнему регистру или обрезать пробелы в начале и конце строки.
Но строки являются неизменяемым типом данных, поэтому методы, преобразующие строку, на самом деле не изменяют её, а возвращают изменённую копию исходной строки, которую следует сразу использовать в работе или присвоить какой-либо переменной.