Python内置的zip函数,不能顾名思义地理解为“压缩”。此zip函数不做压缩(不是gzip),而是将多个可迭代的对象作为参数,按照相同的index,分别将他们内部的元素取出,然后重新组合成一个新的tuple;zip函数的返回是一个可迭代的zip对象,每一次迭代,都是index递增后生成的tuple。
用文字描述zip函数的功能还真有些难度,我们再看看Python官方文档对zip函数的解释:
zip(*iterables) # unpacking函数参数的写法
Make an iterator that aggregates elements from each of the iterables.
Returns an iterator of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables. The iterator stops when the shortest input iterable is exhausted. With a single iterable argument, it returns an iterator of 1-tuples. With no arguments, it returns an empty iterator.
zip函数返回的是一个可迭代的zip对象;没有参数时,zip返回一个空的迭代器;当zip函数只有一个可迭代参数时,它返回一个只有1个元素的tuple的迭代器。我喜欢先看看这几个特殊情况的示例代码:
>>> zip()
>>> list(zip())
[]
>>> list(zip([1,2,3,4,5]))
[(1,), (2,), (3,), (4,), (5,)]
现在来看几个正常一点的zip函数的使用示例:
>>> a = [1,2,3,4,5]
>>> b = (1,2,3,4,5)
>>> c = list(zip(a,b))
>>> c
[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
>>> for t in zip(a,b):
... print(t)
...
(1, 1)
(2, 2)
(3, 3)
(4, 4)
(5, 5)
list函数接受一个可迭代参数(zip函数的返回值),生产一个list对象。或者直接通过for循环来一个个提取zip返回的可迭代对象。这两种用法都很常见。
zip函数使用的一个细节是,如果参数中的可迭代对象长度不相同,那么就以长度最短的为准,“超长”的部分就不用了。
>>> a = [1,2,3,4,5]
>>> b = [1,2,3,4]
>>> c = (1,2,3)
>>> for t in zip(a,b,c):
... print(t)
...
(1, 1, 1)
(2, 2, 2)
(3, 3, 3)
a的最后2个元素,b的最后1个元素,都没有出现的zip的返回结果中。
string对象在Python中也是可迭代的,也可以作为zip函数的参数来使用。
>>> tuple(zip('abcd','1234'))
(('a', '1'), ('b', '2'), ('c', '3'), ('d', '4'))
zip函数的返回值,是个“阅后即焚”的迭代器(Iterator)。
>>> zipped = zip('abcd','1234')
>>> a = list(zipped)
>>> a
[('a', '1'), ('b', '2'), ('c', '3'), ('d', '4')]
>>> b = list(zipped)
>>> b
[]
>>> zipped
zip对象还在,但内含的数据内存已在第1次被迭代的时候释放了。
从zip函数直接获取tuple对象,迭代和赋值一气呵成:
>>> x,y,z = zip('abc','123')
>>> x
('a', '1')
>>> y
('b', '2')
>>> z
('c', '3')
Python官方有一个使用zip函数来做矩阵转置的case,比较有意思:
>>> matrix = [
... (1,2,3,4),
... (5,6,7,8),
... (9,10,11,12),
... ]
>>> matrix
[(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]
>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
以上就是对Python内置的zip函数的介绍,我觉得关键还是要理解可迭代对象这个核心概念。
-- EOF --