如果你碰巧有
from <module> import *
在您的程序(或模块)的中间,您会收到警告:
/tmp/foo:100: SyntaxWarning: import * only allowed at module level
我理解为什么import *
一般不鼓励(命名空间不可见),但在许多情况下它会被证明是方便的,特别是在代码不与任何人共享的情况下。
那么,谁能详细解释为什么from <module> import *
在所有可能的情况下都应该被禁止?
如果你碰巧有
from <module> import *
在您的程序(或模块)的中间,您会收到警告:
/tmp/foo:100: SyntaxWarning: import * only allowed at module level
我理解为什么import *
一般不鼓励(命名空间不可见),但在许多情况下它会被证明是方便的,特别是在代码不与任何人共享的情况下。
那么,谁能详细解释为什么from <module> import *
在所有可能的情况下都应该被禁止?
我相信“在你的程序中间”你是在谈论函数定义中的导入:
def f():
from module import * # not allowed
这是不允许的,因为它会使优化函数体变得过于困难。Python 实现在对函数进行字节编译时想要知道函数局部变量的所有名称,以便它可以将变量引用优化为(CPython)虚拟机的操作数堆栈上的操作,或者至少优化到局部变量槽操作而不是在外部命名空间中查找。如果您可以将模块的全部内容转储到函数的本地命名空间中,那么编译器将不得不假设函数中的任何名称都可能引用模块全局,因为引入的名称列表from module import *
仅在运行时才知道.
在顶级声明from module import *
之间插入是一种糟糕的风格,但它是允许的:
def f():
...
from module import *
def g():
...
编辑 2013 年 4 月:在研究其他内容时,我发现这个限制是在 Python 2.1 中引入的,这是由于“嵌套范围”功能(PEP 227)的结果。引用链接:
更改的一个副作用是在某些条件下,
from module import *
andexec
语句在函数范围内是非法的。Python 参考手册一直说这from module import *
仅在模块的顶层是合法的,但 CPython 解释器以前从未强制执行此操作。作为嵌套作用域实现的一部分,将 Python 源代码转换为字节码的编译器必须生成不同的代码来访问包含作用域中的变量。from module import *
并且exec
使编译器无法弄清楚这一点,因为它们将名称添加到在编译时不可知的本地名称空间。因此,如果函数包含lambda
带有自由变量的函数定义或表达式,编译器将通过引发SyntaxError
异常来标记这一点。
这阐明了评论中讨论的 Python 3.x 与 2.x 行为。它总是与语言规范相反,但 CPython 2.1 到 2.7 只有from module import *
在可能影响编译器知道变量是在本地绑定还是在包含范围内绑定的能力时才会在函数内发出错误。在 3.x 中,它已被提升为无条件错误。
编辑之子: ......显然 flashk 几年前在另一个答案中指出了这一点,引用了“Python 2.1 中的新功能”的同一段。你们现在都去投票。
在任何词汇层面,from amodule import *
“当时似乎是个好主意”的设计决策在现实生活中被证明是一场真正的灾难,除了在交互式解释器提示下的方便探索(即使那样,我也不太热在它上面 -import module as m
只强制两个额外的字符使用限定名称而不是 [[只是一个m.
前缀]],并且限定名称总是比裸名称更清晰和更灵活,更不用说在探索性交互情况下具有m
可用于help(m)
, reload(m)
,的巨大有用性之类的!)。
这种肮脏的构造使得阅读代码的穷人(通常是为了帮助调试它)很难理解神秘出现的名字来自哪里——如果构造被多次使用,这是不可能的词汇层面;但即使只使用一次,它每次都迫使人们费力地重新阅读整个模块,然后才能说服自己,是的,那个邋遢的裸名必须来自模块。
另外,模块作者通常不会去“支持”有问题的可怕结构所需的极端麻烦。如果在你的代码中的某个地方你有一个使用sys.argv
(import sys
当然,在你的模块的最顶部),你怎么知道它sys
应该是模块......或者一些完全不同的模块(或非模块)来自... import *
?!将其乘以您使用的所有限定名称,痛苦是唯一的最终结果——那,以及需要长时间、费力调试的神秘错误(通常是在“获得”Python的人不情愿的帮助下......!- )。
在 function中,添加和覆盖任意本地名称的方法会更糟。作为一项基本但至关重要的优化,Python 编译器在函数体中查找每个裸名上的任何赋值或其他绑定语句,并将其看到的那些名称视为“本地”(其他名称必须是全局或内置)。使用 an import *
(就像使用exec somestring
没有明确的 dicts 用作命名空间一样),突然之间,哪些名称是本地的,哪些名称是全局的就变成了一个完全的谜团——因此糟糕的编译器将不得不对每个名称查找采取最慢的策略,对局部变量使用字典(而不是它通常使用的紧凑“向量”),并一遍又一遍地为每个引用的裸名执行多达三个字典查找。
转到任何 Python 交互式提示。键入import this
。你看到了什么?Python之禅。这段文字中最后一点,可能也是最伟大的智慧是什么……?
命名空间是一个很棒的想法——让我们做更多的事情!
通过在限定名称非常可取的情况下强制使用准名称,您实际上是在做与这个明智的建议完全相反的事情:与其欣赏名称空间的伟大和 honkingtude,并做更多的事情,您正在完美地分解两个好的和现成的命名空间(你要导入的模块的命名空间,以及你要导入它的词法范围的命名空间)来制造一个单一的、邪恶的、有缺陷的、缓慢的、僵硬的、无法使用的混乱。
如果我可以回去更改Python 中的一个早期设计决策(这是一个艰难的选择,因为使用Javascript def
,尤其是lambda
对于更易读的 Javascript 调用function
是紧随其后的;-),我会追溯消除import *
Guido 的想法头脑。在交互式提示下,任何所谓的探索便利都无法平衡它所造成的邪恶……!-)
Python 2.1的发行说明似乎解释了为什么存在这个限制:
更改的一个副作用是 from module import * 和 exec 语句在某些条件下在函数范围内被设为非法。Python 参考手册一直说 from module import * 仅在模块的顶层是合法的,但 CPython 解释器以前从未强制执行此操作。作为嵌套作用域实现的一部分,将 Python 源代码转换为字节码的编译器必须生成不同的代码来访问包含作用域中的变量。from module import * 和 exec 使编译器无法弄清楚这一点,因为它们将名称添加到编译时不知道的本地名称空间。因此,如果函数包含带有自由变量的函数定义或 lambda 表达式,
不禁止,因为...
...它对于快速脚本和 shell 探索非常方便。
...但你不应该把它放在任何严肃的代码中
它根本没有被禁止。它工作正常,但您会收到警告,因为这通常是一个坏主意(出于其他原因)。如果愿意,您可以取消警告;警告模块就是你想要的。
其他人已经给出了深入的答案,我将给出我的理解的简短概述答案..当使用 from 你正在制作它时,你可以直接调用你导入的模块中的任何函数,而无需执行 modulename.functioname (你可以调用“functionname”)如果您在不同的模块中有 2 个同名的函数,这会产生问题,并且在处理大量函数时也会造成混淆,因为您不知道它属于哪个对象/模块(从某人正在查看不熟悉的已编写代码)