模块Module
Lean from python2.7 official documentation
使用文本编辑器编写文件,并将其作为解释器(interpreter)的输入,这样的文件叫做脚本(script)。随着程序越来越长,将脚本拆分成几个文件更利于维护,为此,Python提供将定义写入一个文件中,并在脚本或者解释器中使用它们的方法,这样的文件称作模块(module)。
模块是一个包含Python定义和语句的文件,文件名为模块名加后缀.py
。
模块名(作为一个字符串)可以通过全局变量__name__
来获得。
6.1 更多有关模块的信息
模块包含的语句以及函数定义,用于模块的初始化,仅在模块第一次在import语句中被导入时才执行。(当文件被当作脚本运行时,它们也会执行。)
每个模块都有自己的私有符号表(private symbol table),作为模块中定义的所有函数的全局符号表。模块的作者可以在模块内使用全局变量(global variables),而不必担心与用户的全局变量冲突。
习惯上把所有导入模块的import
语句放在脚本或模块的开头,被导入的模块名存放在全局符号表中。
import
语句有一个变体,它可以把模块符号表中存在的name
直接导入到脚本或模块中,而不会把被调模块名引入当前的符号表:
1 | from fibo import fib |
使用*
可以导入模块内定义的,除了以下划线_
开头的所有name
:
1 | from fibo import * |
使用as
可以为引入的模块或模块内名称添加昵称:
1 | import fibo as fb |
6.1.1 以脚本方式执行模块
使用python
命令运行.py
模块时,模块里的代码会被执行,且__name__
会被赋值为"__main__"
。
通过手动在模块末尾添加:
1 | if __name__ == "__main__": |
可以既把这个文件当作脚本又把它当作一个可调入的模块来使用,这段解析命令行(详见sys.argv)的代码只有在当模块是以“main”文件的方式执行的时候才会运行,如果模块是被导入的,这段代码是不运行的。这种方法多用于以脚本的方式运行模块从而执行一些测试套件。
6.1.2 模块搜索路径
当一个名为 spam
的模块被导入的时候,解释器首先寻找具有该名称的内置模块(built-in module)。如果没有找到,解释器将从 sys.path
变量给出的目录列表里寻找名为 spam.py
的文件。sys.path
初始有这些目录地址:
- 包含输入脚本(input script)的目录或当前的目录;
PYTHONPATH
:一个由目录名组成的列表,目录名的语法与shell中的PATH
变量相同;- 与安装相关的(installation-dependent)系统默认值。
包含正在运行脚本的文件目录被放在搜索路径sys.path
的开头处, 在标准库路径之前。这意味着将加载此目录里的脚本,而不是标准库中的同名模块。
6.2 标准模块Standard Module
Python附带了一个标准模块库(library of standard modules),这些模块内置于解释其中,它们提供对那些不属于语言的核心(the core of the language)但仍然内置的(built in)操作的访问以提高效率,或提供对系统调用(system calls)等操作系统原语(operating system primitives)的访问。
其中值得注意的模块sys
,它被内嵌到每一个Python解释器(无论在哪一种操作系统)。
使用标准列表操作(standard list operations)可以对sys.path
进行修改:
1 | import sys |
6.3 dir()函数
内置函数 dir([object])
用于查找已被定义名称的列表,返回的列表按字母表排序。
如果没有实参,dir()
返回当前本地作用域中的名称列表;
如果有实参, dir(object)
返回object对象包含的有效属性列表。
注意:列表中包含所有类型的名称:变量,模块,函数,等等。
如果要获取内置函数和变量的名称,可以使用:
1 | import __builtin__ |
6.4 包Package
包是一个分层次的文件目录结构,它定义了一个由模块及子模块,和子模块下的子模块等组成的Python的应用环境。
简单来说,包就是文件夹,但该文件夹下必须存在__init__.py
文件, 该文件的内容可以为空。__init__.py
用于标识当前文件夹是一个包。
考虑以下目录结构:
1 | sound/ Top-level package |
包的用户可以从包中导入单个模块,
使用下面的语句加载子模块文件/sound/effects/echo.py
,引用时必须使用全名sound.effects.echo
:
1 | import sound.effects.echo |
使用另一种方法导入子模块echo
,可以在没有包前缀的情况下使用它:
1 | from sound.effects import echo |
同样,可以使用from package import item
语句,直接从子模块中导入函数,类或变量:
1 | from sound.effects.echo import echofilter |
6.4.1 从包中导入 *
如果一个包的__init__.py
文件中,定义了一个名为__all__
的列表,它会被视为在遇到from package import *
语句时应该导入的模块名列表。
在发布该包的新版本时,包作者可以决定是否让此列表保持更新。包作者如果认为从他们的包中导入 * 的操作没有必要被使用,也可以决定不支持此列表。
以前文中的目录结构为例,/sound/effects/__init__.py
文件可以包含如下的列表:
1 | __all__ = ["echo", "surround", "reverse"] |
这样,在使用from sound.effects import *
语句时,将导入列表中的三个子模块。
6.4.2 包内引用Intra-package References
当包内的模块想要引用本包内的其他模块时,可以使用绝对引用(absolute imports)和相对引用(relative imports)。
以前文中目录结构为例,如果sound.filters.equalizer
想要使用sound.effects.echo
模块,可以使用绝对引用:
1 | from sound.effects import echo |
如果sound.effects.surround
想要使用包内引用,可以进行下面的相对引用:
1 | #引用整个sound.formats子包 |
6.4.3 多个目录Multiple Directories中的包
包支持另一个特殊属性,__path__
。它被初始化为一个列表,其中包含在执行该文件中的代码之前,保存包文件__init__.py
的目录名称。
这个变量可以修改;这样做会影响将来对包中包含的模块和子包的搜索。