至此,你掌握了Python语言的大部分基础知识。 Python不仅语言核心非常强大,还提供了其他工具以供使用。标准安装包含一组称为标准库(standard library)的模块,你见过其中的一些(如math和cmath),但还有其他很多。本章简要介绍模块的工作原理以及如何探索模块以获悉其提供的功能,然后概述标准库,重点是几个很有用的模块。
10.1 模块
你已知道如何创建和执行程序(或脚本),还知道如何使用import将函数从外部模块导入到程序中。
>>> import math
>>> math.sin(0)
0.0
下面来看看如何编写自己的模块。
10.1.1 模块就是程序
任何Python程序都可作为模块导入。假设你编写了代码清单10-1所示的程序,并将其保存在文件hello.py中,这个文件的名称(不包括扩展名.py)将成为模块的名称。
代码清单10-1 一个简单的模块
# hello.py
print("Hello, world!")
文件的存储位置也很重要,将在下一节详细介绍。这里假设这个文件存储在目录C:\python(Windows)或~/python(UNIX/macOS)中。
要告诉解释器去哪里查找这个模块,可执行如下命令(以Windows目录为例):
>>> import sys
>>> sys.path.append('C:/python')
提示 在UNIX中,不能直接将字符串'~/python'附加到sys.path末尾,而必须使用完整的路径(如'/home/yourusername/python')。如果你要自动创建完整的路径,可使用sys.path.expanduser('~/python')。
这告诉解释器,除了通常将查找的位置外,还应到目录C:\python中去查找这个模块。这样做后,就可以导入这个模块了(它存储在文件C:\python\hello.py中)。
>>> import hello
Hello, world!
注意 当你导入模块时,可能发现其所在目录中除源代码文件外,还新建了一个名为__pycache__的子目录(在较旧的Python版本中,是扩展名为.pyc的文件)。这个目录包含处理后的文件, Python能够更高效地处理它们。以后再导入这个模块时,如果.py文件未发生变化,Python将导入处理后的文件,否则将重新生成处理后的文件。删除目录__pycache__不会有任何害处,因为必要时会重新创建它。
如你所见,导入这个模块时,执行了其中的代码。但如果再次导入它,什么事情都不会发生。
>>> import hello
>>>
这次为何没有执行代码呢?因为模块并不是用来执行操作(如打印文本)的,而是用于定义变量、函数、类等。鉴于定义只需做一次,因此导入模块多次和导入一次的效果相同。
为何只导入一次
在大多数情况下,只导入一次是重要的优化,且在下述特殊情况下显得尤为重要:两个模块彼此导入对方。
在很多情况下,你可能编写两个这样的模块:需要彼此访问对方的函数和类才能正确地发挥作用。例如,你可能创建了两个模块clientdb和billing,分别包含客户数据库和记账系统的代码。客户数据库可能包含对记账系统的调用(如每月自动向客户发送账单),而记账系统可能需要访问客户数据库的功能才能正确地完成记账。
在这里,如果每个模块都可导入多次,就会出现问题。模块clientdb导入billing,而billing又导入clientdb,结果可想而知:最终将形成无穷的导入循环(还记得无穷递归吗)。然而,由于第二次导入时什么都不会发生,这种循环被打破。
如果一定要重新加载模块,可使用模块importlib中的函数reload,它接受一个参数(要重新加载的模块),并返回重新加载的模块。如果在程序运行时修改了模块,并希望这种修改反映到程序中,这将很有用。要重新加载前述简单的模块hello(它只包含一条print语句),可像下面这样做:
>>> import importlib
>>> hello = importlib.reload(hello)
Hello, world!
这里假设hello已导入(一次)。通过将函数reload的结果赋给hello,用重新加载的版本
替换了以前的版本。由于打印出了问候语,说明这里确实导入了这个模块。
通过实例化模块bar中的类Foo创建对象x后,如果重新加载模块bar,并不会重新创建x指
向的对象,即x依然是(来自旧版bar的)旧版Foo的对象。要让x指向基于重新加载的模块中的
Foo创建的对象,需要重新创建它。
领取专属 10元无门槛券
私享最新 技术干货