import 导入模块对象,from...import 导入具体名字;前者安全可追溯,后者简洁但易污染命名空间、引发循环导入和重载失效问题。

import 和 from ... import 的行为差异
本质区别在于:前者导入模块对象本身,后者导入模块里的具体名字(函数、类、变量)。这直接决定你后续怎么用、能不能改、会不会覆盖。
常见错误现象:from math import sqrt 后又写 sqrt = lambda x: x ** 0.5,你以为改的是自己的变量,其实只是覆盖了本地名字——math.sqrt 没变,但你也再拿不到原版了。
-
import math→ 用math.sqrt(),安全、清晰、可追溯 -
from math import sqrt→ 直接用sqrt(),简洁但名字空间被污染风险高 -
from math import *→ 绝对避免。会悄悄覆盖已有变量,调试时根本看不出哪来的冲突
循环导入报错 ImportError: cannot import name 'X' from partially initialized module
这是 from ... import 最容易踩的坑:A.py 用 from B import func,B.py 又用 from A import cls,Python 解析到一半卡死。
原因:Python 执行 from 时会尝试把目标模块整个加载完,再取名字;而循环中模块处于“已开始加载但未完成”状态,名字还不存在。
- 改成
import B和import A,在函数体内再用B.func()或A.cls,延迟引用 - 把相互依赖的类/函数挪到第三个模块里,由双方 import 它
- 确认是不是真需要双向导入——很多时候只是设计上把职责耦合太紧
重载模块时 import 不生效,from ... import 更糟
开发调试时用 importlib.reload(),但只对 import mod 有效;如果是 from mod import func,reload 后 func 还是旧对象,因为名字已经绑定到老函数上了。
使用场景:Django shell、Jupyter、快速迭代脚本。别在生产代码里 reload。
- 统一用
import mod,reload 后调mod.func()才能拿到新逻辑 - 如果非要用
from形式,reload 后必须重新执行from mod import func -
sys.modules.pop('mod')再 import 是危险操作,可能破坏其他依赖它的模块
__init__.py 里用 from ... import 控制 public API
用户 import pkg 时看到什么,取决于 pkg/__init__.py 里怎么导出。这里用 from ... import 是合理且推荐的,但得小心控制粒度。
性能影响:提前导入太多子模块,会拖慢顶层 import 速度;兼容性上,如果子模块依赖没装,整个 import pkg 就失败。
- 只在
__init__.py中from .submod import ClassA, func_b,暴露明确接口 - 避免
from .submod import *,除非你完全掌控 submod 的 __all__ - 内部工具函数、私有模块(如
_utils.py)别往 __init__.py 里导,加下划线不是保险丝
真正难的不是语法,是判断一个名字该不该出现在用户 import 后的命名空间里——导得太少,用着麻烦;导得太多,以后动不动就破兼容。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











