这段代码实际上在做什么?
当你执行 xy.py 时,你会导入 ab。 import 语句在导入时运行模块,因此 ab 的操作在 xy 的其余部分之前执行。完成 ab 后,它会继续使用 xy。
解释器跟踪使用__name__ 运行的脚本。当你运行一个脚本时——不管你给它起什么名字——解释器都称它为"__main__"。这就是它跟踪哪个脚本是主文件的方式,即在外部调用另一个脚本后返回的脚本。 (你可能会说“home”脚本。)
从此“主”脚本调用的任何其他脚本都被分配其文件名作为其__name__。因此,if __name__ == "__main__" : 行是解释器的测试,以确定它是否在它正在查看(解析)的脚本上运行,或者它是否暂时窥视另一个脚本。这使程序员可以灵活地让脚本在外部调用时表现不同。
要了解发生了什么,请首先关注未缩进的行以及它们在脚本中出现的顺序。记住这个函数——或者def——块在被调用之前不会自己做任何事情。口译员自言自语时可能会怎么想:
- 打开xy.py。
- 使用
__name__ab.py导入和打开文件。
- 哦,一个函数。我会记住的。
- 好的,函数a();我刚刚学到了。我想我现在要打印了。
- 文件结束;回
'__main__'!
- 哦,一个函数。我会记住的。
- 另一个。
- 函数 x();好的,打印 's'。
- 这是什么?
if 声明。嗯,条件已经满足(变量__name__已经设置为'__main__'),所以我打印'b function'。
但是,我认为您没有正确使用它。可能有例外,但最下面两行应该是:
if __name__ == "__main__":
main()
... 这意味着“如果这是'主'或主脚本,请执行名为 main() 的函数。这就是为什么您会在顶部看到一个 def main(): 块,其中包含脚本的主要流程功能。
我们为什么要实现这个?
还记得我之前说过的关于 import 语句的内容吗?当您导入一个模块时,它不仅会“识别”它并等待进一步的说明。它实际上运行脚本中包含的所有可执行操作。因此,将脚本的内容放入 main() 函数可以有效地隔离它,将其隔离,以便在被另一个脚本导入时无法立即运行。
同样,会有例外,但通常的做法是main() 通常不会被外部调用。所以你可能想知道一件事:如果我们不调用main(),我们为什么要调用脚本呢?这是因为许多人使用独立的函数来构建他们的脚本,这些函数是为自己运行而构建的。然后在脚本正文的其他地方调用它们。这让我想到了这一点:
我们的代码在没有它的情况下也可以工作
是的,你是对的。这些单独的函数可以从不包含在main() 函数中的内嵌脚本中调用。如果您习惯于(就像我一样,在我编程的早期学习阶段)构建完全符合您需要的内联脚本,并且如果您再次需要该操作,您将尝试再次弄清楚 - 好吧,你不习惯代码的这种内部结构,因为它构建起来更复杂,而且阅读起来也不那么直观。
但这是一个可能无法在外部调用其函数的脚本,因为如果这样做,它将开始计算和分配变量。如果您尝试重用一个函数,那么您的新脚本与旧脚本的相关性可能非常密切,以至于可能存在冲突的变量。
顺便说一句,this question 包含 an answer by kindall,这最终帮助我理解了 - 为什么,而不是 如何。不幸的是,它被标记为this one 的副本,我认为这是一个错误。 (我是这个网站的新手,所以还不能标记它;如果你同意我的观点,请标记它以引起模组的进一步关注。)