揭祕 Python 中的 enumerate() 函式

MHyourh發表於2020-11-28

如何以去寫以及為什麼你應該使用Python中的內建列舉函式來編寫更乾淨更加Pythonic的迴圈語句?

Python的 enumerate函式是一個神話般的存在,以至於它很難用一句話去總結它的目的和用處。

但是,它是一個非常有用的函式,許多初學者,甚至中級Pythonistas是並沒有真正意識到。簡單來說, enumerate()是用來遍歷一個可迭代容器中的元素,同時通過一個計數器變數記錄當前元素所對應的索引值。

讓我們來看一個示例:

names = ['Bob', 'Alice', 'Guido']

for index, value in enumerate(names):

   print(f'{index}: {value}')

這段程式碼會輸入如下內容:

正如你所看到的,這個迴圈遍歷了 names列表的所有元素,並通過增加從零開始的計數器變數來為每個元素生成索引。

[如果您想知道上面例子中使用的f’…'字串語法,這是Python 3.6及更高版本中提供的一種新的字串格式化技巧。]

用 enumerate()讓你的迴圈更加Pythonic

那麼為什麼用 enumerate()函式去儲存執行中的索引很有用呢?

我發現,有很多從C或Java背景轉過來的新的Python開發人員有時使用下面這種 range(len(…))方法來儲存執行中每個元素的索引,同時再用 for迴圈遍歷列表:

# 警告: 不建議這麼寫
# 遇到問題沒人解答?小編建立了一個Python學習交流QQ群:778463939
# 尋找有志同道合的小夥伴,互幫互助,群裡還有不錯的視訊學習教程和PDF電子書!
for i in range(len(my_items)):

   print(i, my_items[i])

通過巧妙地使用 enumerate()函式,就像我在上面的"names"例子中寫的那樣,你可以使你的迴圈結構看起來更Pythonic和地道。

你不再需要在Python程式碼中專門去生成元素索引,而是將所有這些工作都交給 enumerate()函式處理即可。這樣,你的程式碼將更容易被閱讀,而且減少寫錯程式碼的影響。(譯者注:寫的程式碼越多,出錯機率越高,儘量將自己的程式碼看起來簡潔,易讀,Pythonic,才是我們的追求)

修改起始索引

另一個有用的特性是, enumerate()函式允許我們為迴圈自定義起始索引值。 enumerate()函式中接受一個可選引數,該引數允許你為本次迴圈中的計數器變數設定初始值:

# 遇到問題沒人解答?小編建立了一個Python學習交流QQ群:778463939
# 尋找有志同道合的小夥伴,互幫互助,群裡還有不錯的視訊學習教程和PDF電子書!
names = ['Bob', 'Alice', 'Guido']

for index, value in enumerate(names, 1):

   print(f'{index}: {value}')

在上面的例子中,我將函式呼叫改為 enumerate(names, 1),後面的引數1就是本次迴圈的起始索引,替換預設的0:

OK,這段程式碼演示的就是如何將Python的 enumerate()函式預設0起始索引值修改為1(或者其他任何整形值,根據需求去設定不同值)

enumerate()背後是如何工作的

你可能想知道 enumerate()函式背後是如何工作的。事實上他的部分魔法是通過Python迭代器來實現的。意思就是每個元素的索引是懶載入的(一個接一個,用的時候生成),這使得記憶體使用量很低並且保持這個結構執行很快。

讓我們演示一些更多的程式碼來表達我的意思:

>>> names = ['Bob', 'Alice', 'Guido']

>>> enumerate(names)

在上面這個程式碼片段中,正如你所見,我使用了和前面一樣的示例程式碼。但是,呼叫 enumerate()函式並不會立即返回迴圈的結果,而只是在控制檯中返回了一個 enumerate物件。

正如你所看到的,這是一個"列舉物件"。它的確是一個迭代器。就像我說的,它會在迴圈請求時懶載入地輸出每個元素。

為了驗證,我們可以取出那些"懶載入"的元素,我計劃在這個迭代器上呼叫Python的內建函式 list()

>>> list(enumerate(names))

[(0, 'Bob'), (1, 'Alice'), (2, 'Guido')]

對於輸入 list()中的每個 enumerate()迭代器元素,迭代器會返回一個形式為 (index,element)的元組作為list的元素。在典型的for-in迴圈中,你可以利用Python的資料結構解包功能來充分利用這一點特性:

for index, element in enumerate(iterable):

   # ...

總結:

Python中的enumerate函式 - 關鍵點

  • enumerate是Python的一個內建函式。你應該充分利用它通過迴圈迭代自動生成的索引變數。

  • 索引值預設從0開始,但也可以將其設定為任何整數。

  • enumerate函式是從2.3版本開始被新增到Python中的,詳情見PEP279。

  • Python的 enumerate函式可以幫助你編寫出更加Pythonic和地道的迴圈結構,避免使用笨重且容易出錯的手動生成索引。

  • 為了充分利用 enumerate的特性,一定要研究Python的迭代器和資料結構解包功能。

相關文章