Python-模块和包
文章目录
- 一、模块的概念
- 1. 什么是模块?
- 2. 模块的作用
- 3. 模块的类型
- 二、模块的导入
- 1. 基本导入(import 模块名)
- 2. 导入模块并起别名(import 模块名 as 别名)
- 3. 导入模块中的指定内容(from 模块名 import 内容)
- 4. 导入模块中所有内容(不推荐)
- 三、模块查找的顺序
- 四、`__name__`的作用
- 1. `__name__`的两种取值
- 2. 实际应用:模块的 “自测” 功能
- 五、包的概念
- 1. 什么是包?
- 2. init.py 文件的作用
- 3. 包的导入方式
- 总结
一、模块的概念
1. 什么是模块?
模块(Module)是一个包含Python 定义和语句的文件,文件名以.py为后缀。简单来说,模块就是将 Python 代码按功能拆分到不同文件中,实现代码的模块化、复用性和可维护性。
例如:创建一个名为math_tools.py的文件,里面写了加法、乘法等数学工具函数,这个文件就是一个模块。
2. 模块的作用
- 代码复用:写好的模块可以在多个项目中直接导入使用,无需重复编写。
- 功能拆分:将复杂程序拆分为多个模块,每个模块负责一个具体功能,降低开发难度。
- 避免命名冲突:不同模块中的函数 / 变量可以重名,通过模块名区分,避免冲突。
3. 模块的类型
- 内置模块:Python 自带的模块(如math、json、os),无需安装可直接导入。
- 自定义模块:开发者自己编写的.py文件。
- 第三方模块:需要通过pip安装的模块(如requests、numpy)。
二、模块的导入
Python 提供多种导入模块的方式,可根据需求选择合适的方法。
1. 基本导入(import 模块名)
直接导入整个模块,使用模块中的内容时需加模块名.前缀。
# 导入内置模块math
import math# 使用模块中的函数/属性
print(math.pi) # 访问模块属性(圆周率)
print(math.sqrt(16)) # 调用模块函数(开平方)
2. 导入模块并起别名(import 模块名 as 别名)
当模块名较长时,可给模块起简短别名,简化使用。
# 给numpy模块起别名np(行业常用写法)
import numpy as nparr = np.array([1, 2, 3]) # 使用别名调用模块功能
print(arr)
3. 导入模块中的指定内容(from 模块名 import 内容)
只导入模块中需要的函数、变量等,无需加模块名前缀。
# 从math模块中只导入pi和sqrt
from math import pi, sqrtprint(pi) # 直接使用,无需math.前缀
print(sqrt(25))
4. 导入模块中所有内容(不推荐)
使用*导入模块中所有公开内容(以非下划线_开头的内容),可能导致命名冲突。
# 导入math模块所有内容
from math import *print(sin(pi/2)) # 直接使用sin函数
print(cos(pi))
注意:除非明确知道模块内容且无命名冲突,否则不建议使用这种方式。
三、模块查找的顺序
当使用import导入模块时,Python 会按以下顺序查找模块文件,找到第一个匹配的模块后停止:
- 当前执行脚本所在目录(即运行 Python 程序时的工作目录)
- Python 的内置模块目录(存放math、os等内置模块的位置)
- 环境变量PYTHONPATH指定的目录(可通过sys.path查看)
- Python 安装时默认的第三方模块目录(如site-packages文件夹,存放pip安装的模块)
查看模块查找路径
可通过sys模块的path属性查看具体的查找路径:
import sys# 打印模块查找路径列表
for path in sys.path:print(path)
常见问题:模块找不到(ModuleNotFoundError)
若出现该错误,可能原因及解决方法:
- 模块文件不在当前工作目录:将模块文件移到当前目录,或把模块所在目录添加到sys.path。
- 模块名拼写错误:检查模块名是否正确(区分大小写)。
- 第三方模块未安装:通过pip install 模块名安装。
四、__name__的作用
__name__是 Python 中每个模块都有的内置变量,用于标识模块的 “身份”,其值取决于模块的运行方式。
1. __name__的两种取值
当模块作为主程序运行时(直接执行该.py文件),__name__的值为"__main__"。
当模块被导入时(在其他文件中import该模块),__name__的值为模块的文件名(不含.py后缀)。
2. 实际应用:模块的 “自测” 功能
利用__name__的特性,可以在模块中编写 “自测代码”—— 只有当模块直接运行时,自测代码才执行;当模块被导入时,自测代码不执行。
示例(模块文件:calc.py):
# 定义一个加法函数
def add(a, b):return a + b# 自测代码
if __name__ == "__main__":# 只有直接运行calc.py时,以下代码才执行test1 = add(2, 3)test2 = add(5, 7)print(f"2+3={test1}(预期5)")print(f"5+7={test2}(预期12)")
直接运行calc.py:__name__为"__main__“,执行自测代码,输出测试结果。
在其他文件中import calc:__name__为"calc”,自测代码不执行,仅导入add函数。
五、包的概念
1. 什么是包?
包(Package)是多个相关模块的集合,本质是一个包含__init__.py文件的文件夹。通过包可以将功能关联的模块组织在一起,实现更高级的代码分层和管理(类似文件夹整理文件)。
例如:一个名为my_package的包结构如下:
my_package/ # 包文件夹
├── init.py # 包的初始化文件(必需)
├── module1.py # 模块1
├── module2.py # 模块2
└── sub_package/ # 子包
├── init.py
└── module3.py # 子包中的模块
2. init.py 文件的作用
标识该文件夹是一个 Python 包(Python 3.3 + 后可省略,但为了兼容性建议保留)。
初始化包:在导入包或包内模块时,会自动执行__init__.py中的代码。
简化导入:可以在__init__.py中指定 “对外暴露” 的模块 / 函数,方便外部导入。
示例(my_package/__init__.py):
# 从包内模块中导入指定内容,方便外部直接导入
from .module1 import add
from .module2 import multiply# 定义包的版本等信息
__version__ = "1.0.0"
3. 包的导入方式
(1)导入包内的模块
# 方式1:import 包名.模块名
import my_package.module1print(my_package.module1.add(1, 2))
# 方式2:起别名
import my_package.module1 as m1print(m1.add(3, 4))
# 方式3:from 包名 import 模块名
from my_package import module2print(module2.multiply(2, 5))
(2)导入包内模块的指定内容
# 从包的模块中导入函数
from my_package.module1 import addprint(add(5, 6))
# 从子包中导入模块
from my_package.sub_package import module3
(3)通过__init__.py 简化导入
由于在__init__.py中导入了add和multiply,可以直接从包中导入这些内容:
from my_package import add, multiplyprint(add(10, 20))
print(multiply(3, 4))
总结
- 模块:单个.py文件,实现代码复用和功能拆分。
- 导入方式:import 模块名、from 模块名 import 内容等,按需选择。
- 查找顺序:当前目录 → 内置模块目录 → PYTHONPATH → 第三方模块目录。
- name:区分模块运行方式,实现模块自测。
- 包:含__init__.py的文件夹,用于组织多个相关模块,支持分层管理。
合理使用模块和包,是编写大型 Python 项目的基础,能显著提升代码的可读性和可维护性。
