下面从基础到进阶逐步拆解,所有示例均可直接运行,兼顾原理和实战:
一、模块的核心定义
1.1 什么是模块?
模块(Module)是 Python 中组织代码的基本单元,本质是一个以.py为后缀的文件(比如utils.py),里面包含变量、函数、类、可执行代码等。
1.2 模块的核心作用
- 代码复用:写好的模块可在多个项目 / 文件中导入使用,无需重复编写;
- 命名空间隔离:不同模块的变量 / 函数名可以相同,不会互相冲突(比如
module1.py和module2.py都有add()函数); - 代码结构化:将大型项目拆分为多个模块,按功能划分(如
数据处理模块、日志模块、配置模块),便于维护。
1.3 模块的分类
| 类型 | 说明 | 示例 |
|---|---|---|
| 自定义模块 | 开发者自己编写的.py文件 | my_utils.py |
| 内置模块 | Python 自带的模块(无需安装) | sys、os、json |
| 第三方模块 | 需通过 pip 安装的模块(社区贡献) | requests、pandas |
| 编译扩展模块 | 用 C/C++ 编写的二进制模块(.so/.pyd) | numpy的核心模块 |
二、模块的基础使用
2.1 创建自定义模块
只需新建一个.py文件,写入代码即可。
示例:创建math_utils.py(自定义数学工具模块)
python
# math_utils.py """ 这是一个数学工具模块,包含常用的数学函数 """ # 模块级变量 PI = 3.1415926 # 函数 def add(a: int, b: int) -> int: """两数相加""" return a + b def circle_area(r: float) -> float: """计算圆的面积""" return PI * r * r # 类 class Calculator: """简单计算器类""" def multiply(self, a: int, b: int) -> int: return a * b # 可执行代码(导入时会运行) print("math_utils模块被加载了!")2.2 导入模块的 5 种方式
导入模块的核心关键字是import和from,以下是最常用的 5 种方式,均基于上面的math_utils.py演示:
方式 1:导入整个模块(推荐,避免命名冲突)
python
# main.py # 导入自定义模块 import math_utils # 使用模块中的成员:模块名.成员名 print(math_utils.PI) # 输出:3.1415926 print(math_utils.add(2, 3)) # 输出:5 print(math_utils.circle_area(2)) # 输出:12.5663704 # 创建类实例 calc = math_utils.Calculator() print(calc.multiply(4, 5)) # 输出:20方式 2:导入模块并指定别名(模块名过长时用)
python
# 给模块起别名 import math_utils as mu print(mu.PI) # 输出:3.1415926 print(mu.add(1, 1)) # 输出:2方式 3:从模块中导入指定成员
python
运行
# 只导入需要的成员,无需写模块名前缀 from math_utils import PI, add print(PI) # 输出:3.1415926 print(add(3, 4)) # 输出:7方式 4:从模块中导入成员并指定别名(避免成员名冲突)
python
# 给成员起别名 from math_utils import circle_area as ca print(ca(3)) # 输出:28.2743334方式 5:导入模块的所有成员(不推荐,易冲突)
python
# 导入所有成员(* 表示全部) from math_utils import * print(PI) # 输出:3.1415926 print(add(5, 6)) # 输出:11⚠️ 缺点:如果多个模块有同名成员,后导入的会覆盖先导入的,难以排查问题。
2.3 模块的执行与__name__属性
核心原理
- 当直接运行一个
.py文件时,该文件的__name__变量会被设为"__main__"; - 当该文件被作为模块导入时,
__name__变量会被设为模块名(比如math_utils)。
实用场景:模块内写测试代码
修改math_utils.py,添加测试代码:
python
# math_utils.py(新增测试代码) # ... 原有代码 ... # 仅在直接运行该文件时执行测试 if __name__ == "__main__": print("测试math_utils模块...") assert add(2, 3) == 5 assert circle_area(2) ≈ 12.566 print("所有测试通过!")- 直接运行
math_utils.py:会执行测试代码,输出「测试 math_utils 模块... 所有测试通过!」; - 导入
math_utils模块(如在main.py中):不会执行测试代码,仅加载模块。
三、模块的搜索路径与加载机制
3.1 模块搜索路径
Python 导入模块时,会按以下顺序查找模块文件:
- 当前执行脚本所在目录;
- Python 内置模块目录(如
Python3xx/Lib); - 第三方模块安装目录(如
Python3xx/Lib/site-packages); - 环境变量
PYTHONPATH指定的目录。
查看 / 修改搜索路径
python
import sys # 查看模块搜索路径(列表形式) print(sys.path) # 临时添加自定义路径(仅当前运行有效) sys.path.append("/Users/xxx/my_modules") # 替换为你的模块目录3.2 模块加载流程
- 查找:按搜索路径查找模块文件(如
math_utils.py); - 编译:如果模块是首次导入,会将
.py编译为字节码文件(.pyc),存放在__pycache__文件夹; - 执行:执行模块中的代码,创建模块对象,将变量 / 函数 / 类绑定到模块对象;
- 缓存:后续导入该模块时,直接加载
__pycache__中的.pyc文件,无需重新编译,提升速度。
3.3 模块的重新加载
默认情况下,模块导入后不会重新加载(即使修改了模块文件),需用importlib.reload:
python
import math_utils import importlib # 修改math_utils.py后,重新加载模块 importlib.reload(math_utils)