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]

Name Password4deL ;) :( X-( B-)