介绍
此 PEP 描述了“锁步迭代”提案。此 PEP 跟踪 此功能的状态和所有权,计划在 蟒蛇 2.0。它包含对功能和轮廓的描述 支持该功能所需的更改。本 PEP 总结了 在邮件列表论坛中进行的讨论,并提供进一步的 URL 信息(如适用)。此文件的 CVS 修订历史记录 包含权威的历史记录。
赋予动机
Python 中的标准 for 循环遍历序列中的每个元素 直到序列用尽 。但是,for 循环会遍历 只有一个序列,并且通常需要循环更多 而不是一个锁步方式的序列。换句话说,在某种程度上 这样,通过循环的第 i 次迭代返回一个对象 包含每个序列中的第 i 个元素。
用于实现此目的的常见习语是不直观的。这个PEP 提出了一种执行此类迭代的标准方法,方法是引入 新的内置函数称为 。zip
虽然 zip() 的主要动机来自锁步迭代, 通过将 zip() 实现为内置函数,它具有额外的 在 for 循环以外的上下文中的实用程序。
锁步 for 循环
锁步 for 循环是两个或多个非嵌套迭代 序列,使得在每次通过循环时,一个元素来自 采用每个序列来组成目标。此行为可以 已经通过使用 map() 内置的 Python 完成 功能:
>>> a = (1, 2, 3) >>> b = (4, 5, 6) >>> for i in map(None, a, b): print i ... (1, 4) (2, 5) (3, 6) >>> map(None, a, b) [(1, 4), (2, 5), (3, 6)]
for 循环只是像往常一样循环访问此列表。
虽然 map() 成语在 Python 中很常见,但它有几个 弊:
对于没有函数式编程的程序员来说,这是不明显的 背景。
魔术第一论点的使用是不明显的。None
当 列表的长度不同:较短的序列是 填充:None
>>> c = (4, 5, 6, 7) >>> map(None, a, c) [(1, 4), (2, 5), (3, 6), (None, 7)]
由于这些原因,Python 2.0 中提出了几个建议 锁步 for 循环的语法支持的 beta 时间框架。这里是 两点建议:
for x in seq1, y in seq2: # stuff
for x, y in seq1, seq2: # stuff
这两种形式都行不通,因为它们都已经意味着 Python 中的某些内容和更改含义会破坏现有内容 法典。所有其他关于新语法的建议都遇到了同样的问题, 或与其他名为“列表”的其他提议功能发生冲突 理解“(见 PEP 202)。
建议的解决方案
建议的解决方案是引入一个新的内置序列 发电机功能,在模块中可用。这 函数将被调用,并具有以下签名:__builtin__zip
zip(seqa, [seqb, [...]])
zip()采用一个或多个序列并编织它们的元素 一起,就像相等的序列一样 长度。当最短序列用尽时,编织停止。map(None, ...)
返回值
zip()返回一个真正的 Python 列表,同样的方式。map()
例子
下面是一些示例,基于下面的参考实现:
>>> a = (1, 2, 3, 4) >>> b = (5, 6, 7, 8) >>> c = (9, 10, 11) >>> d = (12, 13) >>> zip(a, b) [(1, 5), (2, 6), (3, 7), (4, 8)] >>> zip(a, d) [(1, 12), (2, 13)] >>> zip(a, b, c, d) [(1, 5, 9, 12), (2, 6, 10, 13)]
请注意,当序列的长度相同时,为 可逆:zip()
>>> a = (1, 2, 3) >>> b = (4, 5, 6) >>> x = zip(a, b) >>> y = zip(*x) # alternatively, apply(zip, x) >>> z = zip(*y) # alternatively, apply(zip, y) >>> x [(1, 4), (2, 5), (3, 6)] >>> y [(1, 2, 3), (4, 5, 6)] >>> z [(1, 4), (2, 5), (3, 6)] >>> x == z 1
当序列不是时,不可能以这种方式反向压缩 长度都一样。
参考实现
这是一个参考实现,在 Python 中内置了 zip() 功能。这将在最终之后替换为 C 实现 批准:
def zip(*args): if not args: raise TypeError('zip() expects one or more sequence arguments') ret = [] i = 0 try: while 1: item = [] for s in args: item.append(s[i]) ret.append(tuple(item)) i = i + 1 except IndexError: return ret
BDFL声明
注意:BDFL 指的是 Guido van Rossum,Python 的仁慈者 终身独裁者。
函数的名称。此 PEP 的早期版本包括 未解决的问题列表 20+ 建议的替代名称。在 面对没有压倒性的更好选择,BDFL强烈 由于其 Haskell [2] 遗产而更受欢迎。请参阅版本 1.7 此 PEP 的替代方案列表。
zip()
zip()
zip()
应为内置函数。可选填充。该 PEP 的早期版本提出了一个 可选的关键字参数,当 参数序列的长度不同。这是相似的 行为到语义,但用户除外 将能够指定 pad 对象。这已被 BDFL 赞成始终截断到最短的序列,因为 KISS原则。如果真的有需要,添加起来会更容易 后。如果不需要,仍然无法删除 它在未来。
pad
map(None, ...)
懒惰的评估。此 PEP 的早期版本建议返回一个执行延迟评估的内置对象 使用协议。这遭到了强烈反对 由 BDFL 支持返回真正的 Python 列表。如果懒惰 将来需要评估,BDFL 建议添加一个功能。
zip()
__getitem__()
xzip()
zip()
没有参数。BDFL强烈希望这次加息。 TypeError 异常。zip()
用一个参数。BDFL 强烈希望这样做 返回 1 元组的列表。内箱和外箱控制。此 PEP 的早期版本 包含对某些人的功能的相当冗长的讨论 想要的,即控制内在和外在的能力 容器类型是(它们分别是元组和列表,在此 PEP的版本)。鉴于简化的 API 和实现, 这种阐述被拒绝了。有关更详细的分析,请参阅 此 PEP 的 1.7 版。
后续更改为
在 Python 2.4 中,没有参数的 zip() 被修改为返回一个空的 列表,而不是引发 TypeError 异常。基本原理 最初的行为是,没有论据被认为是 指示编程错误。然而,这种想法并没有 预期将 zip() 与运算符一起使用以进行解包 可变长度参数列表。例如,zip 的反面可以 定义为:。这种转变 还定义了矩阵转置或等效的行/列交换 定义为元组列表的表。后一种转变是 读取数据文件时常用的记录为行和字段 作为列。例如,代码:*unzip = lambda s: zip(*s)
date, rain, high, low = zip(*csv.reader(file("weather.csv")))
重新排列列式数据,以便将每个字段收集到 用于简单循环和汇总的单个元组:
print "Total rainfall", sum(rain)
如果处理,则使用更容易编码 作为允许的情况,而不是例外情况。这尤其 当数据从 null 构建或递归到 null 时很有帮助 没有记录的案例。zip(*args)zip(*[])
看到这种可能性,BDFL同意(有一些疑虑) 更改了 Py2.4 的行为。
其他更改
上面讨论的函数是在 Py2.3 中实现的 模块为 .此函数 提供懒惰行为,消耗单个元素并产生 每个传递上的单个元组。“即时”风格可节省内存 并且比基于列表的对应项运行得更快。
xzip()
itertools
itertools.izip()
zip()
该模块还添加了 和 .这些工具可以一起用于垫 序列 (以匹配 的行为):
itertools
itertools.repeat()
itertools.chain()
None
map(None, seqn)
zip(firstseq, chain(secondseq, repeat(None)))
版权
本文档已置于公共领域。
文章声明:以上内容(如有图片或视频在内)除非注明,否则均为腾龙猫勺儿原创文章,转载或复制请以超链接形式并注明出处。
本文作者:猫勺本文链接:https://www.jo6.cn/post/87.html
还没有评论,来说两句吧...