Python3中zip操作与列表/元组解包的底层工作原理是什么
Python 3中zip打包与逆向解包的底层逻辑
首先明确两个核心概念,搞懂之后这段代码的运行逻辑就完全通顺了:
- Python 3中的
zip()是惰性迭代器工厂,调用它的时候不会立刻生成所有配对结果,只会返回一个迭代器对象;只有实际迭代这个对象(比如转list、for循环遍历、被*解包)的时候,才会依次从传入的所有可迭代参数里,按索引位置取元素拼成元组返回。 - 表达式里的
*是可迭代对象解包运算符,作用是把它后面跟着的可迭代对象拆成独立的位置参数,传给前面的函数。
顺带提一句,你给出的示例代码里有个笔误:打印结果那行写的list(zip_L1L2)是未定义的变量,正确写法是传入我们赋值得到的zip对象l3,修正后的打包代码如下:
l1 = [1,2,3] l2 = ['a','b','c'] l3 = zip(l1,l2) print(list(l3)) # Output: [(1, 'a'), (2, 'b'), (3, 'c')]
注意:zip返回的迭代器是一次性消耗品,当你把所有元素都取完之后,这个迭代器就变成空的了,再次迭代不会返回任何内容。比如上面跑完
list(l3)之后,l3里已经没有剩余元素,直接跑解包代码会拿不到结果,需要重新执行l3 = zip(l1,l2)生成新的迭代器才行。
接下来拆解l4, l5 = zip(*l3)的执行步骤:
- 首先执行
*l3:此时会迭代l3,把里面存的三个元组(1,'a')、(2,'b')、(3,'c')拆成三个独立的参数,传给zip函数,这行代码等价于手动写zip( (1,'a'), (2,'b'), (3,'c') ) - 接着zip处理这三个传入的元组:按照zip本身的配对逻辑,从每个传入的可迭代对象(也就是这三个元组)里,按相同索引位置取元素拼接:
- 取所有参数的0号元素:1、2、3 → 拼成元组
(1,2,3) - 取所有参数的1号元素:'a'、'b'、'c' → 拼成元组
('a','b','c') - 所有参数都取到末尾,迭代停止
- 取所有参数的0号元素:1、2、3 → 拼成元组
- 最后执行多变量赋值:zip返回的迭代器里刚好有两个元组,Python会按顺序把第一个元组赋值给l4,第二个元组赋值给l5,就完成了原始序列的还原。
对应的解包代码运行效果:
# 因为之前跑list(l3)已经把迭代器消耗空了,这里重新生成一次 l3 = zip(l1,l2) l4, l5 = zip(*l3) print(l4) # Output: (1, 2, 3) print(l5) # Output: ('a', 'b', 'c')
补充一个小细节:逆向解包得到的l4、l5是元组类型,不是原来的列表类型,如果需要换回列表,只要对结果套一层list()转换即可。
内容的提问来源于stack exchange,提问作者Ailete619
相关产品推荐
相关产品推荐

