当前位置: 首页 > 科技观察

一篇文章掌握Python内置zip()全部内容

时间:2023-03-14 09:43:06 科技观察

zip()是Python中最有用的内置类型之一。它可以接收多个可迭代对象参数并返回一个迭代器,迭代器可以将不同的可迭代对象的元素组合起来。不过还是有很多同学不知道zip(),或者不能熟练掌握它的用法,所以本文打算做一个更详细的回顾。内容主要分为三个部分:Usage部分:介绍其基本用法、高级用法、showoperationusageAdvanced部分:介绍其实现原理,注意几个实现细节Divergent部分:重点介绍其不足之处,以及解决方案1.Thenusagesofzip()基本用法:像拉链一样,组合多个可迭代对象,然后用for循环将它们一个一个取出来,或者将结果一次存放到列表、元组、字典等容器中时间。它的结果是一个迭代器,迭代器生成的元素是元组,第i个元组的元素来自可迭代对象参数的第i个元素,如上图所示。另外,for循环还可以依次取出元组中的元素,非常方便:它的参数不需要是同类型的可迭代对象,所以可以有很多种组合,例如:但是,如果将字典作为zip()的参数,结果会是什么?字典是key-value键值对的形式,不同于列表等单元素结构。实验一下,可以看出zip()默认只会遍历字典的key值:如果要取出字典的value值,或者取出key-value键值对,那么就可以使用字典自带的遍历方法values()和items():使用zip(),实现二维列表的行列转换也很方便:上例中的星号(*)运算符即可unpacked(解包),即把my_list(也是列表)的元素分解成多个参数给zip(),重新组合3个列表。解包操作符同样适用于zip对象,因为zip()本身就是一个行列转换操作。如果解包后作为参数传递给zip(),相当于又做了一次行列转换,即回到原点(除了最后的结果是一个元组):最后再介绍一个用法:创建一个n*n的方阵,每一行的数字都相同。2、zip()原理分析官方文档给出了zip()的Python伪代码(不是Python解释器内置的实现,只是展示基本的代码逻辑):defzip(*iterables):#zip('ABCD','xy')-->AxBysentinel=object()iterators=[iter(it)foritiniterators]whileiterators:result=[]foritiniterators:elem=next(it,sentinel)ifelemissentinel:returnresult.append(elem)yieldtuple(result)在这段简短的代码中,可以分析出一些关键信息:zip接收到可变数量的可迭代对象参数,这些参数将被iter()处理成迭代器。推论:如果存在不可迭代对象,这里会报错。while循环是判断列表是否为空,列表中的元素是参数转换而来的迭代器。推论:如果输入参数中存在有效的可迭代对象,则while循环始终为真;如果没有输入参数,则什么都不做。next()会依次读取迭代器中的下一个元素,它的第二个参数会作为迭代器耗尽时的返回值。推论:每一轮依次取出这些迭代器中的一个元素。当一次迭代耗尽时,它会退出死循环,也就是说未耗尽的迭代器会被直接丢弃。3.zip()的问题与zip()最明显的问题是它丢弃了未用尽的迭代器:这是一个桶效应,最终结果由最短的木板决定。一种解决方案是取长板补短板(填充None值),就是itertools中的zip_longest方法:它在填充冗余数据的同时,最大限度地保留原始数据的完整性。但是,如果我们不想要冗余数据,而只想要以最长方式对齐的数据怎么办?Python官方最近采用了PEP-618,就是为了应对这个问题。当迭代器的长度不一致时,既不折衷短板,也不折衷长板,而是抛出ValueError。它认为输入参数值错误,即严格要求输入参数的数据完整性。