这样做做什么,为什么应该包括:if语句?

if __name__ == "__main__":
    print("Hello, World!")

如果你试图结束一个问题 如果你想要结束一个问题 在那里有人应该应该 使用这个学说,而不是,是不是, 考虑关闭作为 重复的为什么Python在我进口时 运行我的模块? 我该如何阻止它?。而对于某些问题,如果有人只是没有调用任何函数,或者错误地期望指定函数main自动用作切入点,使用当我启动 Python 脚本时, 主函数为何不运行? 脚本从哪里开始运行 ?.


当前回答

创建以下两个文件 :

# a.py

import b
# b.py

print("__name__ equals " + __name__)

if __name__ == '__main__':
    print("if-statement was executed")

现在每个文件都单独运行 。


运行中python a.py:

$ python a.py
__name__ equals b

何时a.py执行时,它导入模块b。这导致所有代码都在里面b要运行。 Python 设置globals()['__name__']和在b模块的模块到模块名称,b.


运行中python b.py:

$ python b.py
__name__ equals __main__
if-statement was executed

仅在文件b.py已执行, Python 设置globals()['__name__']在此文件中的文件中"__main__"因此,if用于True这一次。

其他回答

这是 Java 程序员学习 Python 的答案。 每个 Java 文件通常包含一个公共课。 您可以以两种方式使用该课 :

  1. 从其他文件中给班级打个电话。 您只需在调用程序里导入它 。

  2. 单独运行班级 测试目的。

就后一种情况而言,该类应包含一种公共静态真空主主()方法。'__main__'.

我们看看__name__ == '__main__':经常

它检查一个模块是否正在导入 。

换言之,在if只有在代码直接运行时才执行此块。这里directly中指not imported.

让我们看看它用一个简单的代码 来打印模块的名称做什么:

# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

如果我们直接通过python test.py,模块名称是__main__:

call test()
test module name=__main__

简而言之,你需要知道几点:

  1. import a动作实际上运行所有可以运行的a.py,意指每一行a.py

  2. 因为第1点,你可能不希望一切 运行在a.py进口时

  3. 要解决第2点的问题, Python 允许您使用条件检查

  4. __name__全部为隐含变量.py模块 :

  • 何时a.pyimported, 数值__name__联 联 年 月 日 月 日 月 月 日 月 月 日 月 月 月 日 月 月 日 月 月 日 月 月 月 日 月 月 日 月 月 月 日 月 的 月 月 月 日 月 月 日 月 的 月 月 月 月 日 月 月 月a.py模块设置为文件名 "a"
  • 何时a.py直接使用“python a.py" , " 价值__name__设置为字符串__main__
  1. 基于 Python 如何设置变量的机制__name__每个模块的每个模块, 您知道如何达到第3点吗 ? 答案相当简单, 对吧? 使用如果条件 :if __name__ == "__main__": // do A
  • 时当时python a.py将运行此部件// do A
  • import a跳过此部分// do A
  1. 你甚至可以放__name__ == "a"取决于你的功能需要,但很少

Python在4点是特别的 重要的事!

我在这页的答案中读了这么多。我想说,如果你知道这件事的话,你肯定能理解那些答案, 否则,你还是很困惑。

短答

保护用户在无意时不意外地引用剧本的锅炉牌代码。 当剧本遗漏了警卫时, 这里有一些常见的问题:

  • 如果您在另一个脚本中导入了无保护脚本(例如 ) 。import my_script_without_a_name_eq_main_guard))),后一脚本将触发前一脚本运行导入时使用第二脚本命令行参数。这几乎总是一个错误。

  • 如果您在无警卫的脚本中有自定义类, 并将其保存为泡菜文件, 那么在另一部脚本中拆开它就会触发无警卫的脚本的输入, 与前一颗子弹中描述的相同问题 。

长答答

为了更好地了解为什么和如何看待这一问题,我们需要退一步,了解Python初始化脚本的方式,以及这如何与其模块输入机制相互作用。

Python 译员读到源文件时,

  • 它设置了几个特殊的变量,比如__name__,然后

  • 它执行文件中发现的所有代码。

让我们看看这是怎么回事 和它与你的问题有什么关系__name__我们总是在 Python 脚本中看到检查。

