Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Что такое import в Python?
В языке программирования Python подключение пакетов и модулей осуществляется с помощью import. Это позволяет распределять код по логическим "узлам" приложения(модели данных, обработчики, и тп.), что позволяет получить менее нагруженные кодом файлы.
Плюсы:
Повышается читаемость кода.
Код логически разбит по "узлам", его поиск и дальнейший отлов ошибок становится понятнее и проще.
Для разработки в команде это дает более четкое понимание, что и где делает каждый при выполнении "задания".
Минусы:
Нужно понимать, что делается и для чего.
Как использовать import?
Синтаксис import в Python достаточно прост и интуитивно понятен:
# В данной строке импортируется something_we_want
import something_we_want
# В данной строке импортируется something_we_want, как aww(логично и просто)
import something_we_want as aww
# В данной строке импортируется из something_we_want something(логично и просто)
from something_we_want import something
# В данной строке импортируется из something_we_want something, как s(логично и просто)
from something_we_want import something as s
# Синтаксис as позволяет обращаться к импортируемому по новому нами описанному
# далее имени(это работает только в рамках нашего файла)
Что можно импортировать?
Для более глубокого понимания import стоит рассмотреть пример, представленный ниже.
something_we_want.py:
def something():
pass
somedata = 5
main.py:
# 1 случай
import something_we_want
something_we_want.something()
import something_we_want
print(something_we_want.somedata)
# 2 случай
import something_we_want as aww
aww.something()
import something_we_want as aww
print(aww.somedata)
# 3 случай
from something_we_want import something
something()
from something_we_want import somedata
print(somedata)
# 4 случай
from something_we_want import something as s
s()
from something_we_want import somedata as sd
print(sd)
# Классы импортируются по аналогии с функциями
Красиво, читаемо и понятно.
В чем же подвох?
Но даже в таком простом примере есть подвох, о котором многие не догадываются(если вы начинающий программист, то лучше перейдите к следующему оглавлению).
Идеология Python достаточно интересна, что позволяет ему иметь низкий порог вхождения, низкое время написания кода, высокую читаемость, но именно в ней и кроется подвох.
По своему опыту использования данного языка, сложилось отчетливое ощущение главной идеи ООП(все есть объект). Что же в этом плохого?
Все файлы, функции и тд. это объект. Но что это за объект и что за класс за ним стоит?
Все просто, это любимый всеми программистами класс, использующий паттерн проектирования Singleton.
Поэтому при достаточно ветвистой структуре, импорт переменной и дальнейшая ее модификация может порождать достаточно не простые в понимании баги(переменная в своем цикле жизни может иметь любое значение и никаких гарантий нет).
Ветвистая структура приложения и существующие подходы импортирования
Часто в разработке приложений программисты пытаются разбить программу по логическим "узлам". Данный подход повышает читаемость и позволяет вести разработку в команде(один человек занимается реализацией одного "узла", второй другого). Так порождается структура приложения, которая зачастую виду сложности функционала является достаточно обширной(ветвистой, потому что имея одну точку входа откуда уже обрастая функционалом это становится похожим на дерево).
Пример ветвистой структуры:
main.py
app(директория)
models(директория)
User.py
...
handlers(директория)
auth.py
...
...
...
...
Существует 2 подхода импортирования(лучше выбрать один и придерживаться его весь проект):
Именованный
Неименованный
Пример именованного импорта из models.py в auth.py:
# auth.py
from app.models import User
Пример неименованного импорта из models.py в auth.py:
# auth.py
from ..models import User
# Количество точек указывает на сколько (обьектов) мы поднимаемся от исходного.
# В данном примере первая точка поднимает нас на уровень обьекта handlers,
# А вторая точка поднимает нас на уровень обьекта app
Это два абсолютно разных подхода. В первом случае мы "идем" из "корня"(входной точки нашего приложения). Во втором случае мы "идем" от "листа"(нашего файла).
Плюсы и минусы подходов импорта:
Именованный | Неименованный | |
Плюсы | Видна структура импорта и приложения. Высокая читаемость. | Видна часть структуры импорта. Программисту не нужно знать полную структуру приложения. |
Импорт не зависит от точки входа. Код становится не привязанным к приложению. Что по сути позволяет исполнить код из любой точки(тесты, отдельно и тд.). Повышается отлаживаемость. Появляется возможность разработки отдельных узлов приложения без полного вовлечения программиста в проект. | ||
Минусы | Импорт зависит от точки входа. Программисту необходимо знать структуру приложения. Код сильно связан с приложением. Что по сути усложняет отладку, тестирование, и тд. Программист становится сильно вовлеченным в проект. | Снижается читаемость импорта. |
Хоть первый подход и имеет существенные минусы в использовании, но тем не менее он популярен. Программистам он привычнее, хоть и имеет недостатки. А начинающие часто не задумываются об альтернативах.
P.S.
Данная статья была написана для начинающих программистов, которые хотят научиться писать на языке программирования Python, поэтому часть примеров заведомо упрощена и нацелена на освещение существующих подходов.
Пишите тот код, который бы сами хотели получить от исполнителя.