代码之家  ›  专栏  ›  技术社区  ›  OTZ

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

  •  25
  • OTZ  · 技术社区  · 15 年前

    如果你碰巧

    from <module> import *
    

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

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

    我明白为什么 import * 通常不鼓励(命名空间不可见性), 但在许多情况下,这将证明是方便的,特别是在 代码不与任何人共享。

    from <module> import * 应该

    6 回复  |  直到 6 年前
        1
  •  27
  •   zwol    13 年前

    我相信“在你的程序中”你是在说一个进口 里面 函数定义:

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

    任何 函数中的名称可能引用全局模块,因为 from module import * 只有在运行时才知道。

    从模块导入* 介于两者之间 顶级声明的风格很差,但它是允许的:

    def f():
        ...
    
    from module import *
    
    def g():
        ...
    

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

    这种变化的一个副作用是 从模块导入* exec 在某些情况下,语句在函数作用域内是非法的。Python参考手册一直这么说 从模块导入* 从模块导入* 使编译器无法理解这一点,因为它们将在编译时不可知的名称添加到本地命名空间中。因此,如果函数包含函数定义或 lambda SyntaxError 例外。

    这澄清了评论中讨论的python3.x对2.x的行为。它总是与语言规范相反,但是cpython2.1到2.7只会为 从模块导入*

    编辑之子:

        2
  •  16
  •   Alex Martelli    15 年前

    在任何词汇层面上, from amodule import * 是一个“当时似乎是个好主意”的设计决策,在现实生活中已经被证明是一场真正的灾难 除了在交互式解释器提示下进行方便的探索(即使这样,我对它也不太感兴趣)-- import module as m 只强制另外两个字符使用限定名[[只是一个 m. 前缀]], 限定名总是比裸名更清晰、更灵活,更不用说在探索性的交互环境中使用限定名的好处了 m help(m) , reload(m)

    这种杂乱无章的结构使得阅读代码的穷人(通常是注定要帮助调试代码的人)很难理解神秘出现的名字是从哪里来的——如果该结构在词汇级别上被多次使用,这是不可能的;但是即使只使用了一次,它也会迫使整个模块费力地重新阅读每次在你说服自己之前,是的,那肮脏的裸名一定来自模块。

    另外,模块作者通常不会去极端麻烦需要“支持”可怕的建设问题。如果在你的代码中有,比如说,使用 sys.argv import sys 当然,在你的模块的最顶端),你怎么看 那个 sys 是模块应该是。。。或者是来自 ... import * ?! 把它乘以你正在使用的所有限定名,痛苦是唯一的结局——那就是,神秘的bug需要长时间、费力的调试(通常是在那些不情愿的人的帮助下) “得到”蟒蛇。。。!-).

    在函数中 ,一种添加和重写任意本地名称的方法会更糟。作为一个基本但至关重要的优化,Python编译器在函数体中查找每个barename上的任何赋值或其他绑定语句,并将它看到的那些被赋值的名称视为“本地的”(其他名称必须是全局的或内置的)。带着一个 import * (就像一个 exec somestring 如果没有显式dict来用作名称空间,那么突然之间,哪些名称是本地的,哪些名称是全局的,就成了一个完全的谜——因此,对于每个名称查找,糟糕的编译器将不得不采用尽可能慢的策略,对局部变量使用dict(而不是它通常使用的紧凑“向量”),并对引用的每个barename反复执行最多三次dict查找。

    转到任何Python交互提示。类型 import this

    名称空间是一个非常好的主意 --让我们做更多的这些!

    在限定名为 更可取的是,你基本上是在做 相反的 关于这一明智的建议:与其欣赏名称空间的伟大和单调,还不如做更多的事情,你是 两个非常好的、随时可用的名称空间(你要导入的模块的名称空间和你要导入的词法作用域的名称空间)构成了一个单一的、不神圣的、有缺陷的、缓慢的、僵硬的、无法使用的混乱。

    如果我能回去换衣服 Python中的早期设计决策(这是一个艰难的选择,因为 def 尤其是 lambda 对于Javascript更容易理解的调用 function 是一个很接近的秒;-),我会追溯到消灭 导入* 吉多的想法。没有多少 在互动提示下探索的便利性可以平衡它造成的邪恶的数量。。。!-)

        3
  •  13
  •   flashk    15 年前

    这个 release notes for Python 2.1 似乎可以解释为什么存在这种限制:

    这种变化的一个副作用是 从模块import*和exec 在某个函数范围内 手册上一直这么说 模块的顶层,但是CPython 口译员从未强制执行过 以前。作为实施的一部分 对于嵌套作用域,编译器 生成不同的代码来访问 模块导入*并执行 这是因为他们给 本地命名空间 编译时不可知的。因此, 自由变量,编译器将标记 这是通过提出一个语法错误 例外。

        4
  •  4
  •   Bite code    15 年前

    ... 它对于快速脚本和shell探索非常方便。

    1. 你不知道代码中使用了什么,很难知道脚本的依赖性
    2. IDE方便的检查,如“this var has not been declared”不能再工作了
        5
  •  1
  •   kindall    15 年前

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

        6
  •  0
  •   Rick    15 年前