为什么?
有时我需要导入模块的所有属性,所以我使用通配符导入,但是我的一个Vim脚本(使用flake8作为其语法检查器)总是给我一个警告并告诉我无法检测到未定义的名称。
使用通配符导入还有其他缺点吗?
答案 0 :(得分:5)
使用from module import *
通常不是一个好主意。通配符导入导致命名空间污染;您导入的名称多于您需要的名称,如果您不小心引用了导入的名称,则可能无法获得所需的NameError。
此外,如果该库的未来版本添加了其他名称,您最终可能屏蔽其他名称,从而导致陌生人的错误:
from foo import bar
from spam import *
如果您升级spam
并且它现在包含spam.bar
,则会替换上面一行中的foo.bar
导入。
答案 1 :(得分:3)
使用通配符导入可能会导致细微的错误:
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'
在更新库版本时,这一点尤其重要。他们可能会也可能不会添加新变量并以可怕的方式破坏您的代码。
如果您真的想使用*
导入,请始终将其放在首位,以便其他导入和定义优先。
答案 2 :(得分:2)
到目前为止答案很好,但总是很高兴参考PyDocs:
虽然某些模块设计为在使用import *时仅导出遵循某些模式的名称,但在生产代码中仍被认为是不好的做法。
答案 3 :(得分:0)
是的,如果您使用通配符导入所有内容,则从该包中取出所有内容并将其转换为脚本中的实例,更好的方法是简单地导入包:
离。 导入包
package.x
通过这种方式,您不会遇到命名问题。
答案 4 :(得分:0)
answer by Martijn正确地解决了命名空间污染问题,但我认为这里的任何答案都没有正确解决我认为最大的问题......它不是显式< / em>的
考虑一个假设的模块:
#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
实际所做的事情所以你去查看文档 - 除了你不记得是否{ {1}}是corn_beef_hash
或bar
或baz
的一部分。这使得追踪变得更加困难。此外,如果你知道最初定义函数的位置,那么它会给你一些关于它应该做什么的提示,这可以使代码更容易阅读。