if
语句?if __name__ == "__main__":
print("Hello, World!")
如果您要关闭一个问题,而有人应该使用这个习惯用语却没有使用,请考虑将其作为为什么在导入时Python运行我的模块,我该如何停止?的重复项进行关闭。对于那些只是没有调用任何函数或错误地期望使用名为main
的函数作为自动入口点的问题,请使用当我启动Python脚本时,为什么不运行main()函数?脚本从哪里开始运行?。
if
语句?if __name__ == "__main__":
print("Hello, World!")
如果您要关闭一个问题,而有人应该使用这个习惯用语却没有使用,请考虑将其作为为什么在导入时Python运行我的模块,我该如何停止?的重复项进行关闭。对于那些只是没有调用任何函数或错误地期望使用名为main
的函数作为自动入口点的问题,请使用当我启动Python脚本时,为什么不运行main()函数?脚本从哪里开始运行?。
让我们以更为抽象的方式来看待答案:
假设我们在 x.py
文件中有以下代码:
...
<Block A>
if __name__ == '__main__':
<Block B>
...
当我们运行 x.py
时,将运行块 A 和 B。
但是当我们运行另一个模块(例如 y.py
),在该模块中导入了 x.py
并从那里运行代码时(例如从 y.py
中调用 x.py
中的函数),只有块 A 被运行,而不运行块 B。
Python 最擅长的是第四点!其他只是基本逻辑。
我已经在这个页面上读了很多答案。如果你知道这件事,那么你肯定会理解这些答案,否则你仍然会感到困惑。
if __name__ == '__main__':
# Do something appropriate here, like calling a
# main() function defined elsewhere in this module.
main()
else:
# Do nothing. This module has been imported by another
# module that wants to make use of the functions,
# classes and other useful bits it has defined.
考虑:
if __name__ == "__main__":
main()
它检查 Python 脚本的 __name__
属性是否为 "__main__"
。换句话说,如果程序本身被执行,则该属性将是 __main__
,因此程序将被执行(在这种情况下是 main()
函数)。
然而,如果你的 Python 脚本被一个模块使用,那么 if
语句之外的任何代码都会被执行。所以 if __name__ == "__main__"
只是用来检查程序是否作为一个模块使用,并决定是否运行代码。
在解释 if __name__ == '__main__'
的任何内容之前,了解什么是 __name__
以及它的作用非常重要。
__name__
是什么?__name__
是一个DunderAlias——可视为全局变量(可以从模块访问),并且与 global
的工作方式相似。
它是一个字符串(如上所述的全局变量),由 type(__name__)
表示(得到 <class 'str'>
),并且是内置标准,适用于Python 3 和 Python 2 版本。
它不仅可用于脚本中,在解释器和模块/包中也可以找到。
>>> print(__name__)
__main__
>>>
test_file.py:
print(__name__)
导致__main__
somefile.py:
def somefunction():
print(__name__)
test_file.py:
import somefile
somefile.somefunction()
导致somefile
请注意,在包或模块中使用时,__name__
采用文件名。实际模块或包路径的路径未给出,但有自己的DunderAlias __file__
,允许此操作。
您应该看到,在主文件(或程序)中使用__name__
将始终返回__main__
,而如果它是模块/包或任何运行于其他Python脚本的东西,则将返回其源自的文件的名称。
作为一个变量意味着它的值可以被覆盖(“可以”并不意味着“应该”),覆盖__name__
的值将导致可读性下降。因此,请不要这样做,无论出于何种原因。如果需要一个变量,请定义一个新变量。
通常假定__name__
的值为__main__
或文件名。再次更改此默认值会导致更多混乱,而不是好处,从而在后面引起问题。
>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>
通常情况下,在脚本中包含 if __name__ == '__main__'
被认为是一个好的实践。
if __name__ == '__main__'
:现在我们了解了 __name__
的行为,事情变得更清晰了:
if
是一个流程控制语句,如果给定的值为真,则包含执行代码块。我们已经知道 __name__
可以使用 __main__
或导入它的文件名。
这意味着,如果 __name__
等于 __main__
,则文件必须是主文件,实际上正在运行(或者是解释器),而不是导入到脚本中的模块或包。
如果确实如此,__name__
将采用 __main__
的值,然后将执行该代码块中的内容。
这告诉我们,如果正在运行的文件是主文件(或直接从解释器运行),则必须执行该条件。如果它是一个包,则不应该执行,而且此值将不是 __main__
。
__name__
也可以在模块中用来定义模块的名称。
还可以使用 __name__
进行其他不太常见但有用的事情,这里我将展示一些:
if __name__ != '__main__':
# Do some useful things
if __name__ == '__main__':
# Execute something
else:
# Do some useful things
你可以使用它来提供可运行的帮助函数/实用工具,而不需要繁琐地使用库。
它还允许模块作为主脚本从命令行运行,这也非常有用。
我认为最好深入浅出地解释一下:
__name__
:Python 中的每个模块都有一个特殊属性叫做__name__
。它是一个内置变量,返回模块的名称。
__main__
:和其他编程语言一样,Python 也有一个执行入口,也就是主函数。 '__main__'
是顶级代码执行所在范围的名称。基本上使用 Python 模块的两种方式: 直接作为脚本运行或者导入。当一个模块作为脚本运行时,它的__name__
被设置为__main__
。
因此,当模块作为主程序运行时,__name__
属性的值被设置为__main__
。否则,__name__
的值将包含模块的名称。
当从命令行调用Python文件时,这是一个特殊的情况。通常用于调用"main()"函数或执行其他适当的启动代码,例如处理命令行参数。
可以用多种方式编写。另一种方式是:
def some_function_for_instance_main():
dosomething()
__name__ == '__main__' and some_function_for_instance_main()
我并不是在说你应该在生产代码中使用它,但它可以用来说明if __name__ == '__main__'
并没有什么“神奇”的地方。
这只是Python文件中调用主函数的一种约定。
and
作为控制语句是非常熟悉的。我对此没有任何问题。另一个类似的习惯用法是使用or
来设置默认值。例如,x = input("what is your name? ") or "Nameless Person"
。 - John Henckeland
没有任何好处;该函数甚至不返回值。它只会使代码更加难以理解。 - jpmc26and
来控制流程,或者使用 or
来分配默认值?我尝试过谷歌搜索,但是没有找到任何相关信息。 - John Henckeland
语句中嵌套调用。Python有构造使得这种行为对读者更加明显。这里的使用模式(如果条件为真,则执行以下代码)是if
设计的唯一目的;and
被设计用于计算两个条件是否同时为真。这个and
语句的第二个操作数甚至没有被使用。 - jpmc26系统(Python解释器)为源文件(模块)提供了许多变量。您可以随时获取它们的值,因此,让我们聚焦于__name__变量/属性:
当Python加载源代码文件时,它会执行其中找到的所有代码。(请注意,它不调用文件中定义的所有方法和函数,但确实定义了它们。)
然而,在解释器执行源代码文件之前,它为该文件定义了一些特殊变量;__name__是Python自动为每个源代码文件定义的这些特殊变量之一。
如果Python将此源代码文件作为主程序(即您运行的文件)进行加载,则它会将此文件的特殊__name__变量设置为值"__main__"。
如果此文件正在从另一个模块导入,则__name__将被设置为该模块的名称。
因此,在部分示例中:
if __name__ == "__main__":
lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))
表示代码块:
lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))
只有在你直接运行该模块时才会执行;如果另一个模块正在调用/导入它,则该代码块将不会执行,因为在那种情况下 __name__ 的值将不等于 "main"。
希望这可以帮到你。
if __name__ == "__main__":
基本上是顶层脚本环境,它指定了解释器('我优先被执行')。
'__main__'
是顶层代码执行的作用域名称。当从标准输入、脚本或交互式提示符中读取时,一个模块的__name__
被设置为'__main__'
。
if __name__ == "__main__":
# Execute only if run as a script
main()
考虑:
print __name__
上述代码的输出是 __main__
。
if __name__ == "__main__":
print "direct method"
上述语句是正确的并打印出"直接方法"。假设他们在另一个类中导入了这个类,它就不会打印出"直接方法",因为在导入时,它会将__name__设置为"第一个模型名称"。
if __name__
检查保护的代码仅在作为命令调用时运行,而不是在导入时运行。 如果您想使用交互式Python会话调试Python脚本,这也很有用。 您可以在交互式会话中“导入”通常作为命令运行的代码,然后手动输入代码以您喜欢的方式运行脚本中的函数/类。 - cnamejj