3

为什么?

有时我需要导入模块的所有属性,所以我使用通配符导入,但我的一个 Vim 脚本(使用 flake8 作为其语法检查器)总是给我一个警告并告诉我无法检测到未定义的名称。

使用通配符导入还有其他缺点吗?

4

5 回答 5

5

通常使用from module import *. 通配符导入导致命名空间污染;您导入的名称超出了您的需要,如果您不小心引用了导入的名称,您可能不会得到您想要的 NameError。

此外,如果该库的未来版本添加了其他名称,您最终可能会屏蔽其他名称,这仍然会导致奇怪的错误:

from foo import bar
from spam import *

如果您升级spam并且它现在包含 a spam.bar,它将替换foo.bar上面一行中的导入。

于 2013-01-31T13:19:16.977 回答
3

使用通配符导入可能会导致细微的错误:

foo.py

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'

这在更新库版本时尤其重要。他们可能会也可能不会添加新变量并以可怕的方式破坏您的代码。

如果您真的想使用*导入,请始终将其放在首位,以便其他导入和定义优先。

于 2013-01-31T13:22:03.443 回答
2

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_hashbaror bazor的一部分qux。这使得追踪变得更加困难。此外,如果您知道函数最初是在哪里定义的,这会给您一些关于它应该做什么的提示,这可以使代码更易于阅读。

于 2013-01-31T14:03:14.990 回答
2

到目前为止很好的答案,但总是很高兴参考PyDocs

尽管某些模块设计为在您使用 import * 时仅导出遵循某些模式的名称,但在生产代码中仍被认为是不好的做法。

于 2013-01-31T13:20:18.330 回答
0

是的,如果您使用通配符导入所有内容,则从该包中获取所有内容并将其转换为脚本中的实例,这样做的更好方法是简单地导入包:

前任。导入包

package.x

这样你就不会遇到命名问题。

于 2013-01-31T13:19:40.237 回答