我试图找到一个全面的指南,是否最好使用导入模块或从模块导入。我刚刚开始学习Python,我正试图从最佳实践开始。
基本上,我希望任何人都能分享他们的经验,其他开发者有什么偏好,以及避免任何陷阱的最佳方法是什么?
我试图找到一个全面的指南,是否最好使用导入模块或从模块导入。我刚刚开始学习Python,我正试图从最佳实践开始。
基本上,我希望任何人都能分享他们的经验,其他开发者有什么偏好,以及避免任何陷阱的最佳方法是什么?
当前回答
我刚刚发现这两种方法之间还有一个微妙的区别。
如果模块foo使用以下导入:
from itertools import count
这样,模块bar就会错误地使用count,就好像它是在foo中定义的,而不是在itertools中定义的一样:
import foo
foo.count()
如果foo使用:
import itertools
这种错误仍有可能发生,但不太可能发生。酒吧需要:
import foo
foo.itertools.count()
这给我带来了一些麻烦。我有一个模块错误地从一个没有定义它的模块导入了一个异常,只从其他模块导入了它(使用from module import SomeException)。当不再需要导入并删除时,出现问题的模块就被破坏了。
其他回答
简单地说,这都是为了方便程序员。在核心级别,它们只是导入模块的所有功能。
import module:当你使用import module时,你必须写module.method()来使用这个模块的方法。每次使用任何方法或属性时,都必须引用模块。
from module import all:当你使用from module import all而不是使用该模块的方法时,你只需要编写method()而不引用该模块。
我还想补充一点。如果遇到循环导入,了解Python如何将导入的模块作为属性处理可能会很有用。
我有以下结构:
mod/
__init__.py
main.py
a.py
b.py
c.py
d.py
我将使用不同的导入方法从main.py导入其他模块
main.py:
import mod.a
import mod.b as b
from mod import c
import d
Dis.dis显示了两者的区别(注意模块名,a b c d):
1 0 LOAD_CONST 0 (-1)
3 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (mod.a)
9 STORE_NAME 1 (mod)
2 12 LOAD_CONST 0 (-1)
15 LOAD_CONST 1 (None)
18 IMPORT_NAME 2 (b)
21 STORE_NAME 2 (b)
3 24 LOAD_CONST 0 (-1)
27 LOAD_CONST 2 (('c',))
30 IMPORT_NAME 1 (mod)
33 IMPORT_FROM 3 (c)
36 STORE_NAME 3 (c)
39 POP_TOP
4 40 LOAD_CONST 0 (-1)
43 LOAD_CONST 1 (None)
46 IMPORT_NAME 4 (mod.d)
49 LOAD_ATTR 5 (d)
52 STORE_NAME 5 (d)
55 LOAD_CONST 1 (None)
最后它们看起来是一样的(STORE_NAME在每个例子中都是result),但如果你需要考虑以下四个循环导入,这是值得注意的:
例二
foo/
__init__.py
a.py
b.py
a.py:
import foo.b
b.py:
import foo.a
>>> import foo.a
>>>
这是
example2
bar/
__init__.py
a.py
b.py
a.py:
import bar.b as b
b.py:
import bar.a as a
>>> import bar.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "bar\a.py", line 1, in <module>
import bar.b as b
File "bar\b.py", line 1, in <module>
import bar.a as a
AttributeError: 'module' object has no attribute 'a'
没说
青年们
baz/
__init__.py
a.py
b.py
a.py:
from baz import b
b.py:
from baz import a
>>> import baz.a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "baz\a.py", line 1, in <module>
from baz import b
File "baz\b.py", line 1, in <module>
from baz import a
ImportError: cannot import name a
类似的问题……但显然,从x导入y并不等于从y导入x
example4
qux/
__init__.py
a.py
b.py
a.py:
import b
b.py:
import a
>>> import qux.a
>>>
这个也可以
@ahfx已经提到了这些导入的一个关键方面,即加载模块过程的内部。如果你的系统需要使用循环导入(例如,你想在一些流行的http框架中使用依赖注入),就会弹出这个窗口。在这种情况下,from {module} import {function}对于加载过程如何进行的要求显得更加激进。让我们举个例子:
#m1.py:
print('--start-m1--')
from m2 import * # form does not matter; just need to force import of m2
print('--mid-m1--')
def do1(x):
print(x)
print('--end-m1--')
进口
#m2.py
print('--start-m2--')
# from m1 import * # A
# from m1 import do1 # B
# import m1 # C
# D -- no import of "do1" at all
print('--mid-m2--')
def do2(x):
m1.do1(x)
print('--end-m2--')
通过运行
#main.py:
from m1 import do1
do1('ok')
在m2.py (A,B,C,D)中的所有导入选项中,from {module} import {function}是唯一会导致加载过程崩溃的选项,导致臭名昭著的(CPython 3.10.6)
ImportError: cannot import name 'do1' from partially initialized module 'm1'
(most likely due to a circular import)
虽然我不能说为什么会发生这种情况,但似乎从……进口…语句对有问题的模块已经处于初始化过程的“多远”提出了更严格的要求。
我个人总是用
from package.subpackage.subsubpackage import module
然后访问所有
module.function
module.modulevar
等。原因是,与此同时,您可以进行简短的调用,并且可以清楚地定义每个例程的模块名称空间,如果您必须在源代码中搜索给定模块的使用情况,这是非常有用的。
不用说,不要使用import *,因为它会污染您的命名空间,并且它不会告诉您给定函数来自何处(来自哪个模块)
当然,如果在两个不同的包中对两个不同的模块使用相同的模块名,您可能会遇到麻烦,例如
from package1.subpackage import module
from package2.subpackage import module
在这种情况下,您当然会遇到麻烦,但是强烈地暗示您的包布局有缺陷,您必须重新考虑它。
补充一下人们关于from x import *的说法:除了使名称的来源更加困难之外,这还会使Pylint等代码检查器无法使用。它们将报告这些名称为未定义的变量。