1. 程式人生 > >Python中zip()函式的解釋和視覺化

Python中zip()函式的解釋和視覺化

zip()的作用

先看一下語法:

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

Python的內建help()模組提供了一個簡短但又有些令人困惑的解釋:

返回一個元組迭代器,其中第i個元組包含每個引數序列或可迭代物件中的第i個元素。當最短的可迭代輸入耗盡時,迭代器將停止。使用單個可迭代引數,它將返回1元組的迭代器。沒有引數,它將返回一個空的迭代器。

與往常一樣,當您精通更一般的電腦科學和Python概念時,此模組非常有用。但是,對於初學者來說,這段話只會引發更多問題。讓我們嘗試通過示例,程式碼片段和視覺化來解釋zip()功能:
從許多迭代中獲取元素,然後…… 放在一起

我們可以通過幾個列表來演示zip()的功能:

uppercase = ['A', 'B', 'C']
lowercase = ['a', 'b', 'c']

for x, y in zip(uppercase, lowercase):
    print(x, y)

輸出:

A a
B b
C c

但是,不限於兩個可迭代物件作為引數傳遞-我們可以新增任意多個:

uppercase = ['A', 'B', 'C']
lowercase = ['a', 'b', 'c']
numbers = [1, 2, 3]

for x, y, z in zip(uppercase, lowercase, numbers):
    print(x, y, z)

這將輸出:

A a 1
B b 2
C c 3

讓我們直觀地看一下該zip()函式在Python中的工作方式:

zip()函式的另一個重要警告是如果各個迭代器的元素個數不一致,則返回列表長度與最短的物件相同:

uppercase = ['A', 'B', 'C', 'D', 'E']
lowercase = ['a', 'b', 'c', 'd']
numbers = [1, 2, 3]

for x, y, z in zip(uppercase, lowercase, numbers):
    print(x, y, z)

輸出:

A a 1
B b 2
C c 3

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

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

儘管似乎在呼叫此函式時會得到一個列表,但實際上它返回一個稱為zip object的特殊資料型別,這意味著使用索引將無法瀏覽,下面我們學習如何將其轉換為其他資料型別(例如列表)。

在此之前,我們還應再來學習一下迭代(Iteration)、迭代器物件(iterable)、迭代器(iterator )的概念:

  • Iteration是電腦科學的通用術語。它是指對一組元素執行一項操作,一次執行一個元素。一個很好的例子是迴圈 -它適用於每個單獨的專案,直到整個專案集執行完畢為止。
  • Iterable是可以遍歷的物件(譯者注:在Python中所有東西都是object, 比如說變數,容器,類),iterable是可以產生iterator的object。
  • iterator是表示資料流的物件,它一次返回一個元素的資料。它還會記住其在迭代過程中的位置。本質上,它控制應如何迭代可迭代物件。

將zip()物件轉換為列表(並使用索引)

zip()函式返回一個zip物件(類似於map()操作方式)。

zip物件提供了一些有趣的功能(迭代速度比list更快),但是我們經常需要將其轉換為list。為了做到這一點,我們需要呼叫list()函式:

b = ["red", "green", "blue"]
c = ["leopard", "cheetah", "jaguar"]

print(list(zip(b, c)))

輸出:

[('red', 'leopard'), ('green', 'cheetah'), ('blue', 'jaguar')]

list()函式將zip物件轉換為一個元組列表。我們可以使用索引瀏覽各個元組。出於可讀性考慮,我們首先將新列表分配給一個變數:

b = ["red", "green", "blue"]
c = ["leopard", "cheetah", "jaguar"]
new_list = list(zip(b, c))
print(new_list[0])
print(new_list[1])
print(new_list[2])

這將輸出:

('red', 'leopard')
('green', 'cheetah')
('blue', 'jaguar')

將zip()物件轉換成字典

另外,該dict()函式可用於將zip物件轉換為字典。需要注意的是,只能使用兩個zip()引數-前者產生key,後者產生value:

b = ["red", "green", "blue"]
f = ["strawberry", "kiwi", "blueberry"]

print(dict(zip(b, f)))

輸出:

{'red': 'strawberry', 'green': 'kiwi', 'blue': 'blueberry'}

解壓列表

在某些情況下,我們需要執行相反的操作——解壓迭代器。解壓操作涉及將壓縮後的元素恢復為其原始狀態。為此,我們新增*運算子到函式呼叫中。例:

a = [1, 2, 3]
b = [4, 5, 6]
zipped = zip(a, b)
list(zipped)

a2, b2 = zip(*zip(a, b))
print(a == list(a2) and b == list(b2))

輸出:

True

Zip與列表生成式(for迴圈潛在問題)

zip()函式與Python中的for迴圈一起使用的視覺化

在應用for迴圈後注意缺少的元素!

Python的另一個很棒的功能——列表推導式,可以與zip()函式結合使用。表面上看起來很簡單……

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

[print(a, b) for a, b in zip(m, n)]

輸出:

mind norm
mouse night
mini necklace

看起來很簡單,似乎沒有任何錯誤,對嗎?是的

如果我們想a從列表生成式獲取引數並打印出來,我們得到a NameError的報錯提示,這是完全正常的,因為a在列表推導之外不是實數:

Traceback (most recent call last):
  File "C:\Pro\Py\tp-ex\tmp1.py", line 5, in 
    print(a)
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)

print(m)

結果輸出是…

mind norm
mouse night
mini necklace
mini

等等,叛逆的mini在這裡幹什麼?事實證明,m先前引用的列表變數"mind", "mouse", "mini"被覆蓋了!因此,應該牢記列表生成式和for迴圈的執行方式完全不同。

結論

好吧,事實證明,zip()函式在 Python 中確實有一些竅門!