理解Python的主方法
我刚开始学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 个回答
如果你从另一个 Python 脚本中导入你现在正在创建的模块(.py 文件),那么里面的代码不会被执行。
if __name__ == '__main__':
...
但是如果你直接从控制台运行这个脚本,它就会被执行。
Python 不需要一个叫 main() 的函数。任何没有被保护的代码在执行或者导入模块时都会被执行。
关于这个内容可以在 python.berkely.edu 上找到更多信息。
Python和Java、C、C++等语言不一样,没有一个固定的入口点。它的运行方式是逐行执行源文件的内容。通过if
语句,你可以创建一个main
函数,这个函数会在你的文件被当作“主模块”加载时执行,而不是作为其他模块中的库来使用。
简单来说,这意味着Python解释器会从文件的第一行开始执行代码。像class Foobar:
和def foobar()
这样的代码行,会创建一个类或一个函数,并把它们存储在内存中,以便后续使用。
在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__
,那就说明这个模块是由用户独立运行的,这时我们可以执行相应的操作。
在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
)。