Python教程20:模块基础
“分而治之,事半功倍。”
当代码越来越多时,把所有代码放在一个文件里会变得难以维护。模块(Module)就是Python的代码组织方式,让你可以把相关功能分门别类。今天我们学习如何创建和使用模块。
1. 什么是模块
定义
**模块(Module)**是一个包含Python代码的.py文件。每个Python文件都可以作为一个模块被其他文件导入使用。
为什么需要模块:
- 代码复用:写一次,到处用
- 命名空间:避免变量名冲突
- 代码组织:按功能分类,便于维护
- 协作开发:不同人负责不同模块
简单示例
创建一个文件math_utils.py:
1# math_utils.py
2"""数学工具模块"""
3
4PI = 3.14159
5
6def add(a, b):
7 """加法"""
8 return a + b
9
10def circle_area(radius):
11 """计算圆面积"""
12 return PI * radius ** 2
13
14class Calculator:
15 """计算器类"""
16 def multiply(self, a, b):
17 return a * b
在另一个文件中使用:
1# main.py
2import math_utils # 导入模块
3
4print(math_utils.PI) # 3.14159
5print(math_utils.add(3, 5)) # 8
6print(math_utils.circle_area(5)) # 78.53975
7
8calc = math_utils.Calculator()
9print(calc.multiply(4, 5)) # 20
模块的本质:
- 模块是一个命名空间(namespace)
- 文件名(去掉.py)就是模块名
- 通过模块名访问其中的变量、函数、类
2. 导入模块的方式
Python提供了多种导入方式,适应不同场景。
方式1:import模块名
1import math_utils
2
3# 使用:模块名.成员
4result = math_utils.add(1, 2)
优点:
- 清晰知道函数来自哪个模块
- 避免命名冲突
缺点:
- 每次都要写模块名,稍显繁琐
方式2:from模块 import成员
1from math_utils import add, PI
2
3# 直接使用成员,不需要模块名
4result = add(1, 2)
5print(PI)
优点:
- 代码更简洁
缺点:
- 可能产生命名冲突
- 不清楚成员来自哪个模块
方式3:import模块 as别名
1import math_utils as mu # 给模块起别名
2
3result = mu.add(1, 2)
使用场景:
- 模块名太长时
- 避免模块名冲突
- 遵循社区惯例(如
import numpy as np)
方式4:from模块 import *(不推荐)
1from math_utils import *
2
3# 导入模块中所有公开成员
4result = add(1, 2)
5print(PI)
为什么不推荐:
- 导入了哪些成员不明确
- 容易产生命名冲突
- 降低代码可读性
- 违反Python之禅:“Explicit is better than implicit”
唯一例外:在交互式环境(REPL)中快速试验时可以使用。
3. 模块的搜索路径
当你import一个模块时,Python会按以下顺序搜索:
- 当前目录:执行脚本所在的目录
- PYTHONPATH 环境变量:用户自定义的路径
- 标准库目录:Python安装目录下的lib
- site-packages:第三方库的安装目录
查看搜索路径:
1import sys
2
3# sys.path是一个列表,包含所有搜索路径
4for path in sys.path:
5 print(path)
sys模块:
- Python标准库之一
- 提供与Python解释器交互的功能
sys.path存储模块搜索路径
添加自定义路径
如果模块不在搜索路径中,可以手动添加:
1import sys
2
3# 添加路径(临时,仅当前运行有效)
4sys.path.append('/path/to/your/modules')
5
6# 现在可以导入该路径下的模块了
7import my_module
注意:
- 这种方式只在当前Python进程有效
- 重启后需要重新添加
- 更好的方式是配置PYTHONPATH环境变量
4. 模块的执行
__name__变量
每个模块都有一个特殊变量__name__:
- 作为模块被导入时:
__name__是模块名 - 作为脚本直接运行时:
__name__是"__main__"
1# my_module.py
2def hello():
3 print("Hello from module")
4
5# 这段代码只在直接运行时执行,被导入时不执行
6if __name__ == "__main__":
7 print("模块被直接运行")
8 hello()
9else:
10 print("模块被导入")
作为脚本运行:
1$ python my_module.py
2模块被直接运行
3Hello from module
作为模块导入:
1import my_module # 输出:模块被导入
2my_module.hello() # 输出:Hello from module
为什么需要这个机制:
- 模块既可以被导入,也可以独立运行测试
- 导入时不会执行测试代码
- 是Python模块的标准做法
5. 常用的标准库模块
Python自带了丰富的标准库,这些是最常用的:
math - 数学函数
1import math
2
3# math模块提供数学函数和常量
4# 来自Python标准库,无需安装
5print(math.pi) # 3.141592653589793
6print(math.sqrt(16)) # 4.0(平方根)
7print(math.ceil(3.2)) # 4(向上取整)
8print(math.floor(3.8)) # 3(向下取整)
random - 随机数
1import random
2
3# random模块用于生成随机数
4# 常用于游戏、模拟、采样等场景
5print(random.random()) # 0.0到1.0的随机浮点数
6print(random.randint(1, 10)) # 1到10的随机整数
7print(random.choice(['a', 'b', 'c'])) # 随机选择一个元素
datetime - 日期时间
1from datetime import datetime, timedelta
2
3# datetime模块处理日期和时间
4# Python标准库,处理时间相关操作
5now = datetime.now()
6print(now) # 2024-01-15 10:30:00.123456
7
8# 时间计算
9tomorrow = now + timedelta(days=1)
10print(tomorrow)
os - 操作系统接口
1import os
2
3# os模块提供操作系统相关功能
4# 文件路径、目录操作、环境变量等
5print(os.getcwd()) # 当前工作目录
6print(os.listdir('.')) # 列出当前目录文件
json - JSON处理
1import json
2
3# json模块用于JSON数据的编码和解码
4# JSON是Web开发中最常用的数据交换格式
5data = {"name": "Alice", "age": 25}
6json_str = json.dumps(data) # Python对象 → JSON字符串
7print(json_str) # '{"name": "Alice", "age": 25}'
8
9parsed = json.loads(json_str) # JSON字符串 → Python对象
10print(parsed["name"]) # Alice
6. 模块的最佳实践
1. 模块文档字符串
1"""
2这是模块的文档字符串。
3
4应该说明:
5- 模块的用途
6- 主要功能
7- 使用示例
8"""
9
10def my_function():
11 """函数文档"""
12 pass
2. 使用__all__控制导出
1# my_module.py
2"""我的模块"""
3
4__all__ = ['public_func', 'PUBLIC_VAR'] # 指定公开接口
5
6def public_func():
7 """公开函数"""
8 pass
9
10def _private_func():
11 """私有函数(以_开头)"""
12 pass
13
14PUBLIC_VAR = 10
15_PRIVATE_VAR = 20
使用时:
1from my_module import *
2
3# 只会导入__all__中列出的成员
4public_func() # OK
5# _private_func() # NameError
__all__的作用:
- 明确模块的公开接口
- 控制
from module import *的行为 - 提示用户哪些是稳定的API
3. 私有成员约定
1# 以单下划线开头表示"内部使用"
2_internal_var = 10
3
4def _internal_function():
5 """这是内部函数,不应被外部调用"""
6 pass
7
8# 正常命名表示公开接口
9public_var = 20
10
11def public_function():
12 """这是公开函数"""
13 pass
约定:
- 单下划线
_:内部使用,但仍可访问 - 双下划线
__:名称改编(name mangling),类中使用 - 这只是约定,Python不强制私有性
7. 重新加载模块
模块只在第一次导入时执行,再次导入会使用缓存:
1import my_module # 第一次:执行模块代码
2import my_module # 第二次:使用缓存,不重新执行
强制重新加载(开发调试时用):
1import importlib # Python标准库,提供导入相关工具
2
3import my_module
4# 修改了my_module.py后
5importlib.reload(my_module) # 重新加载
注意:
- 生产环境不要用reload
- 重启Python更可靠
- reload主要用于交互式开发
8. 小结
今天我们学习了模块的基础:
- 定义:.py文件就是模块
- 导入方式:import、from…import、as别名
- 搜索路径:当前目录 → PYTHONPATH → 标准库
- name:区分导入和直接运行
- 标准库:math、random、datetime、os、json
- 最佳实践:文档字符串、all、私有约定
模块是Python代码组织的基础,下一课我们将学习包(Package)——模块的集合。
练习题:
- 创建一个工具模块,包含常用的字符串处理函数
- 探索一个标准库模块(如collections),写出3个使用示例
- 理解并解释__name__ == “main“的作用
本文代码示例:
关注公众号:极客老墨
更多 AI 应用开发、工程实践和效率工具分享,欢迎扫码关注。
