理解Python的主方法

165 投票
4 回答
403066 浏览
提问于 2025-04-17 22:53

我刚开始学Python,但我在其他面向对象编程语言上有一些经验。我的课程没有解释Python中的主方法。

请告诉我Python中的主方法是怎么工作的?我有点困惑,因为我在尝试把它和Java进行比较。

def main():
# display some lines

if __name__ == "__main__": main()

主方法是怎么执行的?我为什么需要这个奇怪的if来执行main?当我去掉if时,我的代码就会终止而没有输出。

最简单的代码 -

class AnimalActions:
    def quack(self): return self.strings['quack']
    def bark(self): return self.strings['bark']

class Duck(AnimalActions):
    strings = dict(
        quack = "Quaaaaak!",
        bark = "The duck cannot bark.",
    )


class Dog(AnimalActions):
    strings = dict(
        quack = "The dog cannot quack.",
        bark = "Arf!",
    )

def in_the_doghouse(dog):
    print(dog.bark())

def in_the_forest(duck):
    print(duck.quack())

def main():
    donald = Duck()
    fido = Dog()

    print("- In the forest:")
    for o in ( donald, fido ):
        in_the_forest(o)

    print("- In the doghouse:")
    for o in ( donald, fido ):
        in_the_doghouse(o)

if __name__ == "__main__": main()

4 个回答

10

如果你从另一个 Python 脚本中导入你现在正在创建的模块(.py 文件),那么里面的代码不会被执行。

if __name__ == '__main__':
    ...

但是如果你直接从控制台运行这个脚本,它就会被执行。

Python 不需要一个叫 main() 的函数。任何没有被保护的代码在执行或者导入模块时都会被执行。

关于这个内容可以在 python.berkely.edu 上找到更多信息。

21

Python和Java、C、C++等语言不一样,没有一个固定的入口点。它的运行方式是逐行执行源文件的内容。通过if语句,你可以创建一个main函数,这个函数会在你的文件被当作“主模块”加载时执行,而不是作为其他模块中的库来使用。

简单来说,这意味着Python解释器会从文件的第一行开始执行代码。像class Foobar:def foobar()这样的代码行,会创建一个类或一个函数,并把它们存储在内存中,以便后续使用。

81

在Python中,程序的执行不一定要从main开始。实际上,第一行“可执行代码”会最先被执行。

def main():
    print("main code")

def meth1():
    print("meth1")

meth1()
if __name__ == "__main__":main() ## with if

输出 -

meth1
main code

关于main()的更多信息 - http://ibiblio.org/g2swap/byteofpython/read/module-name.html

一个模块的 __name__

每个模块都有一个名字,模块里的代码可以知道它自己所在模块的名字。这在某些情况下特别有用——之前提到过,当一个模块第一次被导入时,那个模块里的主代码块会被执行。如果我们希望这个代码块只在程序独立运行时执行,而不是在被其他模块导入时执行,该怎么做呢?这可以通过使用模块的 name 属性来实现。

使用模块的 __name__

#!/usr/bin/python
# Filename: using_name.py

if __name__ == '__main__':
    print 'This program is being run by itself'
else:
    print 'I am being imported from another module'

输出 -

$ python using_name.py
This program is being run by itself
$ python
>>> import using_name
I am being imported from another module
>>>

原理 -

每个Python模块都有一个定义好的 __name__,如果这个值是 __main__,那就说明这个模块是由用户独立运行的,这时我们可以执行相应的操作。

226

在Python中,处理“主程序”的方式几乎是这个语言特有的。

这个概念有点微妙。__name__这个标识符会和任何被导入的模块的名字绑定在一起。但是,当一个文件被直接执行时,__name__会被设置为"__main__"(就是这个字面意思:__main__)。

这通常用来区分哪些代码是要执行的,哪些代码是用来定义功能的。所以Python代码里常常会有这样一行:

#!/usr/bin/env python
from __future__ import print_function
import this, that, other, stuff
class SomeObject(object):
    pass

def some_function(*args,**kwargs):
    pass

if __name__ == '__main__':
    print("This only executes when %s is executed rather than imported" % __file__)

通过这种约定,一个文件可以定义类和函数供其他程序使用,同时也可以包含一些代码,这些代码只有在文件作为独立脚本被调用时才会执行。

重要的是要理解,if __name__这一行之前的所有代码在两种情况下都会被执行和评估。无论是文件被导入还是直接执行,解释器都会评估这些代码。如果你在if __name__之前放一个print语句,那么每次其他代码尝试导入这个模块时,它都会打印输出。(当然,这样做会很不友好,最好不要这样做)。

我个人很喜欢这种语义。它鼓励程序员将功能(定义)和执行(功能调用)分开,从而促进代码的重用。

理想情况下,几乎每个Python模块在命令行调用时都能做一些有用的事情。在很多情况下,这个特性被用来管理单元测试。如果某个文件定义的功能仅在系统的其他组件中有用,那么仍然可以使用__name__ == "__main__"来隔离一段代码,这段代码会调用适用于这个模块的一系列单元测试。

(如果你没有这样的功能或者单元测试,最好确保这个文件不可执行)。

总结一下:if __name__ == '__main__':有两个主要的用途:

  • 允许一个模块在被其他代码导入时提供功能,同时作为独立脚本提供有用的语义(相当于功能的命令行包装)。
  • 允许一个模块定义一套单元测试,这些测试和要测试的代码放在同一个文件里,并且可以独立于其他代码执行。

如果你想以类似其他编程语言的方式定义主程序,通常会用def main(*args),然后在if __name__ == '__main__':中简单调用main(*sys.argv[1:])。如果你的.py文件主要是作为其他代码的模块使用,那么你可以定义def test_module(),并在if __name__ == '__main__:'中调用test_module()

  • (Ruby也实现了类似的功能if __file__ == $0)。

撰写回答