在Python中,使用通配符导入所有属性是一个好习惯吗?

时间:2013-01-31 13:15:33

标签: python

为什么?

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

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

5 个答案:

答案 0 :(得分:5)

使用from module import *通常不是一个好主意。通配符导入导致命名空间污染;您导入的名称多于您需要的名称,如果您不小心引用了导入的名称,则可能无法获得所需的NameError。

此外,如果该库的未来版本添加了其他名称,您最终可能屏蔽其他名称,从而导致陌生人的错误:

from foo import bar
from spam import *

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

答案 1 :(得分:3)

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

foo.py

import sys
os = sys # just for the fun of it... :-D

python console

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