【问题标题】:Changes in import statement python3导入语句python3的变化
【发布时间】:2012-08-23 18:14:02
【问题描述】:

我听不懂pep-0404下面的内容

在 Python 3 中,包内的隐式相对导入不再是 可用 - 只有绝对导入和显式相对导入 支持的。此外,星型导入(例如 from x import *)仅 在模块级代码中允许。

什么是相对导入? 在 python2 中允许在哪些其他地方进行星形导入? 请举例说明。

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    每当您导入相对于当前脚本/包的包时,就会发生相对导入。

    以下面的树为例:

    mypkg
    ├── base.py
    └── derived.py
    

    现在,您的 derived.py 需要来自 base.py 的内容。在 Python 2 中,您可以这样做(在 derived.py 中):

    from base import BaseThing
    

    Python 3 不再支持这一点,因为它不明确你想要“相对”还是“绝对”base。换句话说,如果系统中安装了一个名为 base 的 Python 包,那你就搞错了。

    相反,它要求您使用显式导入,它在类似路径的基础上显式指定模块的位置。你的derived.py 看起来像:

    from .base import BaseThing
    

    前导. 表示“从模块目录导入base”;换句话说,.base 映射到 ./base.py

    类似地,.. 前缀在目录层次结构中向上上升,例如 ../..mod 映射到 ../mod.py),然后是 ...,它上升两级(../../mod.py)等等开。

    但请注意,上面列出的相对路径是相对于当前模块 (derived.py) 所在的目录,不是当前工作目录。


    @BrenBarn 已经解释了明星导入案例。为了完整起见,我不得不说同样的话;)。

    例如,您需要使用几个math 函数,但您只能在单个函数中使用它们。在 Python 2 中,你被允许是半懒惰的:

    def sin_degrees(x):
        from math import *
        return sin(degrees(x))
    

    请注意,它已经在 Python 2 中触发了警告:

    a.py:1: SyntaxWarning: import * only allowed at module level
      def sin_degrees(x):
    

    在现代 Python 2 代码中你应该这样做,而在 Python 3 中你必须这样做:

    def sin_degrees(x):
        from math import sin, degrees
        return sin(degrees(x))
    

    或:

    from math import *
    
    def sin_degrees(x):
        return sin(degrees(x))
    

    【讨论】:

    • 这当然会在运行python derived.py时失败
    • @MiloBem 是的,如果您需要两种情况都可以工作,您会怎么做?
    【解决方案2】:

    有关相对导入,请参阅the documentation。相对导入是指从相对于该模块位置的模块导入,而不是绝对从 sys.path 导入。

    至于import *,Python 2 允许在函数中导入星号,例如:

    >>> def f():
    ...     from math import *
    ...     print sqrt
    

    在 Python 2(至少是最新版本)中会为此发出警告。在 Python 3 中不再允许这样做,您只能在模块的顶层(不能在函数或类内部)进行星号导入。

    【讨论】:

    • 为什么会做出这个决定?
    • 我的猜测是它背后的想法是“显式优于隐式”。来自 PEP20 - Python 之禅。模块前的点使相对/非相对链接显式化,从而解决可能的名称冲突。尽管“可读性很重要”。轻微受苦。
    • 不,实际上是“相反”、“实用胜过纯洁”的决定。为了优化函数内部的局部变量访问,这是必要的,因为没有“import *”,编译器总是通过分析代码就知道哪些变量是局部变量并且可以直接查找。实际上,函数甚至不使用 dict 进行本地存储,而是使用优化的数组,其中变量获得唯一索引。
    【解决方案3】:

    要同时支持 Python 2 和 Python 3,请使用如下的显式相对导入。它们是相对于当前模块的。他们已得到支持starting from 2.5

    from .sister import foo
    from . import brother
    from ..aunt import bar
    from .. import uncle
    

    【讨论】:

    • import .brother 在 Python 3.5 中给了我一个无效的语法错误。这个是正常的?我在它所在的目录中有 init.py
    • import .brother 对 python 2 和 3 都无效
    • @RodrigoE.Principe 似乎是import ..uncle。固定的。哦,我在想什么……可能是被那些说 Ni 的骑士分心了!
    【解决方案4】:

    在 Michał Górny 的回答中添加了另一个案例:

    请注意,相对导入基于当前模块的名称。由于主模块的名称始终为“__main__”,因此用作 Python 应用程序的主模块的模块必须始终使用绝对导入。

    【讨论】:

      猜你喜欢
      • 2018-11-18
      • 2018-08-13
      • 1970-01-01
      • 2013-11-07
      • 2014-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多