pygeta

if __name__ == "__main__”这样的语句出现。这个语句是用来干什么的?

这是一个条件判断语句,如果条件满足,就进入下面的语句。简单来说,该语句用来当文件当作脚本运行时候,就执行代码;但是当文件被当做Module被import的时候,就不执行相关代码。

那么需要考虑的是,什么时候if __name__ == “__main__”会为True,也就是__name__ 变量会等于“__main__”?__name__变量是一个Python的Module的全局变量,Python解析器会在执行过程中设置该变量。当Python解析器将代码当作顶层模块运行的时候,__name__变量就会被赋值为“__main__”。

所谓的顶层模块,就是指第一个运行的用户定义的Python的模块。这个模块由于是第一个执行的,因此在该模块运行中,将会由此模块导入imports所有其他的别的相关依赖模块。因此该模块就被当作顶层模块。

  • 最顶层的__name__,将会被设置成了__main__

  • 导入的模块中的__name__就被设置成了模块的名称

因此也可以用if __name__ == “__main__”来判断你的模块代码是不是被当作最顶层模块在使用。

什么时候需要避免使用if __name__ == "__main__”语句。

有些时候可以用来屏蔽掉执行测试的部分代码。比如下面的例子:

如果该模块被执行,可以用来执行测试用例,否则就当作一个模块导入,测试不会被执行。

 

# adder.py
import unittest
def add(a: int, b: int) -> int:
return a + b
class TestAdder(unittest.TestCase):
def test_add_adds_two_numbers(self):
self.assertEqual(add(1, 2), 3)
if __name__ == "__main__":
unittest.main()

 

但是这种方式不太建议,在比较规模项目的测试中,是可以这么做,但是如果代码量一大,这种将代码和测试混在一个文件的方式,不太方便代码管理。一般应该是将测试代码写在另外一个文件中。同时这也要求将

unittest模块在代码模块中导入,这也不是一个很好的实现。

另外一个不好的使用例子是用来包含一些模块使用信息,当用户导入该模块的时候,使用信息不会被执行,但是当当作脚本运行的时候,就可以打印出使用信息。

这其实也不是一个很好的实践。如果是用来打印使用信息,可以用别的更好的方法(比如编写详细的docstrings)。

第三种情况是纯脚本情况:如果你要写的代码就是一个脚本,那么你就直接写代码在全局空间中即可,不要再放到if __name__ == “__main__”下,这样做意义不大。

最后讲一下使用if __name__ == “__main__"的最佳实践。

首先这个语句只是一个判断语句,因此该语句可以被放到文件的任何地方,也可以多次使用。但是比较好的建议是大部分情况,该语句只在文件中出现一次,并且放到文件的最后。这样可以似的代码变得比较整洁,逻辑也会清晰很多。该语句放到最后还有一个好处,就是确保所有需要使用的函数或者变量都已经在前面定义好了。

但是在某些情况,也可以多次的使用if __name__ == "__main__”语句。

比如分情况导入其他模块,见如下例子:

 

# echo.py
if __name__ == "__main__":
import sys
def echo(text: str, repetitions: int = 3) -> str:
"""Imitate a real-world echo."""
echoed_text = ""
for i in range(repetitions, 0, -1):
echoed_text += f"{text[-i:]}\n"
return f"{echoed_text.lower()}."
if __name__ == "__main__":
text = " ".join(sys.argv[1:])
print(echo(text))

 

在该例子中,可以利用该条件语句,是的不必要的导入一些模块。过多的解释就不在赘述。

另外的一个好的代码风格就是if __name__ == "__main__”下面的代码应该尽可能的少,如果需要放比较多的代码,

那么就应该另外定义个main函数来包含这些代码。

 

比如如下代码:

 

# echo.py
import sys
def echo(text: str, repetitions: int = 3) -> str:
"""Imitate a real-world echo."""
echoed_text = ""
for i in range(repetitions, 0, -1):
echoed_text += f"{text[-i:]}\n"
return f"{echoed_text.lower()}."
def main() -> None:
text = " ".join(sys.argv[1:])
print(echo(text))
if __name__ == "__main__":
main()

 

后记

很多讨论将python的if __name__ == “__main__"和其他语言的入口函数main()做比较,然后得出结论说python的语法太不简洁。其实事情并不是这样的,if __name__ == "__main__"只是一个判断语句,不是程序的入口点。

python在演化过程中,对该语句的讨论也进行过很多次,但是一直也没有取消这个语句,主要原因有如下几点:

  • 这个语句已经很短了:很多其他的建议节约不了几行代码

  • 使用场景不多:只建议在需要将一个脚本文件运行同时也能够当作模块导入的时候,需要用到,其他情况不建议经常使用。

  • 暴露了复杂性:让python使用人员,能够了解python的背后的变量和函数,这样可以更好的理解python的实现。

  • 可以向后兼容。

posted on   水月木子  阅读(28)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示