PEP 204 – 范围文字

猫勺猫勺 04-25 111 阅读 0 评论

警告

PEP 已被拒绝。

×

经过深思熟虑,经过一段时间的冥想,这 提案已被否决。悬而未决的问题,以及一些 范围和切片语法之间的混淆,引发了足够多的问题 让 Guido 不接受它用于 Python 2.0,然后拒绝 提案。新语法及其意图被认为是 不够明显。

[ 待定:Guido,请修改/确认这一点。最好两者兼而有之;这 是 PEP,它应该包含所有拒绝的原因 和/或重新考虑,以备将来参考。]


介绍

此 PEP 描述了 Python 2.0 的“范围文字”提案。 此 PEP 跟踪此功能的状态和所有权,预计 用于 Python 2.0 中的介绍。它包含对 功能并概述了支持该功能所需的更改。 此 PEP 总结了在邮件列表论坛中进行的讨论,以及 在适当的情况下提供更多信息的 URL。CVS的 此文件的修订历史记录包含权威的历史记录 记录。

列表范围

范围是固定步进的数字序列,通常用于 for循环。Python for 循环旨在遍历 直接序列:

>>> l = ['a', 'b', 'c', 'd']
>>> for item in l:
...     print item
a
b
c
d

但是,这种解决方案并不总是谨慎的。首先,问题 当改变for循环主体中的序列时出现, 导致 for 循环跳过项。其次,它不是 可以迭代,比如说,每个第二个元素 序列。第三,有时需要处理 元素基于其索引,这在 上面构造。

对于这些实例,以及其他数字范围为 需要,Python 提供了内置函数,该函数 创建数字列表。该函数需要三个 参数、开始、结束和步骤。start 和 step 是 可选,默认值分别为 0 和 1。rangerange

该函数创建一个数字列表,从开始开始,步长为步长,直到但不包括结束,所以 生成一个正好包含 10 个项目的列表,即 数字 0 到 9。rangerange(10)

使用该函数,上面的示例如下所示 这:range

>>> for i in range(len(l)):
...     print l[i]
a
b
c
d

或者,从第二个元素开始,只处理 从那时起,每两个元素:l

>>> for i in range(1, len(l), 2):
...     print l[i]
b
d

这种方法有几个缺点:

  • 目的明确:添加另一个函数调用,可能使用 额外的算术来确定所需的长度和步长 列表,不会提高代码的可读性。此外,它是 可以通过提供 具有相同名称的局部或全局变量,有效 替换它。这可能是也可能不是预期的效果。range

  • 效率:因为函数可以被覆盖, Python 编译器不能对 for 循环做出假设,并且 必须维护一个单独的循环计数器。range

  • 一致性:已经有一种语法用于表示 范围,如下所示。此语法使用完全相同的语法 参数,虽然都是可选的,但以完全相同的方式。似乎 逻辑地将此语法扩展到范围,以形成“范围 文字“。

切片索引

在 Python 中,可以通过以下两种方式之一对序列进行索引: 检索单个项目,或检索一系列项目。 检索一系列项目将生成相同的新对象 键入作为原始序列,包含零个或多个项目 原始序列。这是使用“范围表示法”完成的:

>>> l[2:4]
['c', 'd']

此范围表示法由零、一个或两个分隔的索引组成 通过冒号。第一个索引是开始索引,第二个索引是结束索引。当其中任何一个被遗漏时,它们默认分别为 序列的开始和结束。

还有一个扩展范围符号,它也包含步进。虽然目前不支持此表示法 对于大多数内置类型,如果是,它将按如下方式工作:

>>> l[1:4:2]
['b', 'd']

切片语法的第三个“参数”与 的 step 参数。的基本机制 标准和这些扩展切片是完全不同的 并且不一致,许多类和扩展之外 数学包不实现对扩展的支持 变体。虽然这应该得到解决,但它超出了 这个 PEP。range()

然而,扩展切片确实表明,已经存在一个 完全有效和适用的语法,以某种方式表示范围 解决了前面提到的所有缺点 功能:range()

  • 它是更清晰、更简洁的语法,这已经被证明是 既直观又易于学习。

  • 它与 Python 中范围的其他用法一致 (例如切片)。

  • 因为它是内置语法,而不是内置函数,所以它 不能被覆盖。这意味着观众可以 确定代码的作用,而优化器不会 不得不担心被“影子”。range()

建议的解决方案

