Python 学习笔记 - 第四天
模块是包括 Python 定义和声明的文件.
后缀 .py
. 模块名可以由全局变量 __name__
获取.
fibo.py 示例:
# Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while b < n:
print(b, end=' ')
a, b = b, a+b
print()
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
return result
导入模块:
>>> 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
1.深入模块
使用 import
语句直接导入模块的某些定义:
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
这种方式不会导入模块名. fibo
没有定义.
导入所有定义:
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
这种方式将会导入所有除了以下划线开头 _
的命名. (不推荐)
1.1.作为脚本执行模块
使用这种方式运行 python 模块, 会直接执行模块中的代码:
python fibo.py <arguments>
此时, 模块名 __name__
将被设置成 "__main__"
.
如果在模块中加入代码:
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
执行脚本:
$ python fibo.py 50
1 1 2 3 5 8 13 21 34
如果是直接导入该模块, 是不会执行这段代码的:
>>> import fibo
>>>
1.2.模块的搜索路径
搜索顺序:
当前目录
环境变量 PYTHONPATH
中的目录列表中搜索
Python 默认安装路径中搜索
1.3."编译的" Python 文件
为了加快加载模块的速度, Python 会在 __pycache_
目录下缓存每个模块编译后的版本.
module.version.pyc
例如: CPython 3.3 版本中, spam.py 编译后的版本: __pycache__/spam.cpython-33.pyc
.
高级技巧:
为了减少一个编译模块的大小, 可以在 Python 命令行中使用 -O
或者 -OO
. -O
删除所有断言语句, -OO
删除断言语句和 doc
字符串. 后缀为 .pyo
.pyc
和 .pyo
只是在加载模块的时候更快一些. 不会影响运行速度.
compileall 模块可以为指定目录中的所有模块创建 .pyc
或 .pyo
(使用-O参数) 文件.
2.标准模块
Python 带有一个标准模块库, 并发布有独立的文档, 名为 Python 库参考手册.
示例: 变量 sys.ps1
和 sys.ps2
定义了主题师傅和辅助提示符:
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>
这两个变量只在解释器的交互模式下才有意义.
操作修改 sys.path
:
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')
3.dir() 函数
内置函数 dir()
获取模块中的所有模块定义:
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__',
'__package__', '__stderr__', '__stdin__', '__stdout__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_getframe',
'_home', '_mercurial', '_xoptions', 'abiflags', 'api_version', 'argv',
'base_exec_prefix', 'base_prefix', 'builtin_module_names', 'byteorder',
'call_tracing', 'callstats', 'copyright', 'displayhook',
'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix',
'executable', 'exit', 'flags', 'float_info', 'float_repr_style',
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencoding', 'getobjects', 'getprofile', 'getrecursionlimit',
'getrefcount', 'getsizeof', 'getswitchinterval', 'gettotalrefcount',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path',
'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1',
'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit',
'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdout',
'thread_info', 'version', 'version_info', 'warnoptions']
不传参数时, 返回当前定义的命名:
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__doc__', '__file__', '__name__', 'a', 'fib', 'fibo', 'sys']
dir()
不会列出内置函数和变量名.
但是可以通过列出标准模块 builtins
来查看:
>>> import builtins
>>> dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError',
'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
'__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
'zip']
4.包
示例一个处理声音的模块集:
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
文件.
可以每次只导入包里的特定模块:
import 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.subitem.subsubitem
时, 最后的子项可以是包/模块, 但不能是前一个子项的类/函数/变量.
4.1.从 * 导入包.
如果包中的 __init__.py
中定义了一个名为 __all__
的列表, 就会按照列表中给出的模块名进行导入.
示例: 在 sound/effects/__init__.py
文件中:
__all__ = ["echo", "surround", "reverse"]
当使用 from sound.effects import *
导入这个包时, 会从 sound 包中导入这三个子模块.
如果没定义 __all__
, 将不会导入所有子模块.
但是, 不推荐使用 * 的方式去导入模块命名!!!
4.2.包内引用
如果包内使用了子包结构, 可以按绝对位置从相邻的包中引入子模块.
例如: 如果 sound.filters.vocoder
包需要使用 sound.effects
包中的 echo
模块, 它可以 from sound.Effects import echo
.
也可以使用点号标明关联导入当前包和上级包.
示例:
from . import echo
from .. import formats
from ..filters import equalizer
4.3.多重目录中的包
包支持一个更为特殊的特性, __path__
. 在包的 __init__.py
文件代码执行之前, 该变量初始化一个目录名列表. 该变量可以修改, 它作用于包中的子包和模块的搜索功能.
这个功能可以用于扩展包中的模块集, 不过它不常用.