在Python中,zip是一个内置函数(其实是一个class),可以将多个可迭代对象(如列表、元组等)作为参数,将对象中对应index的元素打包成一个个的元组,然后返回由这些元组tuple组成的zip迭代器(之前文章讲过,类中包含了__iter__ 和__next__魔法方法可作为迭代器)。
以下是python3.10版本builtins.py中内置的zip类的原始代码:
zip类接收2个参数:
- iterables:接受一个或多个可迭代对象,如列表、元组、字符串、字典的键或值(通过keys(), values(), items()等方法获取),range对象等。
- strict=False(该参数是python3.10版本增加):默认为False,表示当迭代对象的length不同时,zip默认使用最小length组成元组,不会报错。否则传入True时会报某对象的length不一致的错误。
1 zip对象处理逻辑示意图
2 zip对象返回的是迭代器
举例:定义两个列表,通过instance函数判断zip对象是否是迭代器
from collections.abc import Iterable,Iterator
list1 = ['name', 'age', 'color']
list2 = ['wang', '12', 'black']
new_iter = zip(list1,list2)
print(isinstance(new_iter,Iterator))
结果打印为:
True
因为是迭代器,我们可以用next函数返回zip对象的元素。
print(next(new_iter))
print(next(new_iter))
以下打印结果也验证了开篇说明的通过zip函数将可迭代对象相同index位置的元素组成了元组。
('name', 'wang')
('age', '12')
3 将zip对象转为list,tuple,set,dict等对象
既然是返回的迭代器,我们可以将上述示例中的迭代器转为可迭代对象。
- 转为list对象:
print(list(new_iter))
#结果
[('name', 'wang'), ('age', '12'), ('color', 'black')]
- 转为tuple对象:
print(tuple(new_iter))
#结果
(('name', 'wang'), ('age', '12'), ('color', 'black'))
- 转为集合对象:
print(set(new_iter))
#结果
{('name', 'wang'), ('color', 'black'), ('age', '12')}
- 转为字典对象:
print(dict(new_iter))
#结果
{'name': 'wang', 'age': '12', 'color': 'black'}
注释:如果每个元组元素大于两个,转换字典会报错,因为字典只需要两个元素组成key和value。
4 使用*解包
举例:list1中嵌套了两个list,使用*list1传入zip作为可迭代对象
list1 = [['name', 'age', 'color','height'],['wang', '12', 'black']]
new_iter = zip(*list1)
print(list(new_iter))
结果:
[('name', 'wang'), ('age', '12'), ('color', 'black')]
举例: 拆解为原来的可迭代对象
x = [1, 2, 3]
y = [4, 5, 6]
print(list(zip(x, y)))
#结果
[(1, 4), (2, 5), (3, 6)]
#拆解为原来的可迭代对象
x2, y2 = zip(*zip(x, y))
print(x == list(x2) and y == list(y2))
True
5 strict参数的作用
举例:定义两个不同长度的list,设置strict=True,zip对象执行会报错
list1 = ['name', 'age', 'color','height']
list2 = ['wang', '12', 'black']
new_iter = zip(list1,list2,strict=True)
执行后报ValueError的错误:
参数默认为False则不会报错,结果如下:
new_iter = zip(list1,list2)
print(list(new_iter))
[('name', 'wang'), ('age', '12'), ('color', 'black')]
6 itertools.zip_longest()介绍
如果可迭代对象长度不同,使用itertools.zip_longest对象可以将不满足长度的元素填充其他值代替(默认使用None代替,可传参数fillvalue=其他值)
- 使用默认值None填充
from itertools import zip_longest
list1 = ['name', 'age', 'color','height']
list2 = ['wang', '12', 'black']
new_iter1 = zip_longest(list1,list2)
print(list(new_iter1))
结果:
[('name', 'wang'), ('age', '12'), ('color', 'black'), ('height', None)]
- 设置其他固定值填充
new_iter1 = zip_longest(list1,list2,fillvalue='1m')
print(list(new_iter1))
结果:
[('name', 'wang'), ('age', '12'), ('color', 'black'), ('height', '1m')]
共勉: 东汉·班固《汉书·枚乘传》:“泰山之管穿石,单极之绠断干。水非石之钻,索非木之锯,渐靡使之然也。”
-----指水滴不断地滴,可以滴穿石头;
-----比喻坚持不懈,集细微的力量也能成就难能的功劳。
----感谢读者的阅读和学习和关注,谢谢大家。