Python 的 __name__ 变量,到底是个什么东西? - 图1

优达学城(Udacity)
由 Google 无人车之父创立、硅谷前沿在线科技学习平台
关注他
282 人赞同了该文章
Python 的 __name__ 变量,到底是个什么东西? - 图2
很多Python脚本里见到过name变量了吧?它经常是以类似这样的方式出现在我们的程序里:

  1. if __name__ == '__main__':
  2. main()

今天,我就带大家详细扒一扒这个内置变量的用法,示范一下在你写的 Python 模组里要怎么用到它。
这个 name 拿来做什么的?
作为 Python 的内置变量,name变量(前后各有两个下划线)还是挺特殊的。它是每个 Python 模块必备的属性,但它的值取决于你是如何执行这段代码的。
在许多情况下,你的代码不可能全部都放在同一个文件里,或者你在这个文件里写的函数,在其他地方也可以用到。为了更高效地重用这些代码,你需要在 Python 程序中导入来自其他文件的代码。
所以,在name 变量的帮助下,你可以判断出这时代码是被直接运行,还是被导入到其他程序中去了。
这个 name 变量可能取什么值?
当你直接执行一段脚本的时候,这段脚本的 name变量等于 main,当这段脚本被导入其他程序的时候,name 变量等于脚本本身的名字。
下面,让我举两个栗子来说明一下:
Python 的 __name__ 变量,到底是个什么东西? - 图3

情况 1 - 直接运行脚本

假设我们有一个nameScript.py,代码如下:

def myFunction():
    print('变量 __name__ 的值是 ' + __name__)
def main():
    myFunction()
if __name__ == '__main__':
    main()

当你直接执行 nameScript.py 时,流程是这样处理的:
Python 的 __name__ 变量,到底是个什么东西? - 图4

在所有其他代码执行之前,name变量就被设置为 main 了。在此之后,通过执行 def 语句,函数 main()myFunction() 的本体被载入。
接着,因为这个 if 语句后面的表达式为真 true,函数 main() 就被调用了。而 main() 函数又调用了myFunction(),打印出变量的值main

情况 2 - 从其他脚本里导入

如果你需要在其他脚本里重用这个 myFunction() 函数,比如在 importingScript.py 里,我们可以将 nameScript.py 作为一个模组导入。
假设 importingScript.py 的内容如下:

import nameScript as ns
ns.myFunction()

这时,我们就有了两个不同的作用域:一个是 importingScript 的,一个是 nameScript 的。让我画个示意图,你就能看出这和之前的区别了:
Python 的 __name__ 变量,到底是个什么东西? - 图5
importingScript.py 里,name 变量就被设置为 main。当导入 nameScript 的时候,Python 就在本地和环境变量 PATH 指向的路径中寻找对应名称的 .py 文件,找到之后,将会运行导入的文件中的代码。
但这一次,在导入的时候,它自身的 name 变量就被设置为了 ‘nameScript’,接下来还是一样,函数 main()myFunction() 的本体被载入。然而,这一次 if 语句后面的表达式结果为假 false,所以 main() 函数没有被调用。
导入完毕之后,回到 importingScript.py 中。现在 nameScript 模块中的函数定义已经被导入到当前的作用域中,于是我们通过 ns.myFunction() 的方式调用模块中的函数,这个函数返回的是模块内的变量的值 ‘nameScript’
如果你试着在 importingScript 中打印 name 变量的值,那当你直接执行 importingScript 的时候,它也会输出 main。原因在于,这个变量是在 importingScript 的作用域中的