0:04
Давайте поговорим об организации кода на Python.
В реальных проектах, конечно, никто код в один файлик не пишет.
Это очень быстро становится громоздким и неподдерживаемым.
Представьте проекты, где
тысячи или даже сотни тысяч строк кода.
Конечно, код надо разделять по смыслу, по назначению.
И в Python'е это разделение предоставляется
механизмом модулей и пакетов.
Что такое модуль в Python?
Модуль в Python мы с вами уже создавали,
когда экспериментировали с интерактивным интерпретатором.
Модуль в Python — это, по сути, файлик с расширением.py,
который содержит определения
переменных, функций, классов,
и который также может содержать импорты других модулей.
Давайте мы с вами начнем
знакомство с модулем и создадим наш новый модуль.
Перейдем в консоль,
создадим директорию playground, в которой мы будем работать.
Перейдем в нее.
Внутри директории playground давайте создадим модуль,
назовем его mymodule.
2:39
Мы видим на экране, что с режима переменной sys.path вывелось.
Это список директорий, в которых Python по умолчанию ищет модули.
Обратите внимание, что на первом месте
написана директория, в которой мы сейчас находимся.
Давайте убедимся в этом.
Утилита pwd показывает нашу текущую директорию.
То есть Python будет искать модули в этой директории в первую очередь,
поэтому ничто нам не мешает запустить
интерактивный интерпретатор Python
и попробовать заимпортировать наш модуль.
Сделаем это. import mymodule,
и видим, что у нас получилось.
Что важно отметить,
это то, что если мы попробуем сделать import mymodule еще раз,
то ничего на экран не выведется.
Это связано с тем, что Python импортирует модуль только один раз.
Он импортирует имя модуля в локальное пространство имен,
и в дальнейшем, если мы делаем точно такой же импорт,
импорта не происходит,
потому что Python видит, что мы уже ранее
этот модуль импортировали, импорт закеширован.
Когда происходит импорт, что вообще происходит?
Python импортирует модуль и выполняет все инструкции,
которые в этом модуле на верхнем уровне определены.
Собственно он наши инструкции, которые мы написали
в файлике mymodule.py и выполнил.
5:07
Обратите внимание на название этого файла.
Оно начинается с двух символов подчеркивания,
заканчивается ими и с расширением py.
Это специальный файл, который должен содержать пакет
для того, чтобы интерпретироваться Python'ом как пакет.
На самом деле начиная с Python'a 3.3 есть
так называемый mainspace packages,
который не требует наличия __init__.py файлика в них.
Но мы будем с вами рассматривать обычные regular packages,
которые вы обычно будете видеть на практике.
Что это за файлик __init__.py?
Это файл, который будет выполняться каждый раз,
когда мы импортируем наш пакет.
Давайте посмотрим на примере.
Откроем наш модуль, который мы писали,
mymodule.py и заменим импорты.
Теперь мы будем импортировать не модуль стандартной библиотеки,
а пакет, который мы только что создали.
7:26
Вот мы видим, что на экран
напечаталась строка, которую мы написали.
Это значит, что файлик __init__.py был выполнен при импорте.
Давайте посмотрим на директорию, которая у нас получилась.
Мы видим, что мы создали mymodule.py,
а также пакет,
который содержит файлик __init__.py.
Однако обратите внимание, что помимо тех директорий и файлов,
которые мы создавали сами,
Python автоматически создал директорию,
которая называется __pycache__ с двумя подчеркиваниями в начале и в конце,
а также файлик _init_.pyc.
Что это такое?
Директория __pycache__ и файлик с расширением.pyc
содержат скомпилированное представление нашего кода.
Виртуальная машина Python не выполняет напрямую код,
который мы пишем сами, она прежде всего его преобразовывает
в оптимизированное внутреннее представление,
которое называется байткодом.
Соответственно, директории __pycache__ и файлы с расширением.pyc
содержат как раз такое соптимизированное
представление нашего кода, то есть байткод.
Про то, что такое байткод
и зачем он нужен, мы с вами будем говорить в отдельном видео,
а сейчас просто не пугайтесь, когда вы увидите
вот такие автоматически созданные Python'ом файлы.
Давайте пойдем дальше и еще поговорим
об импортах и организации кода на Python'е.
Откроем наш модуль.
Очень часто на практике вы будете видеть вот такую конструкцию.
10:28
мы видим, что строка "hello" не напечаталась.
Это как раз благодаря той проверке на то, как вызывается наш модуль,
if __name__ == "_main__".
Мы можем таким образом контролировать,
какие кусочки кода в каких условиях у нас вызываются.
Далее.
Следующее, что мы посмотрим, это как
внутри пакета создавать свои отдельные модули,
как я уже сказал, пакет является объединением одного и более модулей,
и как оттуда импортировать код.
Синтаксис импортов в Python достаточно богат,
поэтому мы сейчас это осветим.
Давайте создадим внутри директории mypackage
новый модуль, который будет называться utils.py.
В этом модуле мы объявим функцию.
С функциями вы пока не знакомы, и у нас в следующих неделях
будут отдельные видео, посвященные им.
Однако давайте сейчас напишем самую простую функцию,
которая будет называться multiply,
и она будет перемножать
два значения, которые ей передали в качестве аргументов,
и возвращать результат этого умножения.
Функция в Python записывается с помощью ключевого слова def,
ну вы это еще увидите в дальнейшем.
Пока наша задача — посмотреть, как эту функцию можно заимпортировать,
находясь внутри mymodule, который мы с вами написали.
Давайте откроем mymodule.
Хотя давайте сначала посмотрим на структуру, которая у нас получилась.
Вот файлик utils.py, который мы только что создали,
он внутри пакета mypackage.
Как нам получить функцию multiply внутри mymodule?
На самом деле, все, что нам нужно сделать — это сделать
вот такой импорт, import mypackage.utils.
Теперь мы можем обращаться к функции multiply
вот таким вот образом - mypackage.utils.multiply.
Давайте умножим 2 и 3.
Сохраним и вызовем python3.
13:10
У нас получилось. Мы видим, что в результате
выполнения нашей программы, получилось число 6.
Однако это достаточно длинная запись.
В Python'е есть конструкция "from... import".
Что это значит?
Что мы можем переписать наш импорт вот таким образом,
используя from mypackage.utils
import, и дальше название нашей функции, которую мы
прописали в модуле utils.
Тогда в коде мы можем обращаться к этой функции
просто по ее имени,
потому что она при импорте была добавлена
в локальное пространство имен.
Опять же запустим -
то же самое.
Есть еще возможность.
Есть такой синтаксис, как import звездочка.
То есть он записывается вот так, "import *".
Это позволяет из модуля utils заимпортировать все объявления,
которые там содержатся.
В данном случае у нас там содержится только функция multiply.
Она будет заимпортирована, и мы можем ее использовать.
Запустим - то же самое.
Однако
такой импорт со звездочкой не рекомендуется
к использованию на практике, потому что он неявный.
И в большинстве случаев его используют при экспериментах
в интерактивном интерпретаторе, возможно при тестировании кода,
но не советуют использовать
при написании кода приложений
и при импортах из каких-то библиотек.
Последнее, что нам осталось посмотреть в работе модулей —
это то, как посмотреть, где, например, находится модуль,
который мы заимпортировали.
Давайте попробуем это сделать.
Под словами "где он находится" я имею в виду, где на диске.
В Python есть такой замечательный модуль, который называется this.
Давайте сделаем import this, и видим, что на экран вывелся
набор утверждений, которым должен следовать каждый Python-программист.
Давайте посмотрим на первые два.
Beautiful is better than ugly — красивое лучше, чем некрасивое.
Логично. Второе -
explicit is better than implicit — явное лучше неявного.
Это очень важный принцип.
Посмотрите на все эти утверждения. Они забавные, интересные
и в целом справедливые.
Однако напоминаю, что наша цель — посмотреть,
откуда же он был заимпортирован.
В Python существуют богатые средства интроспекции,
которые предоставляет модуль стандартной библиотеки inspect.
Мы его импортируем и дальше воспользуемся функцией getfile
из этого модуля, чтобы посмотреть, где находится модуль this.
Передаем название модуля this и видим путь на жестком диске,
на котором хранится наш модуль this.py.
На вашей операционной системе результат будет, скорее всего, другим.
Нас в данном случае интересует директория.
А какие же еще модули содержатся в этой директории, помимо this?
Давайте посмотрим.
Сделаем импорт из модуля os — это модуль стандартной библиотеки,
который позволяет работать с операционной системой.
И в модуле os есть функция listdir,
которая позволяет получить содержимое той или иной директории.
Мы передаем ей наш путь, который мы только что скопировали,
и получаем список файлов, которые находятся в этой директории.
Посмотрите на этот огромный список.
Это все модули стандартной библиотеки в Python, коих просто тонны.
Там есть модули на все случаи жизни.
И с какой-то частью из этих модулей мы вас познакомим
в рамках нашего курса в дальнейшем.
Однако может так получиться, что даже этой богатой функциональности,
которая есть в стандартной библиотеке Python,
вам может не хватить — у вас какая-то специфичная задача.
Не отчаивайтесь, Python — это язык с огромным сообществом,
и существует масса библиотек, написанных этим сообществом
на все случаи жизни, которые вы можете установить в свою систему.
Эти библиотеки находятся на ресурсе pypi.org,
и вы в любой момент можете зайти на этот ресурс, посмотреть,
какая библиотека вам нужна, и установить ее в вашу систему.
А установка пакета стороннего в систему производиться
с помощью утилиты pip, и мы с вами в следующем видео посмотрим,
как стороннюю библиотеку в вашу систему можно поставить.
В этом видео мы познакомились с организацией кода на Python,
посмотрели, что такое модули и что такое пакеты,
и как их организовывать, как импортировать код
из модулей и пакетов.
Также с некоторыми особенностями, которые с модулями и пакетами связаны.
Нас ждет в дальнейшем еще немало работы
с модулями стандартной библиотеки. Теперь вы умеете ими пользоваться.