Основы Python
Объяснение Python, если __name__ = ‘__main__’
Прежде чем мы углубимся в этот вопрос, давайте рассмотрим несколько примеров, чтобы понять, что делает Python, когда мы запускаем код. Когда скрипт Python выполняется, интерпретатор Python за кулисами устанавливает некоторые глобальные переменные среды, а затем выполняет весь код, который присутствует в файле. Это верно даже для модулей, которые импортируются в скрипт.
Одной из переменных среды, устанавливаемых интерпретатором Python при выполнении кода, является __name__. Все специальные переменные начинаются и заканчиваются двойным подчеркиванием и называются переменными Dunder или Magic.
Если кому-то интересно, почему их называют Дандер, это потому, что Дандер - это сокращение от Double Underscores :)
Когда мы выполняем скрипт, значение переменной __name__ устанавливается равным __main__. Для импортированных модулей значение переменной __name__ устанавливается равным названию модуля. Давайте посмотрим на это в действии.
# app.py def function1(): print(“Hello from Function 1”) print(f”File name : {__name__}”) function1() # Output Hello from Function 1 File name : __main__
Давайте создадим модуль и импортируем этот модуль в нашу основную программу и проверим значение __main__
# other.py def function2(): print("Hello from Function 2") print(f"File Name : {__name__}") # app.py from module import function2 def function1(): print("Hello from Function 1") print(f"File name : {__name__}") function1() function2() # Output Hello from Function 1 File name : __main__ Hello from Function 2 File Name : other
Как мы видим, для импортированного модуля значение переменной __name__ устанавливается равным имени модуля, а для основного скрипта — __main__. Пока никаких сюрпризов, все работает именно так, как мы и ожидали.
Теперь, что произойдет, если мы оставим вызов функции или любые другие операторы глобальной области видимости в модуле, который будет импортирован нашей основной программой?
# other.py def function2(): print("Hello from Function 2") print(f"File Name : {__name__}") function2() print("Even I am reachable") # app.py from module import function2 def function1(): print("Hello from Function 1") print(f"File name : {__name__}") function1() # Output Hello from Function 2 File Name : other Even I am reachable Hello from Function 1 File name : __main__
Мы видим, что даже если мы не вызывали импортированную функцию (function2) в нашей основной программе (app.py), функция все равно выполнялась. Вызывался даже оператор print() из модуля.
Если мы вспомним то, о чем говорилось в начале статьи, и внимательно посмотрим на вывод, мы поймем, что это произошло потому, что все содержимое этого импортированного модуля также выполнялось Python.
Возвращаясь к основному вопросу, что представляет собой конструкция __name__ == ‘__main__’, встречающаяся почти во всех сценариях Python. Проще говоря, это защитное заявление, и его основная цель — предотвратить возникновение описанной выше ситуации.
Давайте посмотрим, что мы можем использовать оператор guard и знания, которые мы собрали до сих пор, чтобы решить эту проблему.
# other.py def function2(): print("Hello from Function 2") print(f"File Name : {__name__}") if __name__ == "__main__": function2() print("I am not reachable") # app.py from module import function2 def function1(): print("Hello from Function 1") print(f"File name : {__name__}") if __name__ == '__main__': function1() # Output Hello from Function 1 File name : __main__
Как мы видим, весь код, стоящий за оператором защиты в нашем импортированном модуле, не выполняется, потому что значение __name__ не равно __main__ для импортированного модуля. Хотя в основном скрипте значение __name__ действительно равно __main__ и вызывается function1().
Таким образом, Python дает нам возможность запускать код как отдельные скрипты или как модуль, а также дает нам возможность предотвратить выполнение определенных частей кода. Мы также можем добавить оператор else к оператору guard для выполнения какой-либо другой операции при импорте модуля.
Лучше всего включать в наш код оператор guard, даже если мы не собираемся использовать его как модуль. Поэтому всегда включайте защитный код в свой код, особенно теперь, когда мы понимаем, как он работает.