代码样本

让我们使用略微不同的代码样本来探索导入和脚本是如何工作的。 假设以下是在一个名为foo.py.

# Suppose this is foo.py.

print("before import")
import math

print("before function_a")
def function_a():
    print("Function A")

print("before function_b")
def function_b():
    print("Function B {}".format(math.sqrt(100)))

print("before __name__ guard")
if __name__ == '__main__':
    function_a()
    function_b()
print("after __name__ guard")

特殊变量

当 Python 口译员读取源文件时, 它首先定义了几个特殊变量。 在这种情况下, 我们关心的是__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文件( 加上搜索其它几个变量) 执行该模块之前, 它会指定名称"foo"从导入对帐单到__name__变量,即:

# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"

执行模块代码

设置特殊变量后, 口译员将执行模块中的所有代码, 一次执行一个语句。 您可能想要用代码样本在侧面打开另一个窗口, 以便您可以随此解释一起执行 。

总是

  1. 它印着弦"before import"(没有引文)。

  2. 里面装满了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")
  1. 它印着弦"before function_a".

  2. 它执行def键,创建函数对象,然后将该函数对象指定给一个被称作变量的变量function_a.

  3. 它印着弦"before function_b".

  4. 它执行第二个def键,创建另一个函数对象,然后将其指派到一个被调用的变量function_b.

  5. 它印着弦"before __name__ guard".

只有当您的模块是主程序时

  1. 如果您的模块是主程序, 它就会看到__name__确实设定"__main__"它调用两个功能, 打印字符串"Function A""Function B 10.0".

只有当您的模块被另一个模块导入时

  1. (取代如果您的模块不是主程序,而是被另一个程序导入,那么__name__"foo",而不是"__main__"它会跳过if语句。

总是

  1. 它会打印字符串"after __name__ guard"这两种情况都存在。

摘要摘要摘要

简而言之,这里是两个案例的印刷品:

# What gets printed if foo is the main program
before import
before function_a
before function_b
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 function_a
before function_b
before __name__ guard
after __name__ guard

为什么它这样工作?

你可能会自然而自然而自然地想知道为什么有人想要这个。.py可用于其他程序和/或模块作为模块的文件,也可以作为主要程序本身运行。例如:

  • 您的模块是一个库, 但是您想要有一个脚本模式, 它运行一些单元测试或演示 。

  • 您的模块仅作为主程序使用, 但它有一些单位测试, 以及导入的测试框架 。.py比如您的脚本文件, 并运行特殊测试功能。 您不希望它仅仅因为正在导入模块而尝试运行脚本 。

  • 您的模块大多用作主要程序, 但也为高级用户提供程序员友好的 API 。

除了这些例子之外, 在 Python 中运行脚本只是设置一些神奇变量, 并导入脚本, 这是优雅的。 “ 运行” 脚本是导入脚本模块的副作用 。

" 思想食品 " 组织

  • 问题:我能有多个__name__检查路障?回答:这样做很奇怪, 但语言不会阻止你。

  • 假设以下是foo2.py。如果你说,会发生什么呢?python foo2.py指挥线上?

# Suppose this is foo2.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters

def function_a():
    print("a1")
    from foo2 import function_b
    print("a2")
    function_b()
    print("a3")

def function_b():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    function_a()
    print("m2")
print("t2")
      
  • 现在,找出如果你删除__name__检查中foo3.py:
# Suppose this is foo3.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters

def function_a():
    print("a1")
    from foo3 import function_b
    print("a2")
    function_b()
    print("a3")

def function_b():
    print("b")

print("t1")
print("m1")
function_a()
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")

您可以查看特殊变量__name__使用此简单示例 :

创建创建文件1. py

if __name__ == "__main__":
    print("file1 is being run directly")
else:
    print("file1 is being imported")

创建 *file2。平平

import file1 as f1

print("__name__ from file1: {}".format(f1.__name__))
print("__name__ from file2: {}".format(__name__))

if __name__ == "__main__":
    print("file2 is being run directly")
else:
    print("file2 is being imported")

执行文件2. py

Output:

file1 is being imported
__name__ from file1: file1
__name__ from file2: __main__
file2 is being run directly