В простейшем случае мы записываем коды в один файл Python (имя файла заканчивается на .py). Запускаем, все работает как положено, и мы довольны. Однако все может немного усложниться, когда вам придется разделить код на несколько файлов Python, обычно для упрощения управления кодом и читаемости. В этой статье я расскажу вам о некоторых типичных ошибках, на которые я попал, и надеюсь, что вы не сделаете тех же ошибок, что и я.
В Python каждый файл Python фактически имеет определенный термин под названием «Модуль», и когда вы используете знаменитый синтаксис import
, вы устанавливаете соединение между несколькими различными модулями Python для решения сложной задачи в вашем контексте. Здесь я собираюсь проиллюстрировать следующие темы:
- У каждого файла своя глобальная переменная
- Функция всегда запоминает, где она была создана
- Python - это «передача по ссылке»
- Использование отдельного файла для хранения ГЛОБАЛЬНОЙ переменной в нескольких файлах Python
Если вы хотите узнать о них побольше, продолжайте читать!
Каждый модуль / файл имеет свою собственную глобальную переменную
Когда вы создаете переменную (не внутри функции) в файле Python, вы подключаете эту переменную к пространству имен текущего модуля. Каждая команда в этом файле Python может получить доступ, прочитать и изменить значение переменной, то есть она становится глобальной переменной. Вы также можете явно сделать переменную, определенную в функциях глобально, объявив itglobal.
Однако глобальные переменные не используются в разных файлах Python. Чтобы проиллюстрировать это, давайте посмотрим на следующий пример:
Логика очень ясна, я определил функцию в sub_module.py
и пытаюсь вызвать ее в main.py
файле. Кажется, я определил переменную num=5
в файле main.py
, но оказалось, что функция не может получить к ней доступ, причина в том, что sub_module.py
не может получить доступ к глобальной переменной в других модулях Python, поэтому num=5
невидим для программы. Как это исправить? Просто определите num
в нужном файле.
Функция Python всегда запоминает место создания
Я не уверен, что вы когда-нибудь запутались в приведенном выше примере? Я так и сделал, когда впервые посмотрел на этот пример, потому что я явно импортировал test_func1
из sub_module.py
в main.py
, естественно думать, что функция уже была в текущей области, не так ли?
Но функция Python всегда знает, где она была создана. Хотя кажется, что test_func1
находится в main.py
, он по-прежнему принадлежит sub_module.py
, когда запускается, потому что именно здесь он был создан. А теперь еще несколько полезных практических советов:
Не забудьте также импортировать необходимые пакеты в подмодуль!
В приведенном выше примере, поскольку мы забыли импортировать пакет NumPy в sub_module.py
, хотя мы импортировали его в main.py
, он по-прежнему недоступен для test_func1
. А теперь исправим:
Передача по ссылке против передачи по значению
Первый пример работает, но выглядит странно, не правда ли? Обычно мы просто определяем функцию и класс в подмодуле вместо того, чтобы помещать одну переменную num=5
. Обычный способ решить эту проблему - фактически добавить num
в качестве аргумента в test_func1
, а также передать num=5
функции при ее вызове в main.py
файле.
Теперь вопрос в том, как сделать так, чтобы sub_module.py
узнал, где находится num
? Это потому, что Python всегда передает по ссылке, а не по значению. Чтобы проиллюстрировать это, давайте посмотрим, что на самом деле происходит, когда вы вызываете функцию:
Когда вы вводите num=5
в main.py
, вы в основном создаете PyObject
с целочисленным типом, который находится в части физической памяти, и вы используете имя num
, чтобы указать на этот кусок физической памяти. Теперь, поскольку Python всегда передает по ссылке, вы можете подумать, что test_func1
будет знать, на что указывает имя num
. В результате он получит доступ к value
5, поскольку он буквально знает, где находится это значение.
Могу ли я иметь общую глобальную переменную для разных файлов?
Как мы уже говорили, глобальная переменная уникальна для своего собственного модуля. Но иногда нам действительно нужно иметь ГЛОБАЛЬНУЮ переменную, к которой можно получить доступ и изменить каждый файл Python в каталоге. Канонический способ добиться этого - создать другой файл с вашими ГЛОБАЛЬНЫМИ переменными.
Я специально усложнил этот пример; здесь у нас есть gloabl_.py
файл Python, содержащий num=10
. Но в файле main.py
я также создал num=5
. Он может рассказать вам о различиях, даже если они оба были названы как num
, но они относятся к разным областям. В main.py
мы модифицируем эту ГЛОБАЛЬНУЮ переменную, добавляя 1, и это изменение также будет отражено в sub_module.py
. Здесь я должен импортировать global_
в test_func2
функцию, потому что, если я помещу синтаксис импорта в начало, num
он будет импортирован до выполнения lineglobal_.num += 1
. Помните, что sub_module.py
было выполнено в строке from sub_module import *
, мы можем проверить это в следующем примере:
Как вы видели, теперь, несмотря на то, что глобальная переменная num
увеличилась на 1, это не было отражено в sub_module.py
, поскольку переменная, которую они импортировали, была получена до операции. При импорте Python автоматически сделает для вас копию, так что старый global_.num
и новый global_.num
будут жить в совершенно другой физической памяти.
Заключение
Вот несколько рекомендаций по работе с несколькими файлами Python:
- Передайте переменную в качестве аргумента, поскольку Python «передает по ссылке», что гарантирует, что ваш подмодуль может получить доступ к переданной вами переменной.
- Не забудьте также импортировать необходимый пакет в подмодуль, так как функция всегда запоминает, где он был создан.
- Использование отдельного файла для хранения переменной GLOBAL в модулях Python, но имейте в виду, что при импорте переменной GLOBAL будет сделана копия исходной, поэтому всегда проверяйте, ссылаетесь ли вы на правильную переменную в своей программе. .
Вот и все! Надеюсь, эта статья окажется для вас интересной и полезной, спасибо за внимание! Если вам понравилась эта статья, подпишитесь на меня в среднем, большое спасибо за вашу поддержку. Подключите меня к моему Twitter или LinkedIn, а также дайте мне знать, если у вас есть какие-либо вопросы или какие уроки вы хотели бы видеть в будущем!