定义:

模块是包含 Python 定义和语句的文件。其文件名是模块名加后缀名 .py 。在模块内部,通过全局变量 __name__ 可以获取模块名(即字符串)。

导入模块:

1
import name(模块的真实名字)

本质将模块名称添加到namespeac而非把定义的函数添加进去

6.1 模块详解:

模块包含可执行语句及函数定义。这些语句用于初始化模块,且仅在 import 语句 第一次 遇到模块名时执行。 每个模块都有它自己的私有符号表,该表被定义在该模块里的所有函数当作全局符号表使用。 您可以使用与引用模块函数相同的语法去访问一个模块的全局变量,即 modname.itemname

导入其他模块:import

被放置于一个模块的最高层级,则被导入的模块名称会被添加到该模块的全局命名空间。 import的变式1:将来自某个模块的名称直接导入到导入方的命名空间里面

1
2
3
from fibo import fib, fib2
fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

变式2:导入模块内定义的所有名称(不包含以_开头的名称)

1
2
3
from fibo import *
fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

不建议:可能会覆盖已经定义的名称

变式3:模块名后接as

1
2
import fibo from fib
fib.fib(500)

或者变式1,3结合

1
2
3
from fibo import fib as fibonacci
fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

备注

每次解释器会话只导入一次模块,若模块内容更改,需要重启解释器 如仅交互测试一个模块,可以使用importlib.reload(),例如 import importlib; importlib.reload(modulename)。

6.1.1.以脚本方式执行模块

最常见命令:

1
python fibo.py <arguments>(这个参数的必须的)

导入模块的代码,但是会将_name_命名为"main"(这里前面和后面都有一个__,但是因为md原因导致没有了)

例如

1
2
python fibo.py 50
0 1 1 2 3 5 8 13 21 34

相当于

1
2
3
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

该文件既可作为模块又可以作为脚本 而像下面这种导入其他模块则不会

1
import fibo 

用于为模块提供一个便捷的用户接口,或用于测试

6.1.2.模块的搜索路径

当导入一个名为 spam 的模块时,解释器首先会搜索具有该名称的内置模块。 这些模块的名称在 sys.builtin_module_names 中列出。 如果未找到,它将在变量 sys.path 所给出的目录列表中搜索名为 spam.py 的文件。 sys.path 是从这些位置初始化的:

  • 被命令行直接运行的脚本所在的目录(或未指定文件时的当前目录)。
  • PYTHONPATH (目录列表,与 shell 变量 PATH 的语法一样)。
  • 依赖于安装的默认值(按照惯例包括一个 site-packages 目录,由 site 模块处理)。

更多细节请参阅 sys.path 模块搜索路径的初始化。

备注

在支持符号链接的文件系统中,“被命令行直接运行的脚本所在的目录”是符号链接最终指向的目录。换句话说,符号链接所在的目录并 没有 被添加至模块搜索路径。

初始化后,Python 程序可以更改 sys.path。脚本所在的目录先于标准库所在的路径被搜索。这意味着,脚本所在的目录如果有和标准库同名的文件,那么加载的是该目录里的,而不是标准库的。这一般是一个错误,除非这样的替换是你有意为之。详见 标准模块。

6.1.3.”已编译的“Python文件

模块的编译版本存放在–pycache__目录中,文件名为module.version.pyc,

version:对编译文件格式进行编码,一般是版本号 可以让不同版本的Python编译的模块可以共存 例子:CPython 的 3.3 发行版中,spam.py 的编译版本缓存为 __pycache__/spam.cpython-33.pyc

Python会自动检查编译版本和源码的修改日期来查看编译版是否过期,是否需要重新编译 编译模块与平台无关 Python不检查缓存的两种情况 1.从命令行直接载入的模块:每次重新编译且不存储结果 2.没有源模块 隐藏源代码:将所有源代码编程编译之后的版本,并储存在源目录而非缓存目录中)

