Python 模块导入(import)实战指南
在 Python 中,导入(import)是代码复用的关键。通过正确的导入方式,代码更清晰、模块化,避免命名冲突。使用 import X 导入整个模块,或 from X import Y 导入特定内容有助于提高可维护性。遵循 PEP8 的导入顺序,确保代码结构规范。理解 all 和 name 有助于更精确地控制导入行为,避免不必要的错误和混乱。
“import X” VS “from X import Y”
在 Python 中,有两种主要的导入方式,每种方式有其特定的使用场景。假设我们有两个文件:main.py(我们运行的文件)和 helper.py(我们从中导入的文件),我们来比较一下 import X 和 from X import Y 的区别。
import X:导入整个模块,之后需要通过 X.name 来引用模块中的所有内容。
当使用 import X 时,整个模块 helper 会被导入,之后你需要使用 helper.greet() 来调用 helper 模块中的 greet 函数(或者 helper.function_name())。
from X import Y:只导入模块中的特定函数、类或变量。你可以直接使用 Y,而不需要加上模块名。
使用 from X import Y 时,只导入了 helper.py 中的 greet 函数,你可以直接调用 greet(),而不需要通过 helper.greet() 来引用。
在 from helper import testfunc 中,我们只需要输入 testfunc() 来使用它,而在 import helper 中,我们需要输入 helper.testfunc()。
然而,在更大、更复杂的应用中,使用 from helper import testfunc 更容易导致命名空间冲突——即不小心覆盖了另一个同名的函数或变量。
相反,使用 import helper 则不会不小心覆盖同名的函数或变量,因为它是以命名空间的形式存在(helper.testfunc)。
“from X import Y” VS “from X import *”
from helper import testfunc 只导入 testfunc 函数。
而 from helper import * 会导入 helper.py 中的所有内容。
虽然 from helper import * 看起来起初更方便,但实际上它被认为是一种不好的实践。
当我们使用 from helper import * 时,我们导入了 helper.py 中的所有内容,这也意味着某些导入的函数/变量可能会不小心覆盖现有的同名函数/变量。
因此,通常更好的做法是明确声明我们具体要导入什么,而不是导入文件中的所有内容。
__import__用于动态导入
这使我们可以通过字符串动态导入模块。
sys.path和导入来源
当我们导入内容时,Python 会有一个文件夹列表用于查找。我们可以通过打印 sys.path 来查看这个文件夹列表。
可以手动向 sys.path添加路径
sys.path 是一个字符串列表,Python 会从 sys.path 中的路径查找模块。假设我们需要从 /home/temp/helper.py 导入某个函数,而我们的工作目录是 /home/main.py,这两个路径是完全不同的。
我们可以简单地将 /home/temp/ 添加到 sys.path 中,这样 Python 就知道我们希望从这个路径中查找模块。一旦将 /home/temp/ 添加到 sys.path,我们就可以顺利地从该目录导入模块。
PEP8 导入顺序
PEP8(Python 增强提案 8)是一份规定 Python 代码风格最佳实践的文档。关于导入理想的顺序应该是:
- 标准库导入,例如 os、sys、json、re
- 相关的第三方库导入,例如 pandas、numpy、fastapi
- 本地库导入,例如我们自定义的模块
并且记得在每一组导入之间添加空行,以提高可读性。
all和从文件“exporting”
特殊的 all 变量控制从文件中导入的内容。helper.py 包含了许多函数,但它有一个 all 变量。
以 _开头的变量在使用 from X import *时不会被导入
__name__during imports
__name__ 是一个特殊变量,用于表示当前模块的名称,当模块被直接运行时,它的值为 'main',否则为模块的文件名。