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

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

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


当前回答

简单的说,它是一个切入点 运行文件,像main函数中C编程语言。

其他回答

短答

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

  • 如果您在另一个脚本中导入了无保护脚本(例如 ) 。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__是为每个脚本定义的变量,以定义脚本是作为主模块运行还是作为导入模块运行。

如果我们有两本脚本,

#script1.py
print "Script 1's name: {}".format(__name__)

#script2.py
import script1
print "Script 2's name: {}".format(__name__)

执行脚本1 的输出为

Script 1's name: __main__

执行脚本2 的输出为 :

Script1's name is script1
Script 2's name: __main__

如你所见__name__告诉我们哪个代码是“ main” 模块。 这很棒, 因为您可以只写代码, 而不必担心 C/ C++ 中的结构问题, 如果一个文件不执行“ main” 函数, 那么它无法编译为可执行文件, 如果它可以, 那么它就不能用作图书馆 。

说您会写出一个 Python 脚本,该脚本能做一些伟大的事情,而您会执行一系列用于其他目的的功能。如果我想使用这些功能,我可以在不执行您的程序的情况下导入并使用您的脚本(因为您的代码仅在if __name__ == "__main__":在 C/C++ 中,您需要将这些部分分割成一个单独的模块, 包括文件。 图片如下:

Complicated importing in C

箭头是导入链接。 对于试图包含前一个模块代码的3个模块,每个模块有6个文件(9个,计算执行文件)和5个链接。这使得将其他代码纳入 C 工程很难,除非它是专门编译成一个库。 现在为 Python 绘制它:

Elegant importing in Python

你写一个模块, 如果有人想使用你的代码, 他们只是导入它和__name__变量可以帮助将程序的可执行部分与库部分分开。

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

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

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

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

所有答案都大致解释了它的功能。但我将举一个例子来说明它的用法,这可能有助于进一步澄清这个概念。

假设你有两个Python文件,A.py和B.py。a.py进口进口进口b.py。我们运行a.py文件, 在哪里import b.py代码先执行。在其余a.py代码运行,文件中的代码b.py必须完全运行。

在b.py 代码中,有一些代码是那个文件的独有代码b.py我们不想要任何其他文件(不包括b.py已导入 b. py 文件来运行 。

这就是这行代码检查。如果它是主文件(即,b.py运行代码,在这种情况下它不是代码 (a.py是正在运行的主文件),然后只有代码才能被执行。

当执行 Python 文件时, 它会创建许多特殊的变量, 例如__name__变量__name__您问题的答案是:

if __name__ == "__main__":
       # Do something

这意味着,如果所执行的文件的名称作为源文件运行,并且非模块然后它会运行里面的代码。 这可以用简单的示例来证明。 创建两个 Python 文件,foo.pysecond.py。然后在foo.py,类型如下:

if __name__ == "__main__":
       print("file is not imported")
else:
       print("file is imported")

和在second.py,类型如下:

import foo

if foo.__name__ == "__main__":
       print("file is not imported")
else:
       print("file is imported")

除此以外,如果你们要这样做,print(__name__)然后将打印__main__为什么?

因为文件以主要源代码,如果你愿意print(foo.__name__)将打印fuo fuo的默认值,因为__name__变量是文件的名称,默认是文件的默认名称,我的意思是,您也可以更改它。要做到这一点,只需去foo.py并做此操作的文件 :__name__ = "name"。然后当你运行文件,例如,

__name__ = "Hello, World!"
print(__name__)

然后产出将是:

Hello, World!