建议的 range-literals 实现结合了语法 对于具有(扩展)切片语法的列表文本,要形成 范围文字:

>>> [1:10][
1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [:5]
[0, 1, 2, 3, 4]
>>> [5:1:-1]
[5, 4, 3, 2]

范围文字和切片之间有一个细微的区别 语法:虽然可以省略切片中的所有 start、end 和 step,但在 range 中省略 end 是没有意义的 文字。在切片中,end 将默认为列表的末尾, 但这在范围字面上没有意义。

建议的实现可以在 SourceForge [1] 上找到。它 添加一个新的字节码 ,该字节码从 堆栈并在这些基础上构建一个列表。列表是 推回堆栈。BUILD_RANGE

为了能够构建范围,必须使用新的字节码 基于其他计算,其结果在编译时未知 时间。

该代码引入了两个新函数,它们是 目前徘徊在私有函数和成熟的 API 之间 调用。listobject.c

PyList_FromRange()从开始、结束和步骤构建列表, 如果发生错误,则返回 NULL。它的原型是:

PyObject * PyList_FromRange(long start, long end, long step)

PyList_GetLenOfRange()是一个帮助程序函数,用于确定 范围的长度。以前,它是 中的静态函数,但现在在 和 (for ) 中都是必需的。它之所以非静态,只是为了避免 代码重复。它的原型是:bltinmodule.clistobject.cbltinmodule.cxrange

long PyList_GetLenOfRange(long start, long end, long step)

未解决的问题

  • 对于在范围文本中要求结束参数的差异,一种可能的解决方案是允许范围语法 创建一个“生成器”,而不是像内置函数那样的列表。但是,发电机不会是 列表,例如,不可能分配给 生成器中的项,或附加到生成器中。xrange

    可以想象,范围语法可以扩展到包括元组 (即不可变列表),然后可以安全地实现 作为发电机。这可能是一个理想的解决方案,特别是对于 大数阵列:生成器几乎不需要任何方法 的存储和初始化,并且只有很小 计算和创建适当的性能影响 电话号码应要求提供。(待定:有吗?粗略测试 即使在长度范围的情况下,也表明性能相同 1)

    然而,即使这个想法被采纳,“特殊 case“的第二个参数,使其在 语法,在其他情况下是非可选的?

  • 是否可以将范围语法与普通列表混合使用 文字,创建一个列表?例如:

  • >>> [5, 6, 1:6, 7, 9]

    要创建:

    [5, 6, 1, 2, 3, 4, 5, 7, 9]
  • 范围文字应该如何与另一个提议的新内容交互 功能,“列表推导”?具体来说,应该是 可以在列表推导中创建列表吗?例如:

    >>> [x:y for x in (1, 2) y in (3, 4)]

    此示例是否应返回具有多个范围的单个列表:

    [1, 2, 1, 2, 3, 2, 2, 3]

    或者列表列表,如下所示:

    [[1, 2], [1, 2, 3], [2], [2, 3]]

    但是,由于列表推导式的语法和语义是 这些问题仍然是激烈辩论的主题,可能是最好的 由“列表理解”PEP解决。

  • 范围文字接受整数以外的对象:它对传入的对象执行,因此只要 对象可以被强制成整数,它们将被接受。 但是,生成的列表始终由标准组成 整数。PyInt_AsLong()

    范围文本是否应该创建传入类型的列表?它 在其他内置类型的情况下可能是可取的,例如 长串:

>>> [ 1L : 2L<<64 : 2<<32L ]
>>> ["a":"z":"b"]
>>> ["a":"z":2]
  • 然而,这可能太“神奇”了,不明显。它可能 用户定义的类也存在问题:即使 可以找到基类并创建一个新实例,即该实例 可能需要额外的参数来 ,导致 创建失败。__init__

  • 和函数需要 要分类:它们是 API 的一部分,还是应该 做私人活动?PyList_FromRange()PyList_GetLenOfRange()

    版权

    文档已置于公有领域。

    The End 微信扫一扫

    文章声明:以上内容(如有图片或视频在内)除非注明,否则均为腾龙猫勺儿原创文章,转载或复制请以超链接形式并注明出处。

    本文作者:猫勺本文链接:https://www.jo6.cn/post/91.html

    上一篇 下一篇

    相关阅读

    发表评论

    访客 访客
    快捷回复: 表情:
    评论列表 (暂无评论,111人围观)

    还没有评论,来说两句吧...

    取消
    微信二维码
    微信二维码
    支付宝二维码