模块
2.2 模块
在Python中,经常会遇到一些文件组织概念,比如库、包、模块等。下图就是这几个概念大致的关系。可以看到,库
是包含包
的,而包
又是很多个模块(脚本)
组成的。接下来我们来一一介绍这几个概念。
注意:在之后学习中的组织结构和命名参考下图。
模块一般有两种,广义的模块和狭义的模块。广义的模块其实就是包含能实现一些特定各种功能的集合,这个其实就是库的概念了。广义的模块我们将在后续介绍。
而狭义的模块就是py等可执行的Python脚本文件。通常里面会定义一些相似功能的类
和函数
,我们在需要的时候可以导入该模块。本节中主要讲狭义模块的内容。
如果是在交互模式中,我们编写的代码或者定义的函数在退出后都不能保存。于是在在实际的编程中,我们通常会将一些功能相似的函数、类全部放入到同一个文件中,以方便今后的使用。这个文件能实现类似的功能,比如Python自带的math.py,里面定义了常用的数学函数和变量,我们只需要每次引入后就能使用。这种脚本文件就叫模块
。如果我们创建了一个abc.py
脚本文件,我们就可以称之为模块abc
。
Python安装后自带的模块文件称为内置模块
。
我们从网上下载的模块称为第三方模块
。
自己编写的称之为自定义模块
。
使用模块的好处:
- 提高代码的可维护性。
- 提高代码的复用性。
- 避免函数名或变量名等的冲突。
练习
1、参照上图结构新建文件(夹)并命名
2、将库1
的路径加入到Python搜索路径中
2.2.1 导入模块
要使用模块则需要对模块进行导入。在导入之前,需要确保模块所在的路径在Python搜索路径中。否则会报错:ModuleNotFoundError: No module named '模块名'
。
2.2.1.1 模块导入的类型
按照查找模块路径方式一般分为2种导入类型:绝对导入
和相对导入
。顾名思义,绝对导入是通过绝对路径查找模块并导入。相对导入是通过相对路径查找模块并导入。
绝对导入时,都是从根节点
开始搜索,而根节点
的路径来自于Python搜索路径,也即上节中提到的:sys.path。
相对导入时,只关心相对自己当前目录的模块位置。相对导入的方式不能在模块的内部直接执行(会报错)。不管根节点在哪儿,模块相对位置都是正确的。
相对导入时会使用到的一些目录路径:
.
代表当前目录路径,一般后面要跟上模块名,代表当前目录指定模块。比如:
from .模块甲 import *
..
代表父目录路径,一般后面跟上父目录名,代表指定父目录路径。比如:
from ..包a.模块甲 import *
注意:这种相对导入的方式只允许模块作为被导入而运行。如果直接运行模块则会报错:attempted relative import with no known parent package
2.2.1.2 模块导入的方法
对于模块,通常可以使用以下2种导入方法:import 模块名
导入和from ... import 模块名
导入
不管采用何种导入类型和何种导入方法,都是需要先找到模块,然后再import它。
import 模块甲
绝对导入:
import [库].[包].[子包][.子包...].模块名
相对导入:
无
导入效果:
1、模块会被间接运行
2、模块中所有的对象(变量、函数、类,以下同)会被导入
3、模块甲中的保护对象(以_开头命名的对象)会被导入
使用方式:
模块甲.对象名
from 模块甲 import *
绝对导入:
from [库].[包].[子包][.子包...].模块名 import *
相对导入:
from [相对路径] import 模块名
from [相对路径].模块名 import *
导入效果:
1、包含模块甲的包a(__init__.py
文件)会被间接运行(非当前包中的模块使用该导入方式)
2、模块甲会被间接运行
3、模块甲中所有的非保护对象(非_开头的对象)会被导入
使用方式:
直接使用模块甲中的对象名即可。
注意事项:
大多数情况下,不要用这个方式,这种方式向解释器导入了一批未知的名称,可能会覆盖已经定义的名称。这项操作也会经常让代码变得难以理解。不过,为了在交互式编译器中少打几个字,这么用也没问题。
2.2.1.3 模块导入总结
1、模块的命名空间不仅仅包含模块级的变量和常量,还包括所有在模块中定义的。除此以外,它还包括了任何被导入到模块中的东西。
2、内置命名空间
被包含在一个模块中,它被称作__builtin__
模块,我们之前在Python入门技巧中提到了这个模块。
3、使用 import module,模块自身被导入,但是它保持着自已的名字空间,这就是为什么需要使用模块名来访问它的函数或属性:模块.对象
的原因。而使用 from 模块import 对象,实际上是从另一个模块中将指定的对象导入到当前模块的名字空间中,这就是为什么可以直接访问它们却不需要引用它们所来源的模块。
2.2.1.4 模块导入技巧
导入多个模块
import 模块甲, 模块乙, 模块丙
导入多个对象
from 模块甲 import 对象1, 对象2, 对象3
练习
熟悉各种导入方式并尝试导入
2.2.2 模块内置属性
2.2.2.1 __name__属性
每个模块中都有自己的__name__
属性,当直接运行模块时,__name__属性的值是__main__
,而模块被导入时,__name__
返回被导入模块的名字。通过这种方式就可以判断当前模块是被导入还是自身运行。一般用来对模块文件进行功能测试。
示例:
if __name__ == '__main__':
print('当前模块被运行时,if语句内的命令都会被执行')
print('当该模块被其它脚本导入时,if语句内的命令都不会被执行')
2.2.2.2 __file__属性
返回模块的绝对路径
2.2.2.3 __doc__属性
返回模块的文档字符串
练习
查看常见模块(math、sys、os等)的上述内置属性
2.2.3 探索模块
2.2.3.1 使用dir查看模块
要查明模块包含哪些东西,可使用函数dir,它列出对象的所有属性(对于模块,它列出所有的函数、类、变量等)。
>>> import math
>>> dir(math)
['doc', 'loader', 'name', 'package', 'spec', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'comb', 'copysign', 'cos', 'cosh', 'degrees', 'dist', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'isqrt', 'lcm', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'nextafter', 'perm', 'pi', 'pow', 'prod', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc', 'ulp']
2.2.3.2 使用help 获取帮助
可以通过help函数查看模块的帮助信息。
>>> import math
>>> help(math)
Help on built-in module math:
NAME
math
DESCRIPTION
This module provides access to the mathematical functions
defined by the C standard.
FUNCTIONS
acos(x, /)
Return the arc cosine (measured in radians) of x.
The result is between 0 and pi.
acosh(x, /)
Return the inverse hyperbolic cosine of x.
asin(x, /)
Return the arc sine (measured in radians) of x.
The result is between -pi/2 and pi/2.
asinh(x, /)
Return the inverse hyperbolic sine of x.
atan(x, /)
Return the arc tangent (measured in radians) of x.
练习
使用dir和help来探索之前遇到的模块。
2.2.4 标准模块
在Python安装完毕之后,本身程序就有的模块称之为标准模块。一些模块是内嵌到编译器里面的,我们可以在任何自己创建的脚本中很方便地导入这些标准模块。
2.2.5 第三方模块和自定义模块的使用
将从网上下载的第三方模块或者自己编写的模块放到任何一个Python路径中或和要调用改模块的脚本同一目录下即可。接下来就可以在其它脚本中对该模块进行导入并使用了。