Python專題 詳解enumerate和zip

2022-01-11 02:24:44 字數 3474 閱讀 8875

首先介紹的是enumerate函式。

在我們日常程式設計的過程當中,經常會遇到乙個問題。

在c語言以及一些古老的語言當中是沒有迭代器這個概念的,所以我們要遍歷陣列或者是容器的時候,往往只能通過下標。有了迭代器之後,我們遍歷的過程方便了很多,我們可以直接用乙個變數去迭代乙個容器當中的值。最簡單的例子就是陣列的遍歷,比如我們要遍歷items這個陣列。我們可以直接:

for item in items:

通過迭代器的方式我們可以很輕鬆地遍歷陣列,而不再需要下標,也不需要計算陣列的長度了。但是如果我們在迴圈體當中需要知道元素的下標該怎麼辦

難道我們真的只能在下標和迭代器當中選擇乙個嗎,比如在迴圈體的外面新增乙個變數來記錄下標?

idx = 0

for item in items:

operation()

idx += 1

這樣可以解決問題,但是很麻煩,一點也不簡潔,用專業的話來說一點也不pythonic(符合python標準的**)。為了追求pythonic,於是有了enumerate函式,來解決了我們又想直接迭代又需要知道元素下標的情形。

它的用法也很簡單,我們把需要迭代的物件或者迭代器傳入enumerate函式當中,它會為我們建立乙個新的迭代器,同時返回下標以及迭代的內容。我們來看乙個例子:

for i, item in enumerate(items):

除此之外,enumerate還支援傳入引數。比如在某些場景當中,我們希望下標從1開始,而不再是0開始,我們可以額外多傳入乙個引數實現這點:

for i, item in enumerate(items, 1):

迴圈是我們程式設計的時候必不可少的操作,也正因此,enumerate函式使用非常廣泛。但是有一點需要注意,如果我們迭代的是乙個多元組陣列,我們需要注意要將index和value區分開。舉個例子:

data = [(1, 3), (2, 1), (3, 3)]

在不用enumerate的時候,我們有兩種迭代方式,這兩種都可以執行。

for x, y in data:

for (x, y) in data:

但是如果我們使用enumerate的話,由於引入了乙個index,我們必須要做區分,否則會報錯,所以我們只有一種迭代方式:

for i, (x, y) in enumerate(data):

接下來要介紹的另乙個函式同樣是方便我們迭代的,不過它針對的是另乙個場景——多物件迭代

它的應用場景非常簡單,就是我們想要同時迭代多份資料,比如使用者的名字和使用者的職業資料是分開的,我們希望同時遍歷乙個使用者的職業和名字。如果不使用zip,我們可能只能放棄迭代器回到傳統的下標遍歷的模式了。這樣當然是可以的,不過有兩個小問題,第乙個小問題當然是**的可讀性變差了,不夠pythonic,第二個問題是我們需要維護兩個容器長度不一樣的情況,會增加額外的**。而使用zip,可以同時解決以上兩個問題。

我們來看乙個例子:

names = ['xiaoming', 'xiaohua', 'xiaohei', 'xiaoli']

jobs = ['coach', 'student', 'student', 'student', 'professor']

for name, job in zip(names, jobs):

print(name, job)

最後輸出的結果是人名和職業的tuple:

xiaoming coach

xiaohua student

xiaohei student

xiaoli student

上面舉的例子當中,names和jobs的長度其實是不一致的,在使用了zip的情況下,會自動替我們按照其中較短的那個進行截斷。如果我們不希望截斷,我們也可以使用itertools下的zip_longest來代替zip:

from itertools import zip_longest

for name, job in zip_longest(names, jobs):

這樣的話長度不夠的元素會以none來填充,zip_longest提供了乙個引數fillvalue,可以填充成我們指定的值。

無論是zip還是zip_longest,都可以支援多迭代器的遍歷。比如:

names = ['xiaoming', 'xiaohua', 'xiaohei', 'xiaoli']

jobs = ['coach', 'student', 'student', 'student', 'professor']

hobbies = ['footbal', 'tennis', 'badminton', 'basketbal']

for name, job, hobby in zip(names, jobs, hobbies):

print(name, job, hobby)

zip除了方便我們迭代遍歷之外,另乙個很大的用處是可以很方便地生成dict。比如剛才的例子當中,我們想生成乙個名稱和職業的dict,一般的辦法當然是先定義乙個dict,然後遍歷所有的key和value,來生成dict。然而使用zip,我們可以將這個操作簡化到一行**:

jobdict = dict(zip(names, jobs))

print(zip(names, jobs))

>>>

0x10ec93b40>

我們想要獲得它的內容,需要將它手動轉成list:

print(list(zip(names, jobs)))

>>> [('xiaoming', 'coach'), ('xiaohua', 'student'), ('xiaohei', 'student'), ('xiaoli', 'student')]

無論是enumerate還是zip其實底層都是基於迭代器實現的,從原理上來說並沒有什麼太深奧的內容,而且我們不使用它們也不影響我們寫**。但是python之所以是python,之所以很多人稱道它簡潔的語言和邏輯,離不開我們廣泛地使用這些簡化**邏輯的工具和方法。因此我們加以了解是非常有必要的,希望大家都能寫出pythonic的**,不僅寫**能力強,而且**本身也漂亮。

redis專題 slow log詳解

slowlog subcommand argument 什麼是 slowlog slow log 是 redis 用來記錄查詢執行時間的日誌系統。查詢執行時間指的是不包括像客戶端響應 talking 傳送回覆等 io 操作,而單單是執行乙個查詢命令所耗費的時間。另外,slow log 儲存在記憶體裡...

python專題 python基礎

這個就基礎了,變數和常量的主要最為本質的原因是記憶體中,該塊記憶體的讀寫許可權,常量是不可以被重新賦值的,變數是可以被重新賦值。換句話說,變數的記憶體是可以被讀寫的,而常量的記憶體許可權僅僅是唯讀。python中的識別符號和其他語言都基本一樣,只能由字母,數字,下劃線組成,數字不能開頭!python...

Python專題講解

python中的切片表示法 使用python實現乙個迴圈輸入 在python中複製乙個列表list 理解python的引數傳遞 理解python雙星和單星對引數的作用 理解python中的作用域規則 python中yield關鍵字的作用 在python中呼叫外部命令 if name main 的作用...