Всё, что вы писали до сих пор, помещалось в один файл — это удобно, пока программа маленькая. Но представьте программу для интернет-магазина: код для денег, код для дат доставки, код для статистики по продажам. Если тащить всё в один файл, он превратится в свалку из тысяч строк. А часть этой работы — округление денег, подсчёт среднего — уже давно написана и проверена другими программистами. Модули решают обе проблемы разом: позволяют разложить свой код по отдельным файлам и подключать чужой готовый код, не переписывая его заново.
Что такое модуль
Представьте ящик с инструментами. Молоток, отвёртка, рулетка — каждый лежит в своей ячейке, и вы берёте только то, что нужно для текущей задачи, а не вываливаете весь ящик на стол. Программисты по всему миру уже написали огромное количество готовых "инструментов" на Python: функции для математики, для работы с датами, для генерации случайных чисел. Все они разложены по отдельным файлам, и вы можете взять из такого файла только то, что нужно вам прямо сейчас.
Официальный термин для такого файла-инструмента — модуль. Модуль — это обычный файл с расширением .py, в котором лежат функции, переменные или другой код. Когда вы подключаете модуль к своей программе, все функции и переменные из него становятся вам доступны. Python поставляется с большим набором готовых модулей — их называют стандартной библиотекой, о ней поговорим чуть дальше. Кроме них, вы сами можете написать модуль и подключить его в другом своём файле.
import: подключаем модуль целиком
Чтобы взять инструмент из чужого ящика, нужно сначала этот ящик открыть. В Python для этого есть отдельная команда: вы называете модуль, который хотите использовать, и Python делает всё его содержимое доступным в вашей программе — но не напрямую по именам, а через имя самого модуля, как через подписанную полку.
Эта команда называется import (в переводе — "ввезти", "подключить"). После import указывается имя модуля, а обратиться к чему-то внутри него можно через точку: имя_модуля.имя_функции. Такая запись через точку называется точечной нотацией, и вы уже встречали её раньше, когда вызывали методы строк вроде text.upper() — принцип тот же самый.
import math
print(math.sqrt(25))
print(math.pi)
Разберём построчно:
import math— подключаем модульmathиз стандартной библиотеки. Он хранит математические функции и константы: корень, степень, число пи и другие. Строка ничего не выводит, она только делает модуль доступным дальше по коду.print(math.sqrt(25))— обращаемся к функцииsqrt(квадратный корень) внутри модуляmathчерез точку и вызываем её со значением25. Выведется5.0.print(math.pi)—piздесь не функция, а переменная-константа внутри модуляmath: число π. Скобок нет, потому что мы не вызываем функцию, а просто читаем значение. Выведется3.141592653589793.
Почему через точку, а не просто sqrt(25)? Так Python сразу понимает, откуda взялась функция, и разные модули не путают друг друга: если бы в двух разных ящиках лежали инструменты с одинаковым названием, точка с именем модуля показывает, из какого именно ящика вы его достали.
from ... import: берём только нужное
Иногда из целого ящика вам нужна одна-единственная отвёртка, и таскать за собой весь ящик неудобно — хочется положить её прямо в карман, чтобы обращаться к ней по имени напрямую.
Для этого существует форма from ... import ...: вы называете модуль после from, а после import перечисляете через запятую конкретные имена, которые хотите достать. После такого импорта эти имена становятся доступны напрямую, без имени модуля и без точки.
from math import sqrt, pi
print(sqrt(25))
print(pi)
Разберём построчно:
from math import sqrt, pi— из модуляmathдостаём только функциюsqrtи константуpi, перечислив их через запятую. Остальное содержимое модуляmathпри этом не подключается вовсе.print(sqrt(25))— теперьsqrtиспользуется безmath.впереди, потому что мы забрали именно эту функцию себе "в карман". Выведется5.0, как и раньше.print(pi)— то же самое с константой: обращаемся к ней напрямую по имени. Выведется3.141592653589793.
Ловушка формы from ... import: если вы заберёте из разных модулей две функции с одинаковым именем, вторая незаметно перекроет первую — Python не предупредит об этом. У обычного import модуль такой проблемы нет, потому что имя модуля перед точкой всегда показывает источник. Поэтому from ... import удобен для одной-двух хорошо знакомых вещей, а для модуля целиком чаще используют обычный import.
as: даём модулю удобное имя
Названия некоторых модулей длинные, а использовать их в коде приходится часто — писать длинное имя перед точкой каждый раз утомительно. Это как подписать длинное официальное название фирмы-производителя коротким словом, которое удобно именно вам.
Для этого в Python есть ключевое слово as ("как"): оно ставится после имени модуля и задаёт для него короткий псевдоним — новое имя, под которым модуль будет доступен дальше по коду. Так же можно переименовать и отдельную функцию при импорте через from ... import ... as ....
import statistics as stats
numbers = [4, 8, 15, 16, 23]
print(stats.mean(numbers))
Разберём построчно:
import statistics as stats— подключаем модульstatistics(статистика), но даём ему короткий псевдонимstats. Дальше по коду обращаться к модулю нужно именно черезstats, а не через полное имяstatistics.numbers = [4, 8, 15, 16, 23]— обычный список чисел, с которым мы уже умеем работать.print(stats.mean(numbers))— вызываем функциюmean(среднее арифметическое) из модуляstatistics, но обращаемся к нему через псевдонимstats. Выведется13.2— среднее значение пяти чисел.
Псевдоним — это обычное переименование: после строки с as stats имени statistics для программы как будто больше не существует, есть только stats.
Стандартная библиотека Python
Когда вы устанавливаете Python, вместе с ним сразу попадает большой набор готовых модулей — их не нужно отдельно скачивать, они всегда под рукой. Это как купить ящик с инструментами, в котором уже лежит стартовый набор для базовых задач.
Такой набор официально называется стандартной библиотекой (standard library). В ней сотни модулей на любой случай: от математики до работы с файлами. Полезно заранее знать, какие инструменты вообще есть в этом ящике.
math | математические функции и константы: корень, степень, синус, число π |
statistics | среднее, медиана и другие статистические расчёты по числам |
random | случайные числа и случайный выбор из списка — отдельный урок впереди |
datetime | работа с датами и временем — тоже разберём отдельно |
os, sys | взаимодействие с операционной системой и настройками самого Python |
Кроме стандартной библиотеки существуют модули, которые пишут другие программисты и выкладывают в открытый доступ отдельно от Python — их называют сторонними библиотеками, их нужно ставить дополнительно. Как это делать, вы узнаете в отдельном уроке. А сегодняшний урок — про то, как вообще устроено подключение любого модуля.
Создаём свой модуль
Модулем может быть не только чужой готовый файл — точно так же модулем становится любой ваш собственный файл с расширением .py, если вы подключите его из другого файла. Никакой специальной команды не нужно: как только вы пишете функции в отдельном файле, он уже готов к тому, чтобы его импортировали.
Представим, что в одной папке лежат два файла: helpers.py с полезными функциями и main.py, где эти функции используются.
# файл helpers.py
def square(n):
return n * n
def is_even(n):
return n % 2 == 0
# файл main.py
import helpers
print(helpers.square(5))
print(helpers.is_even(5))
Разберём построчно:
helpers.py— обычный файл с двумя функциями, ничем не отличается от любого файла, который вы писали раньше. Название файла без расширения.pyи станет именем модуля.import helpersв файлеmain.py— подключаем файлhelpers.pyтак же, как подключали быmath. Python ищет файлhelpers.pyв той же папке, что иmain.py.print(helpers.square(5))— вызываем функциюsquareиз модуляhelpersчерез точку, ровно так же, какmath.sqrt(...). Выведется25.print(helpers.is_even(5))— вызываем вторую функцию. ВыведетсяFalse, потому что5нечётное.
Именно поэтому крупные программы почти никогда не пишут в одном файле: функции для денег кладут в один модуль, функции для текста — в другой. Программу становится гораздо легче читать и поддерживать, когда каждый файл отвечает за что-то одно.
if __name__ == "__main__": запуск или импорт?
Когда вы импортируете модуль, Python не просто "заглядывает" в файл за нужной функцией — он выполняет этот файл целиком, сверху вниз, один раз. Обычно это не проблема: функции просто объявляются и ничего не печатают. Но что если в файле helpers.py для проверки была строка print(square(5))? Тогда при каждом импорте этого модуля у вас неожиданно печаталось бы число 25 — хотя вы всего лишь хотели воспользоваться функцией.
Чтобы этого избежать, Python даёт каждому файлу встроенную переменную __name__. Если файл запущен напрямую (python main.py), в этой переменной автоматически оказывается строка "__main__". А если тот же файл подключён через import из другого файла, в __name__ будет храниться имя самого модуля. Проверяя условием if __name__ == "__main__":, вы отделяете код для прямого запуска от того, что должно работать и при импорте.
# файл helpers.py
def square(n):
return n * n
if __name__ == "__main__":
print(square(5))
Разберём построчно:
def square(n): return n * n— функция объявляется как обычно, она выполнится в любом случае: и при прямом запуске, и при импорте.if __name__ == "__main__":— проверяем, запущен ли этот файл напрямую. Если да — переменная__name__равна строке"__main__", и условие истинно.print(square(5))внутриif— эта строка выполнится, только если файлhelpers.pyзапустили напрямую командойpython helpers.py. Если же кто-то напишетimport helpersв другом файле, эта строка выполнена не будет, и никакого лишнего вывода не появится — станет доступна только сама функцияsquare.
Совет: прячьте тестовые вызовы и вывод результатов внутрь if __name__ == "__main__":, если файл когда-нибудь может понадобиться как модуль. Для совсем маленьких учебных программ это не обязательно, но станет привычкой, когда вы начнёте писать программы из нескольких файлов.
Частые ошибки
Обращение к функции без имени модуля после import
import math, а затем вызов sqrt(25) без math. впереди — вызовет NameError: name 'sqrt' is not defined. После обычного import нужно всегда обращаться через точку: math.sqrt(25).
Опечатка в имени модуля или функции
import mathh вызовет ModuleNotFoundError: No module named 'mathh', а math.squareroot(25) вызовет AttributeError, потому что такой функции в модуле нет — правильное имя sqrt.
Использование псевдонима без as, а по памяти
После import statistics as stats имя statistics для кода больше не существует — обращение к statistics.mean(...) вызовет NameError. Работать нужно только через stats.
Своё имя файла совпадает с именем стандартного модуля
Если назвать свой файл math.py и лежит он в той же папке, Python при import math найдёт именно ваш файл, а не встроенный модуль — и настоящий math.sqrt станет недоступен. Не называйте свои файлы именами модулей стандартной библиотеки.
Что важно запомнить
- Модуль — это файл
.pyс функциями, переменными или другим кодом, который можно подключить к своей программе. import имя_модуляподключает модуль целиком, обращаться к его содержимому нужно через точку:имя_модуля.имя_функции.from имя_модуля import имя1, имя2достаёт конкретные имена и делает их доступными напрямую, без точки, но может незаметно перекрыть одинаковые имена из разных модулей.asзадаёт короткий псевдоним модулю или имени: после него обращаться нужно только по новому имени.- Стандартная библиотека — набор готовых модулей, которые устанавливаются вместе с Python и не требуют отдельной загрузки.
- Любой ваш файл
.pyсам становится модулем, как только его подключают черезimportиз другого файла. __name__равен"__main__"только при прямом запуске файла — условиеif __name__ == "__main__":отделяет код для прямого запуска от кода, который должен работать и при импорте.
Проверьте себя
7 вопросов
Среднее и корень
В переменной numbers дан список чисел. Используя модули math и statistics из стандартной библиотеки, вычислите:
rounded_mean— среднее арифметическое чисел списка (функцияmeanмодуляstatistics), округлённое до целого встроенной функциейround;root— квадратный корень из максимального числа списка (функцияsqrtмодуляmath, максимум ищите встроенной функциейmax).
Например, для numbers = [4, 9, 16] среднее равно 9.666..., округлённое — 10, а корень из максимума (16) — 4.0.