【问题标题】:Reasoning behind `from ... import ...` syntax in PythonPython中`from ... import ...`语法背后的推理
【发布时间】:2011-04-05 17:56:43
【问题描述】:

我一直想知道为什么从模块中导入特定对象的语法是from module import x, y, z 而不是import x, y, z from module。我不是母语人士,但后者不是更正确/更自然吗?

那么,将 from 放在首位的原因是什么?仅仅是为了简化语法(需要更少的前瞻)?是不是试图让两种进口在视觉上更加明显?还是其中一种明显的方式“一开始并不明显,除非你是荷兰人”? ;)

【问题讨论】:

  • 我仍在学习 Python,但恕我直言,以下内容似乎与该语言的其余部分更加一致:import(module, x, y, z)。根本不需要from
  • @FM:如果你不希望import 得到特殊的句法处理,你必须写import('module', 'x', 'y', 'z'),传递对象的名称,因为对象本身直到 import 之后才可用。
  • 我见过的最好的导入语法是在 Haskell 中:import module (a, b, c)。干净、清晰并使多个导入语句看起来一致且对齐(不幸的是,import qualified 案例除外)。而且我不知道为什么 GvR 选择了那个丑陋的from ... import
  • 以介词开头的句子既不合语法也不常见。例如,“从梅德福出发,向南行驶 5 号州际公路”。这一切都取决于使句子解析更好的原因。对于包括这种情况在内的许多情况,在行动之前给出上下文更有意义。

标签: python syntax import


【解决方案1】:

来自https://docs.python.org/3/reference/simple_stmts.html#import

import foo # foo imported and bound locally import foo.bar.baz # foo.bar.baz imported, foo bound locally import foo.bar.baz as fbb # foo.bar.baz imported and bound as fbb from foo.bar import baz # foo.bar.baz imported and bound as baz from foo import attr # foo imported and foo.attr bound as attr

我认为这是本地可用性/绑定的问题。

【讨论】:

    【解决方案2】:

    不知道为什么实际上是这样做的,但这是我会这样做的方式,仅仅是因为,作为一名工程类型,我似乎更自然地从一般类别开始,并且深入了解细节。

    这也意味着如果按顺序处理,解析器将不得不存储更少的东西。与:

    import x, y, z from a
    

    您必须记住xyz。与:

    from a import x, y, z
    

    你只需要记住a


    这就是我第一次遇到 Perl 的 post-if 变体时遇到这么多麻烦的原因:

    $x = $y if $y > 40;
    

    因为你事先并不知道你正在阅读的内容是否是有条件的。

    【讨论】:

    • 既然您提到“postfix if”,我想我看到了可读性奖励... +1,除非 uber-answer bei A.M. 否则将被接受来了;)
    • 所以,近十年后,我将补充一点,现在我们有了更好的 Python IDE,语法 from foo import ba<ctrl+space> 允许由 IDE 实现完成(提供选项 bar , bat,, baz...),因为在你尝试完成之前它知道你从哪里导入。
    【解决方案3】:

    除了直接问 Guido,我想你不会找到任何解释。

    语法从一开始就存在。我能找到的最早版本的 python 源代码是 python 1.0.1。查看语法文件中的更改日志,我们发现对更早版本的引用。在 Python 的第 2 版(我想我们说的是 0.9.0 之后的第 2 版)中,我们有这样的注释:

    #   added 'from' NAME option on import clause, and '*' to import all;
    

    这是与

    同时添加的
    #   added class definition.
    

    因此,在将类添加到 Python 的同时出现了 import 语句。这源于 Python 是 Guido van Rossum 的个人项目。换句话说,您正在寻找的答案已经消失在时间的流沙中。

    现在,我猜想为什么 import 语句会写成 from x import y 而不是 import y from x

    documentation for the import statement 提供了实现导入的基本算法:

    导入语句分两步执行 步骤: (1) 找到一个模块,然后 必要时初始化它; (2) 定义 本地命名空间中的一个或多个名称 (进口的范围 语句出现)。声明来了 有两种不同的形式 使用 from 关键字。第一种形式 (没有 from)重复这些步骤 列表中的每个标识符。表格 with from 执行步骤 (1) 一次,并且 然后重复执行步骤(2)。

    在两个版本的 import 语句中,该算法的第一步都位于最左侧。我认为这对于语言实现者来说是最明显的顺序,尽管如果顺序颠倒,英语可能会更自然地阅读。

    【讨论】:

      【解决方案4】:

      这取决于您使用的编程语言语法。我更容易阅读这样的导入。

      更容易阅读和理解

      From Grocery buy apple and orange
      

      Buy apple and orange from grocery.
      Buy apple and orange from supermarket
      

      第一个更适合我...

      【讨论】:

        【解决方案5】:

        用英语说import x, y, z from module 可能更有意义,但在编程中,先引入更通用的Item 然后再引入细节会更有意义。 这可能不是原因,但它使编译器或解释器的事情变得更容易。 试着写一个编译器,你就会明白我的意思了:D

        【讨论】:

        • 我完全意识到编译器编写者的不同之处,但如果我作为程序员关心这一点,我会坚持使用助记符进行汇编:D
        • 不仅对于编译器编写器,它还可以帮助 IDE 为您提供选择,如果您首先在哪里编写“导入”,IDE 无法为您提供任何选择,因为它不知道从你要导入什么模块
        • 好点。它让我想起了 SQL 语句 SELECT Columns FROM Table,它遇到了自动完成的问题。
        【解决方案6】:

        我不知道这种语法的完整遗产,因为它可以追溯到 Python 1.x 天。但是我发现能够向下扫描源的左侧并快速找到脚本所依赖的模块名称很有用。如果语句为“import a,b,c,d,e,really_long_name, alsdf,lsdf from blah”,我需要一段时间才能发现这个脚本依赖于 blah。

        【讨论】:

          【解决方案7】:

          其实,这并不奇怪。看看我们如何在其他语言中“导入”、“包含”或“要求”。我们总是首先指定命名空间。例如,在 PHP 中包含“inc/config.php”。所以在某种程度上,它保持了我们通常包含文件或模块的方式。

          【讨论】:

            【解决方案8】:

            一个非常疯狂的猜测,可能完全没有意义,但我知道 Modula-2 的语法(伙计,那是 20 年前,我觉得老了)......也许 Python 受到了它的启发?

            【讨论】:

            • 最简单的答案,而且很可能是正确的。 GvR 在设计 Python 时采用了各种语言的结构,包括 Modula-2,这可能是该语言的直接提升。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-12-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多