介绍
此 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.c
listobject.c
bltinmodule.c
xrange
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()
版权
本文档已置于公有领域。
文章声明:以上内容(如有图片或视频在内)除非注明,否则均为腾龙猫勺儿原创文章,转载或复制请以超链接形式并注明出处。
本文作者:猫勺本文链接:https://www.jo6.cn/post/91.html