卡卷网
当前位置:卡卷网 / 每日看点 / 正文

python: if __name__ == "__main__" 到底是什么鬼?

作者:卡卷网发布时间:2025-03-27 22:48浏览数量:39次评论数量:0次

引言

if __name__ == '__main__'可能对于很多初学者来说都是比较难以理解的知识点,今天将站在python设计者的角度,全新的方式来认识它。

有部分人可能不太明白,为什么明明它作为一个程序入口却是写在了文件的最后 ?那么在本文中也将揭露该原因。

一、结构组成

为了能够深入了解 if __name__ == '__main__',我们必须从它的组成部分说起。

python: if __name__ == "__main__" 到底是什么鬼?  第1张

四个部分

其实我们将其划分,它总共也就四个部分组成,其中包括:

  1. if: 表示这行代码是判断语句
  2. __name__: 这个是python的内置变量
  3. ==: 判断的依据是相等才为真
  4. '__main__': 这就是个字符串

我相信大部分读者应该已经了解条件判断的逻辑,例如:

a = 1 if a == 1: print('这是真的')

上面的输出结果为真,所以会打印出内容:

这是真的

那么 if __name__ == '__main__' 其实也好理解,它就是一个条件判断,判断的输出为真,则将执行条件中的代码。

那么它难以理解的部分其实就是 __name____main__,接下来我们将逐步剖析他们。

二、__name__

想象一下,你创建了四份.py文件,它们分别是 a.py、b.py、c.py和d.py,其中 d.py 比较特殊,它被放置在了 D 的文件夹中。

2.1 为.py文件取名

现在你来扮演 python设计者,帮忙将这几个文件,在代码中 分别取一个名字吧:

python: if __name__ == "__main__" 到底是什么鬼?  第2张

请为.py文件取名


怎么样,想好了吗?看看你与 python设计者 是不是想到一块去了:

python: if __name__ == "__main__" 到底是什么鬼?  第3张

python解释器为.py文件取名

规则很简单:当.py文件是单独文件,它就是.py后缀前的名称;当.py文件存在于文件夹时,它的名称为“文件夹.xxx”

好了,既然我们为 .py 文件一一对应取了名字,那么如何去保存它,并让开发者获取到呢?

想到了吗?我们可以通过变量来赋值,例如:

# a.py中 name = 'a' # b.py中 name = 'b' # c.py中 name = 'c' # d.py中 name = 'D.d'

我们通过一个变量 name 给我们取的名字赋了值,这样开发者就能获取到名称了。

2.2 变量名冲突

不过 python 是面向全球开发者的,如果我们的开发者想要在自己的代码中使用 name 作为变量名称,那就可能会把我们的 name 变量覆盖掉:

# python解释器生成的名称 name = 'a' # 开发者设计的变量 name = '张飞' print(name)

name 这个英文单词太常见了,因此使用频繁度很高,类似的还有 init、set、get、call等等。

大家能明白上面的代码发生了什么吗?原来的 name'a',可是因为开发者使用了 name 作为变量名,现在 name 变成了 '张飞',这将会使 python设计者 的工作成为无用功。

谁都不想让自己的工作变得无效,特别是python设计者 本人。怎么办,有没有更好的解决方式?

聪明的 python设计者 想到:既然如此,我需要制定我的规则,以后凡是看到 __xxxx__ 类似的内容就是 python解释器 生成的,你们开发者请使用其他变量名进行开发,谢谢!

所以,现在会发生如下改变:

# 原来的 name = 'a' # 现在 __name__ = 'a'

凡是 __xxxx__ 的内容都是 python解释器 内部生成的,不需要开发者自己实现。

2.3 隐藏

终于,python设计者 颁布的规定非常有效,但是显式的地展示 python内部产生 的变量实在是让 .py 文件看上去很难看,开发者一创建一份 .py 文件,开头就是一行变量赋值。

__name__ = 'a' # 下面是开发者自己的代码 ...

为了让 .py 文件更加简洁优美,没有太多冗余,python设计者 决定,隐藏所有 xxxx 的变量,这样开发者的文件仅需要关注自己的代码逻辑,而不会被 python 内置变量所迷惑。

# 现在开发者可以专注于自己的代码逻辑 # 而不用看到python产生的内置变量了 a = 2 b = 3 total = a + b print(total)

当然,如果开发者想获取内置变量当然也可以,只需要输入我们内置变量的名称即可获取相应的数据:

a = 2 b = 3 total = a + b print(total) print(__name__)

如果你想,你可以在任何时候通过内置变量的名称获取到它的值。

2.4 运行文件的名称

现在为 .py 文件取名已经完美解决,但现在有一个非常 特殊的文件 需要我们额外关注。

python: if __name__ == "__main__" 到底是什么鬼?  第4张

运行a.py

现在开发者执行了 python a.py作为设计者 你当然知道现在正在执行 a.py 文件,那么该如何告知开发者呢?

不如重新再创建一个变量,叫做 __has_run__ ,让其等于 True

__has_run__ = True

当执行的 .py__has_run__ == True 则表示该文件是被执行的文件,不然就不是。

我觉得当然可以,但聪明的 python设计者 使用了另一种方式。

三、'__main__'

聪明的 python设计者 借鉴了其他知名语言的一个单词 main

C语言

#include <stdio.h> int main() { return 0; }

C++

#include <iostream> int main() { return 0; }

