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

标签 python module namespaces python-import

如果你碰巧有

from <module> import *

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

/tmp/foo:100: SyntaxWarning: import * only allowed at module level

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

那么,谁能详细解释一下为什么from <module> import *应该 在所有可能的情况下都被禁止?

最佳答案

我相信“在你的程序中间”你是在谈论一个导入inside一个函数定义:

def f():
    from module import *    # not allowed

这是不允许的,因为它会使优化函数体变得过于困难。 Python 实现在对函数进行字节编译时想要知道函数局部变量的所有名称,以便它可以将变量引用优化为(CPython)虚拟机的操作数堆栈上的操作,或者至少优化到局部变量槽操作而不是在外部命名空间中查找。如果您可以将模块的全部内容转储到函数的本地命名空间中,那么编译器将不得不假设函数中的 any 名称可能引用模块全局,因为名称列表带来in by from module import * 只在运行时知道。

from module import * 放在 顶级声明之间是不好的风格,但这是允许的:

def f():
    ...

from module import *

def g():
    ...

2013 年 4 月编辑: 在研究其他内容时,我发现这个限制是在 Python 2.1 中引入的,这是 "Nested Scopes" feature 的结果。 (PEP 227)。引用链接:

One side effect of the change is that the from module import * and exec statements have been made illegal inside a function scope under certain conditions. The Python reference manual has said all along that from module import * is only legal at the top level of a module, but the CPython interpreter has never enforced this before. As part of the implementation of nested scopes, the compiler which turns Python source into bytecodes has to generate different code to access variables in a containing scope. from module import * and exec make it impossible for the compiler to figure this out, because they add names to the local namespace that are unknowable at compile time. Therefore, if a function contains function definitions or lambda expressions with free variables, the compiler will flag this by raising a SyntaxError exception.

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

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

关于Python:为什么要禁止 'from <module> import *'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3571514/

相关文章:

python - 标准库中最有用的 Python 模块?

html - 如何使用竞争 "scopes"命名 OOCSS 类?

namespaces - 为什么在查询本体时我们必须加载本体,还要提供它的命名空间?

python3 linux - 检测没有root按下的键盘键

javascript - 估计服务器上的客户端字体渲染大小?

python - 如何与主管一起运行 ElastAlert

c++ - 对命名空间和函数参数的好奇

python - 在函数调用中混合 *vargs 和 **kargs 参数

linux - PDF::使用 cpan linux 命令创建模块安装失败?

css - Yii:在模块级别集成 CSS 文件