本文目录导读:
这是一个非常经典且重要的 Python 问题。import 是 Python 的核心导入语法,而 from ... import 是 import 的一种变体,用于从模块中导入特定的部分。
它们的核心区别在于和对命名空间的影响。
下面从几个关键维度对比:
导入的对象不同
import module:导入的是整个模块,之后你需要通过模块名.的方式(如module.function())来访问模块内部的函数、类或变量。from module import name:导入的是模块中的特定名称(函数、类、变量等),之后你可以直接使用这个名称,无需模块名前缀。
对命名空间的影响(最关键区别)
-
import module:在当前命名空间中只引入了一个名字——模块名module,这避免了与当前脚本中其他同名变量的冲突,因为调用时总是有前缀module.。- 优点: 清晰、安全、不污染命名空间。
- 缺点: 代码稍微多写几个字母。
-
from module import name:将name直接引入当前命名空间,这意味着如果你已经在当前脚本中定义了一个叫name的变量,它会被覆盖。- 优点: 代码更简洁,高频函数如
os.path.join()可以直接写join()。 - 缺点: 容易引起命名冲突,你从
math模块from math import sum,然后你后面又定义了一个sum变量,sum这个名称指向的不再是math.sum函数了。
- 优点: 代码更简洁,高频函数如
内存与性能细节
- 无论哪种写法,在导入时,Python 都会将整个模块加载到内存中(
.pyc文件或已缓存的模块对象)。 - 区别在于你手里拿到的“钥匙”数量不同:
import math拿到的是整个math模块的引用。from math import sqrt拿到的是math模块中的sqrt这个具体对象的直接引用,虽然模块本身在内存中,但你无法通过math.pi访问pi,除非你同时import math或在from语句里加上pi。
语法变体
import module as alias:给模块起个别名,常用于长模块名(如import pandas as pd)。from module import name as alias:给导入的函数或变量起个别名,用于解决命名冲突或简化名称(如from decimal import Decimal as D)。- *`from module import `极度不推荐。** 这会导入模块中所有不带下划线开头的公开名称,直接“倾倒”到当前命名空间,极易引发难以追踪的命名冲突和代码混淆。
适用场景与最佳实践
| 场景 | 推荐写法 | 原因 |
|---|---|---|
| 导入一个经常使用的标准库或第三方库 | import os, import sys, import numpy as np |
避免命名冲突,代码可读性强,一眼就知道函数来自哪个库。 |
| 只使用模块中的 1-2 个函数或类 | from collections import defaultdict |
代码更简洁,但需确保与当前环境没有名称冲突。 |
| 导入一个包含许多同名常见函数的标准库 | 倾向于 import 或带 as 的显式写法 |
os.path、shutil 中有很多通用名称(如 join, copy, exists),用 from xx import join 容易导致混淆。 |
| 需要导入的子模块很深(如包内嵌套) | from package.subpackage import module |
避免每次写很长的路径,同时保留模块的命名空间隔离。 |
总结表格
| 特性 | import module |
from module import name |
|---|---|---|
| 整个模块 | 模块中的特定对象(函数、类、变量) | |
| 访问方式 | module.name() |
name() 直接使用 |
| 命名空间污染 | 低,只增加一个名字 | 中等,增加 name 名字,可能覆盖已有变量 |
| 代码可读性 | 清晰(知道来源) | 简洁(但不知道来源,需看 import 语句) |
| 推荐程度 | 更通用、更安全 | 适用于少量、无冲突的情况 |
| 特殊变体 | import module as alias |
from module import name as alias, from module import * (不推荐) |
一句话总结:
import module像你从工具箱拿了整套工具,用的时候要带上盒子标签(module.)。from module import name像你从工具箱里只拿了一把扳手,用的时候直接叫“扳手”就行,但要小心跟别的扳手重名了。