📄 第六章 模块 suzhe (转).txt
字号:
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__name__', 'argv', 'builtin_module_names', 'copyright', 'exit',
'maxint', 'modules', 'path', 'ps1', 'ps2', 'setprofile', 'settrace',
'stderr', 'stdin', 'stdout', 'version']
没有自变量时,dir()列出当前定义的名字。
>>> a = [1, 2, 3, 4, 5]
>>> import fibo, sys
>>> fib = fibo.fib
>>> dir()
['__name__', 'a', 'fib', 'fibo', 'sys']
注意dir()列出了所有各类名字:变量名、模块名、函数名,等等。dir()不会列出内置
函数、变量的名字。要想列出内置名字的话需要使用标准模块__builtin__:
>>> import __builtin__
>>> dir(__builtin__)
['AccessError', 'AttributeError', 'ConflictError', 'EOFError', 'IOError',
'ImportError', 'IndexError', 'KeyError', 'KeyboardInterrupt',
'MemoryError', 'NameError', 'None', 'OverflowError', 'RuntimeError',
'SyntaxError', 'SystemError', 'SystemExit', 'TypeError', 'ValueError',
'ZeroDivisionError', '__name__', 'abs', 'apply', 'chr', 'cmp', 'coerce',
'compile', 'dir', 'divmod', 'eval', 'execfile', 'filter', 'float',
'getattr', 'hasattr', 'hash', 'hex', 'id', 'input', 'int', 'len', 'long',
'map', 'max', 'min', 'oct', 'open', 'ord', 'pow', 'range', 'raw_input',
'reduce', 'reload', 'repr', 'round', 'setattr', 'str', 'type', 'xrange']
6.4 包
Python中可以用“包”来组织Python的模块名字空间,名字引用时可以用“带点的模块
名。例如,模块名A.B代表包“A”内名为“B”的子模块。正如使用模块可以使不同模块
的作者不用顾虑彼此的全局变量名会冲突,使用带点的模块名可以使多模块包如NumPy和
PIL的作者不需要担心彼此的模块名会冲突。
假设你有一系列处理声音文件和声音数据的模块(称为一个“包”)。有许多种不同的
声音文件格式(通常用扩展名来识别,如“wav”,“.aiff”,“.au”),所以你可能
需要制作并维护一组不断增加的模块来处理不同文件格式的转换。你还可能需要对声音
数据进行许多不同的操作(如混音、回响、均衡、产生模拟立体声效果),所以你还需
要不断增加模块来执行这些操作。一下是你的程序包的可能的结构(用一个分层文件系
统表示):
Sound/ 顶层包
__init__.py 初始化音响包
Formats/ 用于文件格式转换的子程序包
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
Effects/ 用于音响效果的子程序包
__init__.py
echo.py
surround.py
reverse.py
...
Filters/ 用于滤波的子程序包
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
包目录中的“__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,但调用时不需写包前缀,所以可以用如:
echo.echofilter(input, output, delay=0.7, atten=4)
另外一种写法是直接导入所需的函数或变量:
from Sound.Effects.echo import echofilter
这一次同样是调入了子模块echo,但是使其函数echofilter直接可用:
echofilter(input, output, delay=0.7, atten=4)
注意使用“from 包 import 项”这样的格式时,导入的项可以是包的一个子模块(或子
包),也可以是包内定义的其它名字如函数、类、变量。导入语句首先查找包内是否定
义了所需的项,如果没有则假设它是一个模块然后调入。如果找不到,结果引起Import
Error。
相反的,当使用“import item.subitem.subsubitem”这样的格式时,除最后一个外其
它各项都应该是包,最后一项可以是包也可以是模块,不允许是前面一项内部定义的类
、函数或变量。
6.4.1 从包中导入*
现在,如果用户写“from Sound.Effects import *”会发生什么情况?理想情况下我们
希望这应该扫描文件系统,找到所有包内的子模块并把它们都导入进来。不幸的是这种
操作在Mac和Windows平台上不能准确实现,这两种操作系统对文件名的大小写没有准确
信息。在这些平台上,不知道名为“ECHO.PY”的文件会作为模块echo、Echo还是ECHO被
导入。(例如,Windows 95在显示文件名时总是讨厌地把第一个字母大写)。DOS的8+
3文件名限制更是对长模块名造成了有趣的困难。
这个问题的唯一解决办法是由模块作者显式地提供包的索引。引入*的import语句遵循如
下规定:如果包的“__init__.py”文件定义了一个名为“__all__”的列表,这个列表
就作为从包内导入*时要导入的所有模块的名字表。因此当包的新版本发布时需要包的作
者确保这个列表是最新的。包的作者如果认为不需要导入*的话也可以不支持这种用法。
例如,文件Sounds/Effects/__init__.py 可以包含如下代码:
__all__ = ["echo", "surround", "reverse"]
这意味着from Sound.Effects import *将从Sound包中导入指定的三个子包。
如果没有定义__all__,则from Sound.Effects import *语句不会导入Sound.Effects包
中的所有子模块;此语句只能保证Sound.Effects被导入(可能是执行其初始化代码“_
_init__.py ”)并导入包中直接定义的名字。这包括由“__init__.py”定义的任何名
字和显式导入的子模块名。这也包括模块中已经在前面用import显式地导入的子模块,
例如:
import Sound.Effects.echo
import Sound.Effects.surround
from Sound.Effects import *
在这个例子中,echo和surround模块被导入当前名字空间,因为它们在执行from...imp
ort 语句时已定义(在定义了__all__的情况下这一点也是成立的)。
注意用户应尽量避免使用从模块或包中导入*的做法,因为这样经常导致可读性差的代码
。尽管如此,在交互运行时可以用导入*的办法节省敲键次数,而且有些模块在设计时就
考虑到了这个问题,它们只输出遵循某种约定的名字。注意,from 包 import 特定子模
块的用法并没有错,实际上这还是我们推荐的用法,除非程序还需要用到来自其它包的
同名的子模块。
6.4.2 包内部引用
子模块常常需要彼此引用。例如,模块surround可能要用到模块echo。事实上,这样的
引用十分常见,所以import语句首先从子模块的所在包中寻找要导入的子模块才在标准
模块搜索路径查找。所以,模块surround只要写import echo或from echo import echo
filter。如果在包含本模块的包中没有找到要导入的模块,import语句将去寻找指定名
字的顶级模块。
当包组织成子包时(比如例中的Sound包),没有一种简单的办法可以引用兄弟包中的子
模块――必须使用子模块的全名。例如,如果模块Sound.Filters.vocoder要引用Sound
.Effects 包中的echo模块,它可以用Sound.Effects import echo。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -