Python3中zip()函数使用详解:内存机制与多维应用

沈亦白
沈亦白
发布时间:2026-10-13 | 4人浏览过
原创

本文深入解析Python3中zip()函数的核心机制,重点说明其作为迭代器仅能访问一次的内存优化特性,对比Python2的差异。详细演示单参数、多参数及矩阵场景下的用法,包括列表推导式实现矩阵加减点乘,以及利用*zip进行数据解包还原的方法,帮助开发者避免常见错误并高效处理多维数据。

在Python3中,出于内存优化的考虑,zip()函数生成的对象只能被访问一次。这与Python2的行为不同,在Python2中zip返回的是列表,可以多次访问。开发者在使用时必须注意这一关键区别,避免因重复迭代导致数据丢失。

* coding: utf-8 * 


zip()函数的基本定义是从多个传入的迭代器中依次取出元素,组合成一个新的迭代器。其返回值是一个zip对象,内部元素为元组。该对象可以转换为列表或元组以方便查看或使用。传入的参数可以是元组、列表、字典等任何支持迭代的对象。当zip()函数仅接收一个参数时,即zip(iterable),它会从该迭代器中依次取出元素,并将每个元素包装成一个单元素元组,最终组成一个新的迭代器。

在Python 3.0及以上版本中存在一个重要的行为特征:zip对象中的数据只能操作一次。一旦迭代完成,其内部内存资源会被释放。如果试图在下一次访问该zip对象,将会引发错误或返回空结果,例如在示例1中尝试再次输出zip对象时就会遇到这种情况。

具体表现为访问已耗尽的zip对象时会报错或返回空列表,如例子1中的输出操作所示,这验证了上述内存释放机制。

1、zip()函数单个参数的应用情况

print(‘=‘*10 + “zip()函数单个参数” + ‘=‘*10) 
list1 = [1, 2, 3, 4] 
tuple1 = zip(list1)

list2=list(tuple1)

首先打印zip函数的返回类型以确认其数据结构。

代码示例:print(“zip()函数的返回类型:\n”, type(tuple1)),执行结果显示其类型为zip。

接下来演示如何将zip对象转化为列表以便查看具体内容。

print(“zip对象转化为列表:\n”, list(tuple1))#值为[(1,), (2,), (3,), (4,)] 
print(“zip对象转化为列表:\n”, list(tuple1))#值为[]

print(“list2输出的列表1为:\n”,list2) 
print(“list2输出的列表2为:\n”,list2) 

当zip()函数接收两个参数时,即zip(a,b),函数会分别从迭代器a和b中依次各取出一个元素,组成一个元组。随后,将这些依次组成的元组合并成一个新的迭代器,即新的zip类型数据。需要注意的是,虽然zip不强制要求a与b的维数完全相同,但当两者具有相同的行数与列数时,会正常组合对应位置的元素。若a与b的行数或列数不同,zip会取两者结构中最小的行数和列数,依据这个最小维度将对应位置的元素进行组合。这种行为在效果上类似于调用itertools.zip_longest(*iterables)函数,但zip_longest会填充缺失值,而zip直接截断。

2、zip()函数有两个参数的具体场景

print(‘=‘*10 + “zip()函数有2个参数” + ‘=‘*10) 
m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
n = [[2, 2, 2], [3, 3, 3], [4, 4, 4]] 
p = [[2, 2, 2], [3, 3, 3]]

测试行与列相同的情况

代码示例:print(“行与列相同:\n”, list(zip(m, n)))

执行结果为:[([1, 2, 3], [2, 2, 2]), ([4, 5, 6], [3, 3, 3]), ([7, 8, 9], [4, 4, 4])]。

测试行与列不同的情况

代码示例:print(“行与列不同:\n”, list(zip(m, p)))

执行结果为:[([1, 2, 3], [2, 2, 2]), ([4, 5, 6], [3, 3, 3])]。可以看到,由于p矩阵较短,结果被截断,只保留了前两组对应元素。

3、zip()的实际应用,也可以结合for循环与列表推导式来实现更复杂的逻辑。

利用zip进行矩阵相加减及点乘运算

定义两个3x3矩阵:m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],n = [[2, 2, 2], [3, 3, 3], [4, 4, 4]]。

演示矩阵点乘操作

print(‘=‘*10 + “矩阵点乘” + ‘='10)#左右两端各有10个 
print([x*y for a, b in zip(m, n) for x, y in zip(a, b)])

[2, 4, 6, 12, 15, 18, 28, 32, 36]

矩阵相加与相减的逻辑与点乘类似,只需改变运算符即可。

print(‘=‘*10 + “矩阵相加,相减” + ‘=‘*10) 
print([x+y for a, b in zip(m, n) for x, y in zip(a, b)])

[3, 4, 5, 7, 8, 9, 11, 12, 13]

4、*zip的操作限制

m5=[1,2,3] 
n5=[4,5,6] 
k5=[7,8,9] 
zip5=zip(m5,n5,k5)

print(“list(zip5):”,list(zip5))不能输出,否则zip(*zip5)

如果对已经耗尽的zip对象直接执行*zip操作,将无法执行或得到预期外的结果,如前文所述,必须先保存或使用一次。

m6,n6,k6=zip(*zip5) 
print(“m6:”,m6)#m6: (1, 2, 3) 
print(“n6:”,n6)#n6: (4, 5, 6) 
print(“k6:”,k6)#k6: (7, 8, 9)

5、*zip()函数的用法

*zip()函数是zip()函数的逆过程,用于将zip对象还原为原先组合前的数据。通过解包操作,可以将打包后的元组序列重新分离为原始的多个迭代器。

print(‘=‘*10 + “*zip()函数” + ‘=‘*10) 
m = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 
n = [[2, 2, 2], [3, 3, 3], [4, 4, 4]]

print(“zip(m, n)返回:\n”, zip(m, n)) # 
print(“*zip(m, n)返回:\n”, *zip(m, n))

*zip(m, n)返回:([1, 2, 3], [2, 2, 2]) ([4, 5, 6],[3, 3, 3]) ([7, 8, 9], [4, 4, 4])

print(“list(zip(m, n))返回:\n”, list(zip(m, n)))

list(zip(m, n))返回: [([1, 2, 3], [2, 2, 2]), ([4, 5, 6], [3, 3, 3]), ([7, 8, 9], [4, 4, 4])]

m2, n2 = zip(*zip(m, n))#先合到一块 
print(“m2:”,m2)#([1, 2, 3], [4, 5, 6], [7, 8, 9]) 
print(“n2:”,n2)#([2, 2, 2], [3, 3, 3], [4, 4, 4]) 
print(m == list(m2) and n == list(n2))#true

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表