Bootstrap

python 3 zip()函数用法解析 及 经典错误解析

参考资料1
参考资料2
参考资料3

描述

zip() 函数用于将可迭代的(比如列表、元组等)对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。

我们可以使用 list() 转换来输出列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
zip 方法在 Python 2 和 Python 3 中的不同:在 Python 2.x zip() 返回的是一个列表。
如果需要了解 Pyhton2 的应用,可以参考 Python zip()。

zip用法

keys = ['one', 'two', 'three', 'four']
values = [1, 2, 3]
d = zip(keys, values)
print(d)
#<zip object at 0x0000023A69F436C8>
print(list(d))
# [('one', 1), ('two', 2), ('three', 3)]

这里每次组合时依次取出对应顺序的对象元素(如’one’和1)组合为元组,直到最少的对象中元素全部被组合,剩余的其他对象中未被组合的元素将被舍弃。

*zip用法

从已迭代的对象中还原至原来的对象,类似在压缩后“解压”。

keys = ['one', 'two', 'three', 'four']
values = [1, 2, 3]
d = zip(keys, values)
keys_1, values_1 = zip(*d)

print(keys_1)
# ('one', 'two', 'three') 是一个元组,不再是列表
 
print(list(values_1))
# [1, 2, 3] 需要手动转化为列表

常见错误说明:zip返回的值是一个迭代器指针,使用for循环后,指针将被置于数据的结尾,再进行其他操作时会出现错误。(转化为list的操作本质上也是一个for循环)

以下两种操作无报错,但结果不对

keys = ['one', 'two', 'three', 'four']
values = [1, 2, 3]
d = zip(keys, values)
print(d)
# <zip object at 0x0000023A69F436C8>
print(list(d))
# [('one', 1), ('two', 2), ('three', 3)]
for item in d:
    print(item)

后面的for循环将没有任何输出,因为前面的list操作已经将指针指向数据末尾。

keys = ['one', 'two', 'three', 'four']
values = [1, 2, 3]
d = zip(keys, values)
print(d)
# <zip object at 0x0000023A69F436C8>
for item in d:
    print(item)
# ('one', 1)
# ('two', 2)
# ('three', 3)
print(list(d))
# []

两个语句反过来,list操作输出的结果为[]

以下操作会报错(一般涉及*zip操作)

keys = ['one', 'two', 'three', 'four']
values = [1, 2, 3]
d = zip(keys, values)
print(list(d))  # 使用 list() 转换来输出,返回列表的长度与最短的对象相同
a1,a2 = zip(*d)  # 与 zip 相反,zip(*) 可理解为解压,返回二维矩阵式
print(a1)

# ValueError                                Traceback (most recent call last)
# <ipython-input-72-23d98b2e87d7> in <module>
#       3 d = zip(keys, values)
#       4 print(list(d))  # 使用 list() 转换来输出,返回列表的长度与最短的对象相同
# ----> 5 a1,a2 = zip(*d)  # 与 zip 相反,zip(*) 可理解为解压,返回二维矩阵式
#       6 print(a1)
#       7 

# ValueError: not enough values to unpack (expected 2, got 0)

如果指针位于数据起始,会有2个数据用于解压,但现在由于list操作,指针位于数据末尾,只有0个数据用于解压,因此*zip操作会报错。

keys = ['one', 'two', 'three', 'four']
values = [1, 2, 3]
d = zip(keys, values)
for item in d:
    print(item)
    
older = list(zip(*d))
print(older[0])
print(older[1])

# ('one', 1)
# ('two', 2)
# ('three', 3)
# ---------------------------------------------------------------------------
# IndexError                                Traceback (most recent call last)
# <ipython-input-82-5383a9a8e39e> in <module>
#       6 
#       7 older = list(zip(*d))
# ----> 8 print(older[0])
#       9 print(older[1])

# IndexError: list index out of range

错误在第8行,*zip的操作是没有问题的,但解压出来的对象是个空的对象,list出来的也是个[], 所以索引的时候会out of range。

END

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;