模块可以让代码有逻辑地组织起来。将相关代码分组到一个模块中,可以使代码更易于理解和使用。模块化编程是指将大型的编程任务分解为单独的、较小的、更易于管理的子任务或模块的过程。可以像拼积木一样将各个模块拼凑在一起,以创建更大的应用程序。
在大型的编程项目中,模块化编程有几个优点。
①简便性:一个模块通常不关注整个的庞大问题,而只关注问题的一小部分。如果将大型项目拆成一个个模块,那么在处理单个模块时,待解决的问题较小,更容易解决问题。模块化编程会使开发大型软件更加容易,并且不易出错。
②可维护性:模块通常经过精心设计,以便它们在不同问题域之间建立逻辑边界。如果以最小化相互依赖性的方式编写模块,那么降低了修改单个模块时对程序其他部分产生影响的可能性。这使得由许多程序员组成的团队在大型项目上协同工作更加简单。
③可重用性:单个模块中定义的功能可以被应用程序的其他部分轻松地重用(通过定义适当的接口)。这样就不需要编写重复的代码。
④作用域:模块通常定义一个单独的名称的空间,这有助于避免程序不同区域中的标识符之间发生冲突。
模块
在Python中,定义模块的方式有以下三种:
①使用Python编写模块。
②使用C编写模块,并在运行时动态加载模块,如re(正则表达式)模块。
③内建模块,固有地包含在Python解释器中,如itertools模块。
在这三种方式下,都以相同的方式访问模块的内容:使用import语句。本书将重点主要放在用Python编写的模块上。使用Python编写模块的构建极其简单,需要做的就是创建一个包含合法Python代码的文件,然后为该文件命名,.py为扩展名。例如,在当前目录下新建一个名为module.py的文件:
- s = 'I love Python'
- l = [1, 2, 3]
- def f(arg):
- print(arg)
- class C:
- pass
在module.py中定义了以下对象:
①s是一个字符串。
②l是一个列表。
③f是一个函数。
④C是一个类。
打开交互式解释器,可以通过导入模块来访问这些对象:
- >>> import module # 导入之前定义的模块
- >>> # 访问模块中的对象
- >>> print(module.s)
- I love Python
- >>> module.l
- [1, 2, 3]
- >>> module.f(123)
- 123
- >>> c = module.C()
- >>> c
- <module.C object at 0x10c465710>
模块搜索路径
以上述示例的导入模块语句import module为例,Python解释器执行import语句时,将从以下路径中搜索module.py:
①输入脚本的目录(如果以脚本模式运行)或当前目录。
②PYTHONPATH环境变量(如果已设置)中包含的目录列表(PYTHONPATH的格式取决于操作系统)。
③安装Python时配置的与安装相关的目录列表。
在Python变量sys.path中,可以访问生成的搜索路径,该变量是从名为sys的模块中获取的:
- >>> import sys
- >>> sys.path
- ['', '/Library/Frameworks/Python.framework/Versions/3.7/lib/python37.zip',
- '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7',
- '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload',
- '/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages']
注意,sys.path的实际内容取决于安装时的情况,因此,在不同计算机上的运行结果可能会有所不同。
为了确保可以找到模块,需要执行以下操作之一:
①将module.py放入输入脚本的目录(如果以脚本模式运行)或当前目录。
②在启动Python解释器之前,修改PYTHONPATH环境变量,以包含module.py所在的目录,或者将module.py放入PYTHONPATH环境变量已经包含的目录中。
③将module.py放入与安装相关的目录之一(可能没有访问权限,具体取决于操作系统)。