他们都是通过 main 来表示运行的文件的,当然还有 java、C#、PHP 等等。

而且,python设计者 并没有另外创建一个新的变量,他继续使用 __name__ 来赋值,当一个文件被运行时,它的名字就会改变为 __main__

python: if __name__ == "__main__" 到底是什么鬼?  第5张

python a.py

python: if __name__ == "__main__" 到底是什么鬼?  第6张

python b.py

python: if __name__ == "__main__" 到底是什么鬼?  第7张

python c.py

python: if __name__ == "__main__" 到底是什么鬼?  第8张

python d.py

为何用 '__main__' ?别忘了之前 python设计者 的设计套路,凡是内置的都是类似 __xxxx__

四、结合观察

终于可以解释 if __name__ == '__main__' 了:

4.1 执行 python a.py

当进行 python a.py 时,a.py__name__ 将变为 '__main__',因为条件判断为真,将运行条件判断下的代码:

# python a.py # 其实就是 if '__main__' == '__main__' # 条件判断为 True if __name__ == '__main__': print('我是a.py中的代码')

上面的代码 print('我是a.py中的代码') 将被执行。

4.2 b.py中的情况

此时,由于我们执行的是 python a.py,我们来看看各个文件的名称是如何取名的:

python: if __name__ == "__main__" 到底是什么鬼?  第5张

python a.py

那么假如 b.py 中也有 if __name__ == '__main__',它将如下:

# 其实就是 if 'b' == '__main__' # 条件判断为 False if __name__ == '__main__': print('我是b.py中的代码')

上面的代码由于条件判断为 False,那么 print('我是b.py中的代码') 无法执行。

以此类推, 在 python a.py 的大前提下, c.py、d.py 中相应的 if __name__ == '__main__' 也无法执行。

这就是为什么我们称 if __name__ == '__main__' 为程序的入口:

当我们执行 python xxx.py 时,只有 xxx.py 下的 if __name__ == '__main__' 才能够执行,即程序最开始执行的地方。

五、为何要放在最后

既然是一个程序的入口,为什么 if __name__ == '__main__' 不在开头而放在文件的最后部分?这其实跟 python 的语法有关系,我们来看一个示例:

if __name__ == '__main__': print(a) a = 3

我们将 if __name__ == '__main__' 放在最前方,然后在下方定义了一个 a ,由于 if __name__ == '__main__' 是入口方法,我们都在下方调用,但是能够调用到 a 吗?

NameError: name 'a' is not defined

很明显不能,python 执行时将会报错,这个是因为我们在执行 if __name__ == '__main__' 的时候 a 并没有被定义,因此根本找不到它。python 这跟其他部分语言不通,它的定义必须在使用前,不然无法获取。

变量的调用

正确声明

a = 1 print(a)

错误声明

print(a) a = 1

函数的调用

正确声明

def main(): pass main()

错误声明

main() def main(): pass

类的调用

正确声明

class Dog: pass dog = Dog()

错误声明

dog = Dog() class Dog: pass

所以,为了保证在 if __name__ == '__main__' 中的代码都可以被执行,我们将其放在最后:

a = 1 def main(): pass class Dog: pass if __name__ == '__main__': print(a) main() dog = Dog()

六、阅读代码从 if __name__ == '__main__' 开始

现在我们明白了 if __name__ == '__main__' 的用处即为什么放在最后,我们将改变我们阅读代码的方式。

不要再从文件开头开始读,而是先寻找 if __name__ == '__main__' ,然后在 if __name__ == '__main__' 下开始读代码。下面将用一个示例说明这样做的好处。

def func_1(): # 这里是非常复杂的代码 # 熟悉代码需要花费 10分钟 pass def func_2(): # 这里是非常简单的代码 # 熟悉代码需要花费 5分钟 pass if __name__ == '__main__': func_2()

我们可以看到上面有两个函数,我们看看不同方式阅读代码花费的时间是多少:

  • 从头开始读,为了理解 func_1()func_2() 代码,总花费将使用 15分钟
  • 我们开始从 if __name__ == '__main__' 读代码,你会发现根本没有使用函数 func_1(),你仅需要了解 func_2() 的逻辑,总花费使用 5分钟
读代码方式花费时间
从头开始读15分钟
从 if __name__ == '__main__' 开始读5分钟


由于你不清楚整个文件的逻辑,如果只是为了明白整个程序的逻辑,从头开始读可能会去读很多 无效代码,这会浪费很多时间。

七、PyCharm中的好处

使用 if __name__ == '__main__' ,这个好处将在 PyCharm 中体现的淋漓尽致。

如果不写 if __name__ == '__main__' ,你的文件将无法出现运行按钮:

python: if __name__ == "__main__" 到底是什么鬼?  第10张

没有运行按钮

但只要你写了 if __name__ == '__main__',Pycharm将会给你一个快捷的运行按钮:

python: if __name__ == "__main__" 到底是什么鬼?  第11张

运行按钮

八、结尾

希望你能够通过本篇文章,真正了解到 if __name__ == '__main__' 带来的好处,它不仅将你的代码变得更加规范,而且也有助于提高代码的整体可读性。

如果你喜欢这篇文章,请给我点个赞看到吧!

END

免责声明:本文由卡卷网编辑并发布,但不代表本站的观点和立场,只提供分享给大家。

卡卷网

卡卷网 主页 联系他吧

请记住:卡卷网 Www.Kajuan.Net

欢迎 发表评论:

请填写验证码