为什么?
有时我需要导入模块的所有属性,所以我使用通配符导入,但我的一个 Vim 脚本(使用 flake8 作为其语法检查器)总是给我一个警告并告诉我无法检测到未定义的名称。
使用通配符导入还有其他缺点吗?
为什么?
有时我需要导入模块的所有属性,所以我使用通配符导入,但我的一个 Vim 脚本(使用 flake8 作为其语法检查器)总是给我一个警告并告诉我无法检测到未定义的名称。
使用通配符导入还有其他缺点吗?
通常使用from module import *
. 通配符导入导致命名空间污染;您导入的名称超出了您的需要,如果您不小心引用了导入的名称,您可能不会得到您想要的 NameError。
此外,如果该库的未来版本添加了其他名称,您最终可能会屏蔽其他名称,这仍然会导致奇怪的错误:
from foo import bar
from spam import *
如果您升级spam
并且它现在包含 a spam.bar
,它将替换foo.bar
上面一行中的导入。
使用通配符导入可能会导致细微的错误:
import sys
os = sys # just for the fun of it... :-D
>>> import os
>>> from foo import *
>>> os.path.join('p1', 'p2')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'join'
这在更新库版本时尤其重要。他们可能会也可能不会添加新变量并以可怕的方式破坏您的代码。
如果您真的想使用*
导入,请始终将其放在首位,以便其他导入和定义优先。
Martijn的答案正确地解决了命名空间污染的问题,但我认为这里的任何答案都没有正确解决我认为是最大的问题......它不是明确的。
考虑一个假设的模块:
#foo.py
from bar import *
from baz import *
from qux import *
def breakfast(x):
with corn_beef_hash(x) as yummy:
for egg in yummy:
yield ham(egg.scrambled)
现在几个月后,你似乎不记得corn_beef_hash
实际做了什么,所以你去查看文档——除了你不记得是否corn_beef_hash
是bar
or baz
or的一部分qux
。这使得追踪变得更加困难。此外,如果您知道函数最初是在哪里定义的,这会给您一些关于它应该做什么的提示,这可以使代码更易于阅读。
到目前为止很好的答案,但总是很高兴参考PyDocs:
尽管某些模块设计为在您使用 import * 时仅导出遵循某些模式的名称,但在生产代码中仍被认为是不好的做法。
是的,如果您使用通配符导入所有内容,则从该包中获取所有内容并将其转换为脚本中的实例,这样做的更好方法是简单地导入包:
前任。导入包
package.x
这样你就不会遇到命名问题。