1.zip()的作用

zip(iter1 [,iter2 [...]]) —> zip object

话不多说直接上例子:

  1. uppercase = ['A', 'B', 'C']
  2. lowercase = ['a', 'b', 'c']
  3. for x, y in zip(uppercase, lowercase):
  4. print(x, y)
  5. Out: A a
  6. B b
  7. C c

但是,不限于两个可迭代对象作为参数传递-我们可以添加任意多个:

  1. uppercase = ['A', 'B', 'C']
  2. lowercase = ['a', 'b', 'c']
  3. numbers = [1, 2, 3]
  4. for x, y, z in zip(uppercase, lowercase, numbers):
  5. print(x, y, z)
  6. Out: A a 1
  7. B b 2
  8. C c 3

让我们直观地看一下该zip()函数在Python中的工作方式:

image.png

zip()函数的另一个重要警告是如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同:

  1. uppercase = ['A', 'B', 'C', 'D', 'E']
  2. lowercase = ['a', 'b', 'c', 'd']
  3. numbers = [1, 2, 3]
  4. for x, y, z in zip(uppercase, lowercase, numbers):
  5. print(x, y, z)
  6. Out: A a 1
  7. B b 2
  8. C c 3

正如我们所看到的,即使列出了三个三元组,uppercase和lowercase列表具有5和4个元素。正如我们所看到的,即使列出了三个三元组,uppercase和lowercase列表具有5和4个元素。

要知道的重要一件事是zip()函数返回什么。

尽管似乎在调用此函数时会得到一个列表,但实际上它返回一个称为zip object的特殊数据类型,这意味着使用索引将无法浏览,下面我们学习如何将其转换为其他数据类型(例如列表)。
**
在此之前,我们还应再来学习一下迭代(Iteration)、迭代器对象(iterable)、迭代器(iterator )的概念:

  • Iteration是计算机科学的通用术语,它是指对一组元素执行一项操作,一次执行一个元素。一个很好的例子是循环 -它适用于每个单独的项目,直到整个项目集运行完毕为止。


  • Iterable是可以遍历的对象(注:在Python中所有的东西都是object,比如说变量,容器,类),iterable是可以产生iterable的object。


  • iterator是表示数据流的对象,它一次返回一个元素的数据,它还会记住其在迭代过程中的位置。本质上,它控制应如何迭代可迭代对象。


2.将zip()对象转换为列表(并使用索引)


zip()函数返回一个zip对象
**zip对象提供了一些有趣的功能(迭代速度比list更快),但是我们经常需要将其转换为list。为了做到这一点,我们需要调用list()函数:

  1. b = ["red", "green", "blue"]
  2. c = ["leopard", "cheetah", "jaguar"]
  3. print(list(zip(b, c)))
  4. Output:
  5. [('red', 'leopard'), ('green', 'cheetah'), ('blue', 'jaguar')]

list()函数将zip对象转换为一个元组列表。我们可以使用索引浏览各个元组。出于可读性考虑,我们首先将新列表分配给一个变量:

  1. b = ["red", "green", "blue"]
  2. c = ["leopard", "cheetah", "jaguar"]
  3. new_list = list(zip(b, c))
  4. print(new_list[0])
  5. print(new_list[1])
  6. print(new_list[2])
  7. Output:
  8. ('red', 'leopard')
  9. ('green', 'cheetah')
  10. ('blue', 'jaguar')

3.将zip()对象转换成字典

另外,该dict()函数可用于将zip对象转换为字典。需要注意的是,只能使用两个zip()参数-前者产生key,后者产生value:

  1. b = ["red", "green", "blue"]
  2. f = ["strawberry", "kiwi", "blueberry"]
  3. print(dict(zip(b, f)))
  4. Output:
  5. {'red': 'strawberry', 'green': 'kiwi', 'blue': 'blueberry'}

4.解压列表

在某些情况下,我们需要执行相反的操作——解压迭代器。解压操作涉及将压缩后的元素恢复为其原始状态。为此,我们添加*运算符到函数调用中。例:

  1. a = [1, 2, 3]
  2. b = [4, 5, 6]
  3. zipped = zip(a, b)
  4. list(zipped)
  5. a2, b2 = zip(*zip(a, b))
  6. print(a == list(a2) and b == list(b2))
  7. Out:
  8. True

5.Zip与列表生成式(for循环潜在问题)

zip()函数与Python中的for循环一起使用的可视化

image.png

在应用for循环后注意缺少的元素!

Python的另一个很棒的功能——列表推导式,可以与zip()函数结合使用。表面上看起来很简单……

  1. m = ["mind", "mouse", "mini"]
  2. n = ["norm", "night", "necklace"]
  3. [print(a, b) for a, b in zip(m, n)]
  4. Out:
  5. mind norm
  6. mouse night
  7. mini necklace

看起来很简单,似乎没有任何错误,对吗?是的
如果我们想a从列表生成式获取参数并打印出来,我们得到a NameError的报错提示,这是完全正常的,因为a在列表推导之外不是实数

  1. print(a)
  2. Traceback (most recent call last):
  3. File "C:\Pro\Py\tp-ex\tmp1.py", line 5, in
  4. print(a)
  5. NameError: name 'a' is not defined

但是,如果我们决定使用for循环而不是列表生成式,然后打印a,我们会得到一些奇怪的结果。请记住,for循环输出的结果与列表生成式的结果相同。

m = ["mind", "mouse", "mini"]
n = ["norm", "night", "necklace"]




for m, n in zip(m, n):
    print(m, n)

Out:
    mind norm
    mouse night
    mini necklace

这是看起来输出似乎并没有什么问题!!

但是如果我们输出 m:

print(m)

Out:
    mini

事实证明,m先前引用的列表变量”mind”, “mouse”, “mini”被覆盖了!因此,应该牢记列表生成式和for循环的运行方式完全不同。