Каждый раз, когда интерпретатор Python читает исходный файл, он делает две вещи:
это устанавливает несколько специальных переменных как [1 111], и затем
это выполняет весь код, найденный в файле.
Позволяют нам видеть, как это работает и как это касается Вашего вопроса о __name__
проверки, которые мы всегда видим в сценариях Python.
Позволяет нам использовать немного отличающийся пример кода, чтобы исследовать, как работают импорт и сценарии. Предположим, что следующее находится в файле, названном foo.py
.
# Suppose this is foo.py.
print("before import")
import math
print("before functionA")
def functionA():
print("Function A")
print("before functionB")
def functionB():
print("Function B {}".format(math.sqrt(100)))
print("before __name__ guard")
if __name__ == '__main__':
functionA()
functionB()
print("after __name__ guard")
, Когда Python interpeter читает исходный файл, он сначала определяет несколько специальных переменных. В этом случае мы заботимся о __name__
переменная.
, Когда Ваш Модуль Является Основной Программой
при выполнении модуля (исходный файл) как основная программа, например,
python foo.py
интерпретатор присвоит трудно кодированную строку "__main__"
__name__
переменная, т.е.
# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__"
, Когда Модуль будет Импортирован Другим
, С другой стороны, предположите, что некоторый другой модуль является основной программой, и это импортирует модуль. Это означает, что существует оператор как это в основной программе, или в некотором другом модуле основной импорт программы:
# Suppose this is in some other main program.
import foo
В этом случае, интерпретатор посмотрит на имя файла Вашего модуля, foo.py
, снимет изоляцию эти .py
и присвоит ту строку Вашему модулю __name__
переменная, т.е.
# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"
После того, как специальные переменные будут настроены, интерпретатор выполняет весь код в модуле, один оператор за один раз. Можно хотеть открыть другое окно на стороне с примером кода, таким образом, можно следовать наряду с этим объяснением.
Всегда
Это печатает строку "before import"
(без кавычек).
Это загружает math
модуль и присваивает его переменной, названной math
. Это эквивалентно замене import math
со следующим (обратите внимание, что __import__
функция низкого уровня в Python, который берет строку и инициировал фактический импорт):
# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
Это печатает строку "before functionA"
.
Это выполняется def
блок, создавая функциональный объект, затем присваивая тот функциональный объект переменной, названной functionA
.
Это печатает строку "before functionB"
.
Это выполняет второе def
блок, создавая другой функциональный объект, затем присваивая его переменной, названной functionB
.
Это печатает строку "before __name__ guard"
.
Только, Когда Ваш Модуль Является Основной Программой
__name__
был действительно установлен на [1 133] и это вызывает эти две функции, печатая строки "Function A"
и "Function B 10.0"
. Только, Когда Ваш Модуль Импортируется Другим
__name__
будет "foo"
, не "__main__"
, и это пропустит тело if
оператор. Всегда
"after __name__ guard"
в обеих ситуациях. Сводка
, Таким образом, вот то, что было бы распечатано в этих двух случаях:
# What gets printed if foo is the main program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard
Вы могли бы естественно задаться вопросом, почему кто-либо захочет это. Ну, иногда Вы хотите записать .py
файл, который может и использоваться другими программами и/или модулями как модуль, и может также быть выполнен как сама основная программа. Примеры:
Ваш модуль является библиотекой, но Вы хотите иметь режим сценария, куда он выполняет некоторые модульные тесты или демонстрацию.
Ваш модуль используется только в качестве основной программы, но он имеет некоторые модульные тесты и работы среды тестирования путем импорта .py
файлы как сценарий и выполнения специальных тестовых функций. Вы не хотите, чтобы он попытался выполнить сценарий просто, потому что это импортирует модуль.
Ваш модуль главным образом используется в качестве основной программы, но он также предоставляет благоприятный для программиста API опытным пользователям.
Вне тех примеров, это изящно, что выполнение сценария в Python просто настраивает несколько волшебных переменных и импортирует сценарий. "Выполнение" сценария является побочным эффектом импорта модуля сценария.
Вопрос: у меня могут быть [приблизительно 1 143] блоки проверки? Ответ: странно сделать так, но язык не остановит Вас.
предположим следующее находится в [1 144]. Что происходит, если Вы говорите python foo2.py
относительно командной строки? Почему?
# Suppose this is foo2.py.
def functionA():
print("a1")
from foo2 import functionB
print("a2")
functionB()
print("a3")
def functionB():
print("b")
print("t1")
if __name__ == "__main__":
print("m1")
functionA()
print("m2")
print("t2")
__name__
регистрация foo3.py
: # Suppose this is foo3.py.
def functionA():
print("a1")
from foo3 import functionB
print("a2")
functionB()
print("a3")
def functionB():
print("b")
print("t1")
print("m1")
functionA()
print("m2")
print("t2")
# Suppose this is in foo4.py
__name__ = "__main__"
def bar():
print("bar")
print("before __name__ guard")
if __name__ == "__main__":
bar()
print("after __name__ guard")
Вот еще более быстрый подход:
// strpos is faster than an unnecessary substr() and is built just for that
if (strpos($str, $prefix) === 0) $str = substr($str, strlen($prefix));