Python:为什么要禁止'from <module> import*'?

OTZ*_*OTZ 28 python namespaces module python-import

如果你碰巧有

from <module> import *
Run Code Online (Sandbox Code Playgroud)

在程序(或模块)的中间,您将收到警告:

/tmp/foo:100: SyntaxWarning: import * only allowed at module level
Run Code Online (Sandbox Code Playgroud)

我理解为什么import *一般不鼓励(命名空间不可见),但在很多情况下它会证明是方便的,特别是在代码不与任何人共享的情况下.

那么,任何人都可以准确地详细解释为什么from <module> import *在所有可能的情况下都应该禁止?

zwo*_*wol 26

我相信"在你的程序的中间"你是在谈论一个导入内部函数定义:

def f():
    from module import *    # not allowed
Run Code Online (Sandbox Code Playgroud)

这是不允许的,因为它会使功能的主体过于优化.Python实现想要在字节编译函数时知道函数局部变量的所有名称,以便它可以优化变量引用到(CPython)虚拟机的操作数堆栈上的操作,或者至少到本地变量槽.操作而不是外部命名空间中的查找.如果您可以将模块的全部内容转储到函数的本地名称空间中,那么编译器必须假定函数中的任何名称都可能引用模块全局,因为引入的名称列表from module import *仅在运行时已知.

from module import * 之间在顶层声明是作风不好,但它是允许的:

def f():
    ...

from module import *

def g():
    ...
Run Code Online (Sandbox Code Playgroud)

编辑2013年4月:在研究其他内容时,我发现这种限制是在Python 2.1中引入的,这是"嵌套范围"功能(PEP 227)的结果.引用链接:

这种变化的一个副作用是在某些条件下,from module import *exec语句在函数范围内被认为是非法的.Python参考手册一直表示from module import *只在模块的顶层合法,但CPython解释器以前从未强制执行过.作为嵌套作用域实现的一部分,将Python源转换为字节码的编译器必须生成不同的代码来访问包含作用域中的变量.from module import *exec使其无法编译器摸不着头脑,因为他们的名字添加到本地命名空间是在编译时不可知.因此,如果函数包含函数定义或lambda带有自由变量的表达式,编译器将通过引发SyntaxError异常来标记此函数.

这澄清了评论中讨论的Python 3.x vs 2.x行为.它始终与语言规范相反,但CPython 2.1到2.7只会from module import *在函数内发出错误,如果它可能影响编译器知道变量是在本地绑定还是在包含范围内绑定的能力.在3.x中,它已被提升为无条件错误.

SON OF EDIT: ......显然,flashk在几年前在另一个答案中指出了这一点,引用了同一段"Python 2.1中的新功能".你们现在都去投票了.

  • 谢谢分析,扎克.似乎:(1)如果函数体中没有或没有任何嵌套块,则允许在函数体中使用`import*`(带警告); (2)尽管Python文档说除了模块的顶层之外不允许它,但它永远不会被强制执行(即,仍然可能); (3)如果字节编译器可以执行模块,因此它知道所有变量和函数,那么优化就不会有问题; (4)只是向我展示嵌套作用域Python的错误示例. (3认同)

Ale*_*lli 16

在任何词汇层面,from amodule import *是"在当时似乎是一个好主意"已经证明一个真正的灾难在现实生活中的设计决策,与可能得心应手探索在交互式解释提示(即使这样的异常,我不太热它- import module as m力量只有两个额外的字符,使用合格的名称,而不是[只是一个m.前缀],以及合格的名称始终是清晰和更灵活的比barenames,更不用说具有探索性的互动情况大用处mhelp(m),reload(m),之类的!).

这浑身脏兮兮的构造使得它很难,为贫穷的人阅读的代码(通常在一个注定试图帮助调试吧)明白的地方神秘地显现名字的来源 - 是不可能的,如果构造是用来不止一次在词汇水平; 但是,即使只使用一次,它也会强制重新读取整个模块,每次都可以说服自己,是的,那个脏兮兮的名字必须来自模块.

此外,模块作者通常不会遇到"支持"有问题的可怕构造所需的极端麻烦.如果某个地方你的代码中有,比方说,一个使用的sys.argv(和import sys你的模块的最顶部,当然),你怎么知道sys是模块应该...或者一些完全不同的一个(或一非模块)来自... import *?!乘上所有合格的名称,你正在使用,并且痛苦是唯一的最终结果-这一点,神秘的错误,需要长期,艰苦的调试(通常与别人的不情愿帮助谁 "得到"巨蟒...! - ).

在函数中,添加和覆盖任意本地名称的方法会更糟.作为一个基本的,但重要的优化,Python的编译器环视功能的身体上的每个barename任何转让或其他具有约束力的声明,并认为"地方",因而它看到分配(其余必须是全局或内置插件)的名字.随着import *(就像有exec somestring没有明确的类型的字典的命名空间使用),突然就变成了总谜,其中名称是局部的,其名称是全球-所以穷人编译器将不得不求助于最慢的可能策略为每名查找,使用dict作为局部变量(而不是它通常使用的紧凑"矢量"),并为每个引用的裸名称执行最多三次dict查找,一遍又一遍.

转到任何Python交互式提示.类型import this.你看到了什么?Python的禅宗.该文中最后也可能是最伟大的智慧是什么?

命名空间是一个很棒的主意 - 让我们做更多的事情吧!

通过强制使用barenames,其中合格的名称是如此远远优于,你基本上做很这一明智的建议:与其羡慕的命名空间的伟大和honkingtude,做更多的这些,你打破完美2好的和随时可用的命名空间(你要导入的模块,以及你导入它的词法范围的命名空间)来制作一个单一的,不圣洁的,错误的,缓慢的,刚性的,无法使用的混乱.

如果我可以回过头来改变Python中的一个早期设计决策(这是一个很难的选择,因为使用Jxt def,尤其lambda是Javascript更可读的function是紧随其后的第二个;-),我会追溯地消除import *Guido的想法心神.在交互式提示中,没有任何据称的探索便利可以平衡它所造成的邪恶数量......! - )

  • "为什么要消除这种便利?" - 它在法律界被称为"有吸引力的滋扰":一种所谓的"便利",它诱使人们撤消(在这种情况下,与我所展示的关键Python原则完全相反).Python通常很擅长,但是`... import*`是一个不幸的例外.例如,只要看看它在SO上出现的所有情况,你就会开始看到它存在的错误,困难和困惑的滋生地.你不惜一切代价想要简洁吗?然后Python不适合你 - 力量,清晰度,优雅,是的,极端简洁,**不**. (5认同)

fla*_*shk 12

Python 2.1发行说明似乎解释了为什么存在这种限制:

更改的一个副作用是,在某些条件下,from module import*和exec语句在函数作用域内变为非法.Python参考手册一直表示,模块导入*仅在模块的顶层是合法的,但CPython解释器之前从未强制执行过.作为嵌套作用域实现的一部分,将Python源转换为字节码的编译器必须生成不同的代码来访问包含作用域中的变量.来自模块import*和exec使得编译器无法解决这个问题,因为它们会在编译时向本地命名空间添加名称,这些名称是不可知的.因此,如果函数包含函数定义或带有自由变量的lambda表达式,