Python学习从0开始——006模块
一、定义
Python 把各种定义存入一个文件,在脚本或解释器的交互式实例中使用。这个文件就是 模块 ;模块中的定义可以 导入 到其他模块或 主 模块(在顶层和计算器模式下,执行脚本中可访问的变量集)。
模块是包含 Python 定义和语句的文件。其文件名是模块名加后缀名 .py 。在模块内部,通过全局变量 name 可以获取模块名(即字符串)。
#fibo.py
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
#终端
>>> import fibo
>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
>>> fib = fibo.fib
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
二、模块详解
2.1引入
#其它引入方式:
#模块名后使用 as 时,直接把 as 后的名称与导入模块绑定
>>> import fibo as fib
#与 import fibo 一样,唯一的区别是导入的名称是 fib
>>> fib.__name__
'fibo'
#把 as 后的名称与导入函数绑定
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
2.2脚本方式运行
python fibo.py <arguments>
这项操作将执行模块里的代码,和导入模块一样,但会把 name 赋值为 “main”。 也就是把下列代码添加到模块末尾:
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
这个文件既能被用作脚本,又能被用作一个可供导入的模块,因为解析命令行参数的那两行代码只有在模块作为“main”文件执行时才会运行,当这个模块被导入到其它模块时,那两行代码不运行。常用于为模块提供一个便捷的用户接口,或用于测试(把模块作为执行测试套件的脚本运行)。
#fibo.py
import argparse
def fib(n):
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
def main():
#对这个命令行工具的描述,通常会在用户请求帮助时显示
parser = argparse.ArgumentParser(description='Print Fibonacci series up to n.')
#使用 add_argument 方法添加一个命令行参数。
#'n' 是这个参数的名字,用户在命令行中提供这个参数的值时不需要使用任何前缀(如 -- 或 -)。
#type=int 指定参数是一个整数。如果用户提供了一个非整数值,argparse 会抛出一个错误。
parser.add_argument('n', type=int, help='an integer for the upper limit of the Fibonacci series')
args = parser.parse_args()
fib_sequence = fib(args.n)
print(fib_sequence)
if __name__ == "__main__":
main()
#终端
~/Python python fibo.py -h
usage: fibo.py [-h] n
Print Fibonacci series up to n.
positional arguments:
n an integer for the upper limit of the Fibonacci series
optional arguments:
-h, --help show this help message and exit
~/Python python fibo.py 1000
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
2.3模块搜索路径
导入一个名为 spam 的模块时,解释器首先会搜索具有该名称的内置模块。 这些模块的名称在 sys.builtin_module_names 中列出。 如果未找到,它将在变量 sys.path 所给出的目录列表中搜索名为 spam.py 的文件。 sys.path 是从这些位置初始化的:
被命令行直接运行的脚本所在的目录(或未指定文件时的当前目录)。
PYTHONPATH (目录列表,与 shell 变量 PATH 的语法一样)。
依赖于安装的默认值(按照惯例包括一个 site-packages 目录,由 site 模块处理)。
2.4编译版本缓存
为了快速加载模块,Python 把模块的编译版本缓存在 pycache 目录中,文件名为 module.version.pyc,version 对编译文件格式进行编码,一般是 Python 的版本号。例如,CPython 的 3.3 发行版中,spam.py 的编译版本缓存为 pycache/spam.cpython-33.pyc。这种命名惯例让不同 Python 版本编译的模块可以共存。
Python 对比编译版与源码的修改日期,查看编译版是否已过期,是否要重新编译。此进程完全是自动的。此外,编译模块与平台无关,因此,可在不同架构的系统之间共享相同的库。
Python 在两种情况下不检查缓存。一,从命令行直接载入的模块,每次都会重新编译,且不储存编译结果;二,没有源模块,就不会检查缓存。为了让一个库能以隐藏源代码的形式分发(通过将所有源代码变为编译后的版本),编译后的模块必须放在源目录而非缓存目录中,并且源目录绝不能包含同名的未编译的源模块。
三、标准模块
Python 自带一个标准模块的库, 一些模块是内嵌到编译器里面的, 它们给一些虽并非语言核心但却内嵌的操作提供接口,要么是为了效率,要么是给操作系统基础操作例如系统调入提供接口。 这些模块集是一个配置选项, 并且还依赖于底层的操作系统。 例如,winreg 模块只在 Windows 系统上提供。一个特别值得注意的模块 sys,它被内嵌到每一个 Python 编译器中。
四、dir() 函数
内置函数 dir() 用于查找模块定义的名称。返回结果是经过排序的字符串列表:
没有参数时,dir() 列出当前已定义的名称,注意它列出所有类型的名称:变量,模块,函数,……,但是不会列出内置函数和变量的名称。
五、包
5.1导入
包是通过使用“带点号模块名”来构造 Python 模块命名空间的一种方式。 例如,模块名 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
...
导入包时,Python 搜索 sys.path 里的目录,查找包的子目录。
需要有’_init_.py ‘文件才能让 Python 将包含该文件的目录当作包来处理(除非使用 namespace package,这是一个相对高级的特性)。 这可以防止重名的目录如 string 在无意中屏蔽后继出现在模块搜索路径中的有效模块。 在最简单的情况下,’_init_.py '可以只是一个空文件,但它也可以执行包的初始化代码或设置 '_all_ '变量。
#单个模块导入
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;如果未在包中定义,则假定 item 是模块,并尝试加载。如果找不到 item,则触发 ImportError 异常。
相反,使用 import item.subitem.subsubitem 句法时,除最后一项外,每个 item 都必须是包;最后一项可以是模块或包,但不能是上一项中定义的类、函数或变量。
5.2从包中导入 *
如果包的 ‘_init_.py ‘代码定义了列表’_all_’,运行 from package import * 时,它就是被导入的模块名列表。发布包的新版本时,包的作者应更新此列表。如果包的作者认为没有必要在包中执行导入 * 操作,也可以不提供此列表。
# sound/effects/__init__.py
__all__ = ["echo", "surround", "reverse"]
但是以下这种形式,子模块会被本地定义的 reverse 函数遮挡
# sound/effects/__init__.py
__all__ = [
"echo",
"surround",
"reverse",
]
def reverse(msg: str):
return msg[::-1]
如果没有定义 ‘_all_’,from sound.effects import * 语句 不会把包 sound.effects 中的所有子模块都导入到当前命名空间;它只是确保包 sound.effects 已被导入(可能还会运行 '_init_.py '中的所有初始化代码),然后再导入包中定义的所有名称。 这包括由 '_init_.py '定义的所有名称(以及显式加载的子模块)。 它还包括先前 import 语句显式加载的包里的任何子模块。
所以,生产不推荐*。
5.3 相对导入
相对导入基于当前模块名。因为主模块名永远是 “_main_” ,所以如果计划将一个模块用作 Python 应用程序的主模块,那么该模块内的导入语句必须始终使用绝对导入。
from . import echo
from .. import formats
from ..filters import equalizer
5.4多目录中的包
包还支持一个特殊属性 ‘_path_’ 。在包的 ‘_init_.py’中的代码被执行前,该属性被初始化为一个只含一项的列表,该项是一个字符串,是’_init_.py’所在目录的名称。可以修改此变量;这样做会改变在此包中搜索模块和子包的方式。