德阳移动网站建设,湖南智能网站建设哪里好,做网站还需要兼容ie6吗,网站建设公司创意这个问题来自于知乎用户的提问#xff0c;当时看到这个问题#xff0c;我只是做了下简单的回答。后来我发现#xff0c;对于很多人来说#xff0c;更准确的说应该是大部分的 Python 初学者#xff0c;对这个问题理解的不是很深刻。所以这里我来做下总结#xff0c;并试图…这个问题来自于知乎用户的提问当时看到这个问题我只是做了下简单的回答。后来我发现对于很多人来说更准确的说应该是大部分的 Python 初学者对这个问题理解的不是很深刻。所以这里我来做下总结并试图把这个问题说明白。
程序入口
对于很多编程语言来说程序都必须要有一个入口比如 CC以及完全面向对象的编程语言 JavaC# 等。如果你接触过这些语言对于程序入口这个概念应该很好理解C 和 C 都需要有一个 main 函数来作为程序的入口也就是程序的运行会从 main 函数开始。同样Java 和 C# 必须要有一个包含 Main 方法的主类来作为程序入口。
而 Python 则有不同它属于脚本语言不像编译型语言那样先将程序编译成二进制再运行而是动态的逐行解释运行。也就是从脚本第一行开始运行没有统一的入口。
一个 Python 源码文件除了可以被直接运行外还可以作为模块也就是库被导入。不管是导入还是直接运行最顶层的代码都会被运行Python 用缩进来区分代码层次。而实际上在导入的时候有一部分代码我们是不希望被运行的。
举一个例子来说明一下假设我们有一个 const.py 文件内容如下
PI 3.14def main():print PI:, PImain()我们在这个文件里边定义了一些常量然后又写了一个 main 函数来输出定义的常量最后运行 main 函数就相当于对定义做一遍人工检查看看值设置的都对不对。然后我们直接执行该文件(python const.py),输出
PI: 3.14现在我们有一个 area.py 文件用于计算圆的面积该文件里边需要用到 const.py 文件中的 PI 变量那么我们从 const.py 中把 PI 变量导入到 area.py 中
from const import PIdef calc_round_area(radius):return PI * (radius ** 2)def main():print round area: , calc_round_area(2)main()运行 area.py输出结果
PI: 3.14
round area: 12.56可以看到const 中的 main 函数也被运行了实际上我们是不希望它被运行提供 main 也只是为了对常量定义进行下测试。这时if __name__ __main__ 就派上了用场。把 const.py 改一下
PI 3.14def main():print PI:, PIif __name__ __main__:main()然后再运行 area.py输出如下
round area: 12.56再运行下 const.py输出如下
PI: 3.14这才是我们想要的效果。
if __name__ __main__ 就相当于是 Python 模拟的程序入口。Python 本身并没有规定这么写这只是一种编码习惯。由于模块之间相互引用不同模块可能都有这样的定义而入口程序只能有一个。到底哪个入口程序被选中这取决于 __name__ 的值。
__name__
__name__ 是内置变量用于表示当前模块的名字同时还能反映一个包的结构。来举个例子假设有如下一个包
a
├── b
│ ├── c.py
│ └── __init__.py
└── __init__.py目录中所有 py 文件的内容都为
print __name__我们执行 python -c import a.b.c输出结果
a
a.b
a.b.c由此可见__name__ 可以清晰的反映一个模块在包中的层次。其实所谓模块名就是 import 时需要用到的名字例如
import tornado
import tornado.web这里的 tornado 和 tornado.web 就被称为模块的模块名。
如果一个模块被直接运行则其没有包结构其 __name__ 值为 __main__。例如在上例中我们直接运行 c.py 文件python a/b/c.py输出结果如下
__main__所以if __name__ __main__ 我们简单的理解就是 如果模块是被直接运行的则代码块被运行如果模块是被导入的则代码块不被运行。
实际上这个问题还可以衍生出其他的一些知识点例如 __main__.py 文件与 Python 的 -m 参数。
__main__.py 文件与 python -m
Python 的 -m 参数用于将一个模块或者包作为一个脚本运行而 __main__.py 文件则相当于是一个包的”入口程序“。
首先我们需要来看看 python xxx.py 与 python -m xxx.py 的区别。两种运行 Python 程序的方式的不同点在于一种是直接运行一种是当做模块来运行。
先来看一个简单的例子假设有一个 Python 文件 run.py其内容如下
import sys
print sys.path我们用直接运行的方式启动python run.py输出结果(为了说明问题输出结果只截取了重要部分下同)
[/home/huoty/aboutme/pythonstudy/main, ...]然后以模块的方式运行python -m run.py:
[, ...]
/usr/bin/python: No module named run.py由于输出结果只列出了关键的部分应该很容易看出他们之间的差异。直接运行是把 run.py 文件所在的目录放到了 sys.path 属性中。以模块方式运行是把你输入命令的目录也就是当前工作路径放到了 sys.path 属性中。以模块方式运行还有一个不同的地方是多出了一行 No module named run.py 的错误。实际上以模块方式运行时Python 先对 run.py 执行一遍 import所以 print sys.path 被成功执行然后 Python 才尝试运行 run.py 模块但是在 path 变量中并没有 run.py 这个模块所以报错。而正确的运行方式应该是 python -m run.
这个例子并不能明显的说明问题。接着我们来看看 __main__.py 的作用。
仍然先看例子有如下一个包
package
├── __init__.py
└── __main__.py__init__.py
import sys
print __init__
print sys.path__main__.py
import sys
print __main__
print sys.path用 python -m package 运行结果
__init__
[, ...]
__main__
[, ...]用 python package 运行结果
__main__
[package, ...]然后我们来总结一下
1、 加上 -m 参数时会把当前工作目录添加到 sys.path 中而不加时则会把脚本所在目录添加到 sys.path 中。2、 加上 -m 参数时 Python 会先将模块或者包导入然后再执行3、 __main__.py 文件是一个包或者目录的入口程序。不管是用 python package 还是用 python -m package 运行时__main__.py 文件总是被执行。
后序
我试图使用长篇大论来阐述在 Python 中如何理解 if __name__ __main__ 这个问题不知道我有没有描述得足够的明白。Python 的确是简单的优雅的但也有很多问题是不太容易理解的例如很多高级的特性像元类、生成器表达式、描述符、协程等。Python 并没有在太多的地方规定要如何如何很多的用法只是惯用法例如 self 和本文讨论的内容。这些用法或是为了让代码看起来更优雅或是前人的经验。使用 Python 是有无限可能的你可以写出很多简洁优雅的代码。
参考资料
http://www.tuicool.com/articles/jMzqYzFhttp://stackoverflow.com/questions/4042905/what-is-main-py