建议不要在Python中使用import *
。
任何人都可以分享原因,以便下次可以避免吗?
答案 0 :(得分:192)
因为它会在你的命名空间中放入很多东西(可能会影响之前导入的其他一些对象,你不会知道它)。
因为您不确切知道导入的内容,并且无法轻易找到导入某个内容的模块(可读性)。
因为您无法使用像pyflakes
这样的酷工具来静态检测代码中的错误。
答案 1 :(得分:40)
答案 2 :(得分:36)
您没有将**locals()
传递给函数,是吗?
由于Python缺少“include”语句,和 self
参数是显式的,和作用域规则非常简单,通常很容易指出一个变量的指针,告诉那个对象来自哪里 - 没有阅读其他模块,也没有任何类型的IDE(无论如何,这些都是内省的,因为语言是非常动态的。)
import *
打破了这一切。
此外,它具有隐藏错误的具体可能性。
import os, sys, foo, sqlalchemy, mystuff
from bar import *
现在,如果条形模块具有任何“os
”,“mystuff
”等属性,它们将覆盖显式导入的属性,并可能指向非常不同的东西。在bar中定义__all__
通常是明智的 - 这说明将隐式导入的内容 - 但仍然很难跟踪对象的来源,而无需读取和解析条形模块并跟随其导入。当我获得项目的所有权时,import *
的网络是我解决的第一件事。
不要误解我:如果遗失import *
,我会哭的。但必须谨慎使用。一个很好的用例是在另一个模块上提供外观界面。
同样,使用条件导入语句或在函数/类命名空间内导入需要一些纪律。
我认为在大中型项目中,或者有几个贡献者的小型项目,在静态分析方面需要最少的卫生 - 至少运行pyflakes或更好地配置正确的pylint - 以捕获几种在它们发生之前的错误。
当然,因为这是python - 随意破坏规则和探索 - 但要警惕可能增长十倍的项目,如果源代码缺少纪律,那将是一个问题。
答案 3 :(得分:15)
那是因为你正在污染命名空间。您将导入自己的命名空间中的所有函数和类,这可能与您自己定义的函数冲突。
此外,我认为使用合格的名称对于维护任务更为明确;你可以在代码行上看到函数的来源,这样你就可以更容易地查看文档了。
在模块foo中:
def myFunc():
print 1
在您的代码中:
from foo import *
def doThis():
myFunc() # Which myFunc is called?
def myFunc():
print 2
答案 4 :(得分:15)
可以在交互式会话中执行from ... import *
。
答案 5 :(得分:10)
http://docs.python.org/tutorial/modules.html
请注意,一般来说,从模块或包中导入
*
的做法是不受欢迎的,因为它经常导致可读性差的代码。
答案 6 :(得分:7)
假设您在名为foo的模块中有以下代码:
import ElementTree as etree
然后在你自己的模块中你有:
from lxml import etree
from foo import *
你现在有一个难以调试的模块看起来像它有lxml的etree,但实际上却有ElementTree。
答案 7 :(得分:6)
这些都是很好的答案。我要补充说,在用Python编写新人代码时,处理import *
非常困难。即使你或他们没有编写代码,它仍然是一个绊脚石。
我教孩子们(大约8岁)用Python编程来操纵Minecraft。我想给他们一个有用的编码环境来处理(Atom Editor)并教授REPL驱动的开发(通过bpython)。在Atom中,我发现提示/完成的效果与bpython一样有效。幸运的是,与其他一些统计分析工具不同,Atom不会被import *
愚弄。
但是,让我们举个例子......在this wrapper中他们from local_module import *
包含this list of blocks一堆模块。让我们忽略名称空间冲突的风险。通过执行from mcpi.block import *
,他们可以制作完整的模块类型列表,您必须查看这些块以了解可用的内容。如果他们使用了from mcpi import block
,那么您可以输入walls = block.
,然后会弹出自动填充列表。
答案 8 :(得分:4)
理解人们放在这里的有效点。但是,我确实有一个论点,有时候,“明星导入”可能并不总是一个坏习惯:
const.py
的模块:
import const
,那么对于每个常数,我必须将其称为const.SOMETHING
,这可能不是最方便的方式。from const import SOMETHING_A, SOMETHING_B ...
,那么显然它太冗长并且违背了结构化的目的。from const import *
可能是更好的选择。答案 9 :(得分:2)
这是一种非常糟糕的做法有两个原因:
第1点: 让我们看一个例子:
from module1 import *
from module2 import *
from module3 import *
a = b + c - d
在这里,看到代码时,没有人会知道b
,c
和d
实际属于哪个模块。
另一方面,如果你这样做:
# v v will know that these are from module1
from module1 import b, c # way 1
import module2 # way 2
a = b + c - module2.d
# ^ will know it is from module2
对你来说更加清洁,加入你团队的新人也会有更好的想法。
对于第2点:请说module1
和module2
变量为b
。当我这样做时:
from module1 import *
from module2 import *
print b # will print the value from module2
此处module1
的值丢失了。即使在b
中声明了module1
并且我编写了期望我的代码使用module1.b
如果在不同的模块中有相同的变量,并且您不想导入整个模块,您甚至可以这样做:
from module1 import b as mod1b
from module2 import b as mod2b
答案 10 :(得分:2)
作为测试,我创建了一个带有2个函数A和B的模块test.py,它们分别打印" A 1"和" B 1"。导入test.py后:
import test
。 。 。我可以运行2个函数作为test.A()和test.B(),以及" test"在命名空间中显示为模块,因此如果我编辑test.py,我可以使用以下命令重新加载:
import importlib
importlib.reload(test)
但如果我这样做:
from test import *
没有提及"测试"在命名空间中,所以在编辑后没有办法重新加载它(据我所知),这是交互式会话中的一个问题。鉴于以下任何一种情况:
import test
import test as tt
将添加" test"或" tt" (分别)作为命名空间中的模块名称,这将允许重新加载。
如果我这样做:
from test import *
名字" A"和" B"在命名空间中显示为函数。如果我编辑test.py并重复上述命令,则不会重新加载函数的修改版本。
以下命令会引发错误消息。
importlib.reload(test) # Error - name 'test' is not defined
如果有人知道如何从模块导入*"重新加载装有"的模块,请发布。否则,这将是避免形式的另一个原因:
from module import *
答案 11 :(得分:1)
按照文档中的建议,永远不要在生产代码中使用import *
。
虽然从模块导入*
不好,但importing * from a package却更糟。基本上,from package import *
导入由包的__init__.py
定义的任何名称,但是它还包括以前的import
语句加载的包的任何子模块。
考虑以下示例:
# anywhere in the code before import *
import sound.effects.echo
import sound.effects.surround
# in your module
from sound.effects import *
最后一条语句会将echo
和surround
模块导入当前名称空间(可能会覆盖先前的定义),因为它们是在sound.effects
包中在import
时定义的语句已执行。