ps: .pyc的读取未必比.py快,只是加载速度更快 compileall 模块可以为一个目录下的所有模块创建 .pyc 文件。

6.2.标准模块

Python自带的,在Python的库参考中另外描述 这些模块集是一个配置选项,并且还依赖于底层的操作系统 例如winreg只在WIndows系统上提供 但是sys模块内嵌到每一个Python解释器,sys.psq和sys.ps2变量定义了一些字符,可以作为主提示符和辅助提示符 变量的sys.path:字符串列表,用于确定解释器的模块搜索路径 从环境变量PYTHONPATH提取默认路径进行初始化,若未设置PYTHONPATH,则使用内置的默认路径 可以通过标准列表操作修改该变量

1
2
import sys
sys.path.append('/ufs/guido/lib/python')

6.3.dir()函数

查找模块定义的名称,返回值:经过排序的字符串列表 没有参数时: 返回值:当前已经定义的名称 包括:变量,模块,函数…… 但是不会列出内置函数和变量的名称 这些内容的定义在标准模块 builtins 中:

6.4. 包

通过”带点号模块名“来狗仔Python模块命名空间的一种方式 可以让不同包的作者不用担心彼此的全局变量名,比如模块名冲突

导入包时,Python 搜索 sys.path 里的目录,查找包的子目录。

需要有 __init__.py 文件才能让 Python 将包含该文件的目录当作包来处理(除非使用 namespace package,这是一个相对高级的特性)。 这可以防止重名的目录如 string 在无意中屏蔽后继出现在模块搜索路径中的有效模块。 在最简单的情况下,__init__.py 可以只是一个空文件,但它也可以执行包的初始化代码或设置 __all__ 变量,这将在稍后详细描述。

还可以从包中导入单个模块,例如:

1
import sound.effects.echo

这将加载子模块 sound.effects.echo。 它必须通过其全名来引用。

1
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

另一种导入子模块的方法是 :

1
from sound.effects import echo

这也会加载子模块 echo,并使其不必加包前缀,因此可按如下方式使用:

1
echo.echofilter(input, output, delay=0.7, atten=4)

Import 语句的另一种变体是直接导入所需的函数或变量:

1
from sound.effects.echo import echofilter

同样,这将加载子模块 echo,但这使其函数 echofilter() 直接可用:

1
echofilter(input, output, delay=0.7, atten=4)

注意,使用 from package import item 时,item 可以是包的子模块(或子包),也可以是包中定义的函数、类或变量等其他名称。import 语句首先测试包中是否定义了 item;如果未在包中定义,则假定 item 是模块,并尝试加载。如果找不到 item,则触发 ImportError 异常。

相反,使用 import item.subitem.subsubitem 句法时,除最后一项外,每个 item 都必须是包;最后一项可以是模块或包,但不能是上一项中定义的类、函数或变量。

6.4.1. 从包中导入*

提供包的显式索引

导入在init.py 代码定义了列表 all 发布新版本时,应更新该列表 例如:sound/effects/__init__.py 文件可以包含以下代码:

1
__all__ = ["echo", "surround", "reverse"]

这意味着 from sound.effects import * 将导入 sound.effects 包的三个命名子模块。请注意子模块可能会受到本地定义名称的影响。 例如,如果你在 sound/effects/__init__.py 文件中添加了一个 reverse 函数,from sound.effects import * 将只导入 echo 和 surround 这两个子模块,但 不会 导入 reverse 子模块,因为它被本地定义的 reverse 函数所遮挡:

1
2
3
4
5
6
7
8
__all__ = [
    "echo",      # 指向 'echo.py' 文件
    "surround",  # 指向 'surround.py' 文件
    "reverse",   # !!! 现在指向 'reverse' 函数 !!!
]

def reverse(msg: str):  # <-- 此名称将覆盖 'reverse.py' 子模块
    return msg[::-1]    #     针对 'from sound.effects import *' 的情况

没有定义____all____:

有点没懂

6.4.2. 相对导入

使用前导符号.来完成 一般用于子模块