Python:为什么应该';从<;模块>;进口*';禁止吗?

Python:为什么应该';从<;模块>;进口*';禁止吗?,python,module,namespaces,python-import,Python,Module,Namespaces,Python Import,如果你碰巧有 from <module> import * 我理解为什么一般不鼓励导入*(名称空间不可见性), 但在许多情况下,这将被证明是方便的,尤其是在 代码不与任何人共享 那么,有人能详细解释一下为什么导入的*应该 在所有可能的情况下都被禁止?我认为“在程序中间”指的是函数定义中的导入: def f(): from module import * # not allowed 这是不允许的,因为这会使优化函数体变得太困难。Python实现希望在字节编译函数时知道

如果你碰巧有

from <module> import *
我理解为什么一般不鼓励导入*(名称空间不可见性), 但在许多情况下,这将被证明是方便的,尤其是在 代码不与任何人共享

那么,有人能详细解释一下为什么导入的
*
应该 在所有可能的情况下都被禁止?

我认为“在程序中间”指的是函数定义中的导入:

def f():
    from module import *    # not allowed
这是不允许的,因为这会使优化函数体变得太困难。Python实现希望在字节编译函数时知道函数局部变量的所有名称,以便优化(CPython)虚拟机操作数堆栈上操作的变量引用,或者至少优化局部变量插槽操作,而不是外部名称空间中的查找。如果您可以将模块的全部内容转储到函数的本地命名空间中,那么编译器必须假设函数中的任何名称都可能引用模块全局名称,因为从模块导入*引入的名称列表只有在运行时才知道

将模块导入中的
*
放在顶级声明之间是一种糟糕的风格,但这是允许的:

def f():
    ...

from module import *

def g():
    ...
编辑2013年4月:在研究其他内容时,我发现Python 2.1中引入了此限制,这是()的结果。引用链接:

更改的一个副作用是,在某些情况下,函数范围内的
from module import*
exec
语句被设置为非法。Python参考手册一直说,模块导入的
*
仅在模块的顶层是合法的,但CPython解释器以前从未强制执行过这一点。作为嵌套作用域实现的一部分,将Python源代码转换为字节码的编译器必须生成不同的代码来访问包含作用域中的变量<来自模块导入*和
exec
的code>使编译器无法理解这一点,因为它们向本地名称空间添加了在编译时不可知的名称。因此,如果函数包含带有自由变量的函数定义或
lambda
表达式,编译器将通过引发
SyntaxError
异常来对此进行标记

这澄清了评论中讨论的Python3.x与2.x行为。它总是与语言规范相反,但是CPython 2.1到2.7只会在函数中为模块导入*中的
发出错误,如果这可能会影响编译器了解变量是在本地绑定还是在包含范围内绑定的能力。在3.x中,它被提升为无条件错误

编辑之子:。。。显然,flashk在几年前的另一个回答中指出了这一点,引用了“Python2.1中的新功能”的同一段话。你们现在就去投票吧。

这似乎解释了为什么存在这种限制:

改变的一个副作用是 来自模块import*和exec 声明被定为非法 在某个函数范围内 条件Python参考 手册上一直这样说 模块导入*仅在 模块的顶层,但CPython 解释器从未强制执行过这一点 之前作为实施的一部分 对于嵌套作用域,编译器 将Python源代码转换为字节码 生成不同的代码以访问 包含范围中的变量。从…起 模块导入*并执行 编译器无法理解 这是不可能的,因为他们在 包含的本地命名空间 在编译时不可知。所以,, 如果函数包含函数 定义或lambda表达式 自由变量,编译器将标记 这是通过提出一个SyntaxError实现的 例外


这一点也不禁止。它工作正常,但你会得到警告,因为这通常是一个坏主意(因为其他人已经考虑过的原因)。如果愿意,可以取消显示警告;警告模块正是您想要的。

在任何词汇级别上,amodule import*
中的
都是一个“当时似乎是个好主意”的设计决策,在现实生活中被证明是一场真正的灾难,除了交互式解释器提示下的便捷探索之外(即使如此,我对它也不太感兴趣--
导入模块,因为m
只强制使用两个额外的字符来代替限定名[[只是一个
m.
前缀]],并且限定名称总是比裸名称更清晰、更灵活,更不用说在探索性交互情况下使用
m
可用于
help(m)
reload(m)
,等等!)的巨大用处了

这种乱七八糟的结构使得穷人阅读代码变得非常困难(通常是为了帮助调试代码)要理解神秘出现的名称来自何处——不可能,如果该结构在词汇层面上使用了不止一次;但即使只使用了一次,它也会迫使人们每次都费力地重新阅读整个模块,然后才能说服自己,是的,脏兮兮的裸名必须来自该模块

另外,模块作者通常不会为了“支持”这个令人毛骨悚然的结构而付出极大的努力。如果您的代码中有某个地方使用了
sys.argv
(当然,在模块的最顶端有一个
import sys
),您如何知道
sys
是它应该是的模块…还是来自
…import*
?的某个完全不同的模块(或非模块)?乘以您正在使用的所有限定名称,痛苦是唯一的最终结果——这是一个神秘的错误
def f():
    ...

from module import *

def g():
    ...