Python包、模块、类的导入语法与机制解析
1、核心概念:包、模块、类
在理解导入语法前,需要先明确几个核心概念:
概念 | 定义 | 示例 |
---|---|---|
包 | 包含多个模块的目录,需通过 __init__.py 文件声明(Python 3.3+ 可选)。 | 目录 mypackage 下有 submodule1.py 和 submodule2.py ,且含 __init__.py |
模块 | 单个 .py 文件,包含函数、类、变量等代码,用于实现特定功能。 | math.py (标准库模块)、my_module.py (自定义模块) |
类 | 模块或包中的代码结构,用于封装数据和方法。 | datetime 模块中的 datetime 类(from datetime import datetime ) |
2、导入的常见语法
导入(Import) 是将其他模块/包中的代码对象(类、函数、变量等)加载到当前代码的命名空间中,使其可以被直接调用。
Python 的导入语法是from...import...
,从“源”中导入“目标对象”
from
用于指定“源”,模块或包(可选,无from
时直接导入模块/包);import
用于指定“目标对象”,模块、子包、类、函数、变量等(必须,是导入操作的核心)。
2.1、直接导入模块或包(无 from
)
语法:import source
说明:source
可以是模块(.py
文件)或包(目录),将整个源加载到当前命名空间,访问时需通过 源名.对象名
。
示例:
# 导入模块(如标准库 math)
import math
print(math.pi) # 访问模块内的变量# 导入包(如自定义包 mypackage)
import mypackage # 需确保 mypackage 所在目录在 sys.path 中
mypackage.module_a.func_a() # 访问包内子模块的函数(需 mypackage/__init__.py 暴露模块)
2.2、导入时重命名(模块/包均可)
语法:import source as alias
说明:为模块或包起别名,简化后续调用(尤其适合名称过长或避免命名冲突)。
示例:
# 模块重命名(科学计算常用)
import numpy as np # 用 np 代替 numpy
arr = np.array([1, 2, 3])# 包重命名(自定义包)
import mypackage as mp # 用 mp 代替 mypackage
mp.module_a.func_a() # 调用包内子模块的函数
2.3、从源(模块/包)中导入特定对象
语法:from source import target
说明:source
是模块或包(支持层级路径),target
是源中的对象(类、函数、变量、子模块、子包等)。
示例:
# 从模块中导入类(最常见场景)
from datetime import datetime # source=模块 datetime,target=类 datetime
now = datetime.now()# 从包中导入子模块(自定义包场景)
from mypackage import module_a # source=包 mypackage,target=子模块 module_a
module_a.func_a() # 直接使用子模块的函数# 从子包中导入模块(层级路径)
from mypackage.subpackage import module_b # source=子包 mypackage.subpackage,target=模块 module_b
module_b.ClassB().method() # 使用子包模块中的类
2.4、从源中导入多个对象(模块/包均可)
语法:from source import target1, target2, ...
说明:同时导入源中的多个对象(类型可混合:类、函数、子模块等)。
示例:
# 从模块中导入多个函数/变量
from math import pi, sqrt # 导入变量 pi 和函数 sqrt
print(pi)
print(sqrt(25))# 从包中导入多个子模块
from mypackage import module_a, subpackage # 导入子模块 module_a 和子包 subpackage
module_a.func_a()
subpackage.module_b.func_b() # 调用子包模块的函数
2.5、从源中导入所有对象(不推荐)
语法:from source import *
说明:导入源中所有非下划线开头的对象(类、函数、变量、子模块等),但强烈不推荐(易导致命名冲突,代码可读性差)。
示例:
# 从模块导入所有对象(如 math)
from math import * # 导入 pi、sqrt、sin 等所有对象
print(pi)
print(sin(0))# 从包导入所有对象(需包的 __init__.py 定义 __all__ 控制导出)
from mypackage import * # 导入 mypackage 中 __all__ 声明的子模块/对象
module_a.func_a() # 若 __all__ 包含 module_a 则可用
3、导入的机制
3.1、导入的优先级(从高到低)
- 内置模块
- 存储位置:C 语言实现,集成在 Python 解释器内存中(无物理文件)。
- 加载时机:Python 启动时自动加载,优先于所有磁盘路径。
- 当前目录
- 存储位置:脚本所在目录(或交互式环境的终端工作目录)。
- 作用时机:本地自定义模块(如
my_module.py
)的优先搜索路径。
- 环境变量
PYTHONPATH
- 存储位置:用户通过环境变量自定义的额外搜索目录(如
export PYTHONPATH=/my/lib
)。 - 加载时机:Python 启动时自动读取,路径按顺序添加到
sys.path
中。
- 存储位置:用户通过环境变量自定义的额外搜索目录(如
- 标准库目录
- 存储位置:Python 安装路径下的
lib
目录(如/usr/lib/python3.12
)。 - 内容时机:包含标准库的
.py
文件、.pyc
预编译文件及 C 扩展(.so
/.pyd
)。
- 存储位置:Python 安装路径下的
3.2、sys.path
sys.path
是 Python 运行时的一个内置列表,用于存储模块搜索的路径。
除了上面提到的“内置模块”以外,其他的加载路径都保存在这里。
进入python解释器后,通过以下命令就能查看sys.path
的具体内容:
import sys
print(sys.path)
''
,代表当前目录(脚本所在目录或终端工作目录)
没有额外配置环境变量PYTHONPATH
,所以接下来是到了系统级的标准库,首先是.zip
压缩文件,这是用来提高加载速度的。
然后是/usr/lib/python3.12
,标准库的未压缩目录版本(与 .zip 内容重复,备用路径),如下图。
/usr/lib/python3.12/lib-dynload
是动态加载的 C 扩展模块,一些列的.so
文件。
/home/ly/web_pyvenv/lib/python3.12/site-packages
虚拟环境隔离的第三方包目录(如 numpy、pandas 等用户安装的库)。