status |
校对 |
|
完成度100% |
PCS100 import ~ 模块及包的使用
模块(modules)
模块(modules) 其实,就是普通的 Python 脚本文件,一般命名是模块名称加上.py后缀; 这类Python 脚本文件,主要供其他程序将其引入,以便利用其提供的操作/功能/数据,Python标准库全部是以模块方式提供的.
例如:fibo模块(fibo.py)是一个实现Fibonacci功能的模块。
1 #coding:utf-8
2 # Fibonacci数列模块
3 # 输出所有小于n的Fibonacci数
4 def fib(n):
5 a, b = 0, 1
6 if n == 1:
7 print 1
8 while b < n:
9 print b,
10 a, b = b, a+b
11
12 # 返回所有小于n的Fibonacci数
13 def fib2(n):
14 result = []
15 a, b = 0, 1
16 while b < n:
17 result.append(b)
18 a, b = b, a+b
19 return result
在Python解释器中,使用import fibo语句导入fibo模块,使用fibo.fib(1000)来调用函数,也可以用fib = fibo.fib将模块函数赋值到本地函数。
>>> import fibo >>> fibo.fib(1000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 >>> fibo.fib2(100) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> fibo.__name__ 'fibo' >>> fib = fibo.fib >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 >>> from fibo import fib,fib2 >>> fib(1000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 >>> fib2(100) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
正如上述代码中,不仅可以通过import来实现模块中函数的使用,还可以通过from ...import方式来导入模块中函数。
包(package)
包是采用"."组织模块命名空间方式,比如模块名称A.B表示是表示A 包中的模块B。这种命名空间的组织方式能够避免不同模块命名的冲突。例如:假设需要设计一组模块来处理声音文件和声音数据,就是如何组织一个包。由于存在多个不同声音格式的文件,需要一个随时能增加新模块的包来处理新增的声音格式。另外还需要对声音进行各种不同处理(例如混声、加回音、加入平衡、加入人工音效等),所以还需要另写一些模块来作这些处理。比如以下组织结构:
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 ...
__init__.py是必须的,它帮助Python将该目录识别为包。在最简单的例子中,__init__.py是一个空文件。当然也可以让__init__.py做一些包的初始化动作或是设定一些变量,如__all__变量。
import
直接导入包中的一个模块或导入模块中定义的一个函数(如模块fibo的函数fib)来使用,比如:
1 import Sound.Effects.echo
2
3 # 使用这个模块,必须使用完整的名字来调用
4 Sound.Effects.echo.echofilter(input, output, delay=0.7, atten=4)
5
6 # 另一种替代方法
7 from Sound.Effects import echo
8 # 不同的是,不需要包前缀
9 echo.echofilter(input, output, delay=0.7, atten=4)
10
11 # 另一种直接导入你需要的函数和变量的方法
12 from Sound.Effects.echo import echofilter
13 # 其使用方法为
14 echofilter(input, output, delay=0.7, atten=4)
from ... import
另一种写法,from Sound.Effects import * 会怎么样? 理想情况下,可能期望会搜寻整个包目录,然后搜寻所有的模块并且一一导入。但是,在Mac以及Windows平台下,文件的名称大小写不一致,所以无法保证所有的模块都会被导入。所以唯一解决的方法就是包的作者提供一个明确索引给使用包的人。如果遵守该习惯的话,当使用包的人在导入的时候使用from Sound.Effects import *,就会查找包中的__init__.py中的__all__这个list变量,该变量就包含所有应该被导入进来的模块名称。身为包的作者有责任维护更新__init__.py。以Sounds/Effects/__init__.py为例:
1 __all__ = ["echo", "surround", "reverse"]
表示当from Sound.Effects import * 时会import 这三个module。如果没有定义all,from Sound.Effects import *不会保证所有的子模块被导入。所以要么通过init.py,要么显式地import以保证子模块被导入。如下:
1 import Sound.Effects.echo
2 import Sound.Effects.surround
3 from Sound.Effects import *
值得注意的是import *不被鼓励,因为这样会降低程序的可读性,虽然有时会减少一些打字,而且有些模块在设计时故意只让某些特别的名称可以被使用。使用from Package import specific_submodule没有任何不对,但如果你的模块名称和其他名称冲突,就得使用as为冲突模块取个别名:
1 from Package import specific_submodule as specific_submodule_alias
搜寻路径
当你导入fibo时,Python解释器先在当前目录下搜寻fibo.py文件,如果没有找到,会依次在$PYTHONPATH指示的所有路径中搜寻。$PYTHONPATH的设定方法与$PATH是一样的,即多个目录路径的字符串。事实上,模块的搜寻路径是依照sys.path变量(多个路径组成的list变量)。当Python解释器启动时,会将当前目录、$PYTHONPATH、以及按照安装时设定的一些目录加入到sys.path变量中,所以可以修改这些参数来控制搜寻模块的路径。 比如:
1 import sys
2 # 将fibo.py的路径添加到sys.path
3 sys.path.append('/home/shengyan/workspace/')
4
5 from pcs import fibo
::Lizzie [2008/06/16 21:24:00]