[python3]模块
模块
模块:是一个包含PYTHON定义和语句的文件,以.py结尾的文件名就是模块名。
在模块内模块的名字(作为字符串)保存在全局变量__name__中。
例如,我们编写一个名为fibo.py的文件,里面有两个函数:fib(n)和fib2(n)。在python解释器中使用import fibo可以导入这个模块。使用模块名可以访问这两个函数:fibo.fib(1000)。fibo.__name__保存的就是这个模块的名字。
每个模块都有自己的符号表,作为自己的全局符号表,每个模块有也有自己的全局变量。所以模块的作者不用担心自己的全局变量会和其它模块冲突。如果想访问这些变量,可以使用modname.itemname的这种形式访问。
import的一种变形,可以直接把函数直接导入到另一个模块的符号表中:
>>> from fibo import fib, fib2 >>> fib(500) 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
还有一种导入所有名字的方法:
from fibo import *
这种方法导入了除了以下划线(_)开头的所有名字。很多情况不使用这种方法,因为可能导入一些和现有文件冲突的名字。
如果导入的名字后面有一个as关键字,那么as后的名字被直接绑定到这个导入的模块上,如:
import fibo as fib
fib.fib(500)
这个关键子也可以用于带有from形式的版本,如:
from fibo import fib as fibonacci
fibonacci(500)
以脚本的方式执行一个模块
python fibo.py <arguments>
模块中的代码将会被执行,就像导入了该模块一样,而且__name__被设置成”__main__”。这意味着要在代码底部添加:
if __name__ == "__main__": import sys fib(int(sys.argv[1]))
代码。这可以让模块像被从一个叫main的文件中导入了一样。这种方法通常用于测试模块。
模块的搜索目录
当一个被命名为spam的模块被导入时,解释器会先在内建模块中查找这个名字。如果没有找到,之后会在sys.path这个列表中查找。sys.path在如下位置被初始化:
- 包含在输入脚本(如果没有指定文件时,是当前文件夹)
- PYTHONPATH
- 依赖于安装时的默认值
在初始化后,python程序能修改sys.path。
包
包:是一种python模块名字空间的组织方法,使用“点分模块名”的方法。例如:一个模块的名字A.B,代表在一个名为A的包中包含了一个名为B的子模块。(python中的‘包’就是目录)
假设你想设计一个模块的集合,用于处理声音文件和声音数据。有很多不同的声音格式,所以你可能需要去创建和维护一个不断增加的模块集合,用于在不同格式之间转换。还有很多你想在声音数据上执行的不同的操作,所以这个模块你可能会一直写下去,没有终点。这里有一个可能的结构:
sound/ Top-level package __init__.py Initialize the sound package formats/ Subpackage for file format conversions __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... effects/ Subpackage for sound effects __init__.py echo.py surround.py reverse.py ... filters/ Subpackage for filters __init__.py equalizer.py vocoder.py karaoke.py ...
当导入这个包,python会在sys.path中查找’包’的子目录。
__init__.py文件要求python将文件夹做为包对待。这么作可以防止文件名使用了一个“常用名”,如“string”。从而隐藏了一个有效的模块名。在最简单的情况下,__init__.py仅仅是一个空文件,但是它也能为’包’执行初始代码或设置__all__变量。
包的用户能单独导入‘包’中的一个模块,例如:
import sound.effects.echo
这加载了子模块sound.effects.echo
。必须使用完整的名字进行索引:
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
或者可以使用另一种方法导入:
from sound.effects import echo
这同样可以导入模块,而且它不用‘包’的路径前缀,可以使用模块+函数的形式:
echo.echofilter(input,output, delay=0.7, atten=4)
再或者直接导入要使用的函数或变量:
from sound.effects.echo import echofilter
这样就可以直接调用该函数:
echofilter(input,output, delay=0.7, atten=4)
注意:当使用from package import item
这种形式时,item可以是包内的模块(子包)或者是在模块中定义的一些名字,如:一个函数、类或变量。import
语句先测试item是否在’包’中;如果不在,假定它是一个模块并试图加载它。如果没有找到会抛出一个ImportError
异常。
当使用import item.subitem.subsubitem
这种形式时,除了最后一项,其它必须是’包’;最后一项可以是模块或者是包,但是,不能是一个类、函数或定义的变量。
dir()函数
内建的dir()函数用于找出定义在包中的所有名字,如:
>>> import fibo, sys >>> dir(fibo) ['__name__', 'fib', 'fib2']
从包中导入*
如果用户输入from sound.effects import *
,将会导入‘包’中的有的子模块,不过这可能会耗时很长,而且会有一些不想要的副作用。
解决的办法是为‘包’的作者提供一个明显的包序号。import
语句使用如下导入顺序:如果包的__init__.py
定义了一个名为__all__
的列表(PS:__init__.py中可能包含了__all__=[“echo”, “surround”, “reverse”]的语句。),当遇到from package import *
时,它处理这个将要被导入的模块名列表。如果__all__
没被定义,那么from sound.effects import *
语句不会将sound.effects
的所有子模块导入当前的名字空间;它能只保证包sound.effects已经被导入。考虑下面代码:
import sound.effects.echo import sound.effects.surround from sound.effects import * 接下来来可以执行诸如echo.echofilter(input, output, delay=0.7, atten=4)这样的函数。
当执行from...import
语句时,定义在sound.effects包中的echo和surround模块被导入到当前的名字空间中。
虽然某些模块仅被设计用来导入,但是使用import *
仍然不被推荐。
使用from PACKAGE import SPECIFIC_SUBMODULE
这种形式是被推荐使用的,除非要导入两个包的同名子模块。
包内索引
当包具有多层结构时(就像例子中的sound包一样),可以使用绝对导入,索引到子模块。例如,如果模块sound.filters.vocoder需要在sound.effects包中使用echo模块,可以使用from sound.effects import echo
导入。
也可以使用相对导入,from module import name
这种形式的导入语句。这些导入使用“引导点”指示当前目包和父级包。在surround模块中的例子:
from . import echo from .. import formats from ..filters import equalizer
注意:相对导入是基于当前模块的名字的。因为主模块的名字一直是“__main__”,其它模块想使用像main模块一样的python应用程序,就必须使用绝对导入。
在多个目录中的包
包支持很多的特殊属性,__path__。在代码执行以前它被初始化成为一个列表,包含了拥有包的__init__.py文件的目录的名字。这个变量可以修改;如果这么做了会影像模块和包的搜索。