[譯]Python的enumerate()函式揭祕

vimiix發表於2019-03-01

今天的原文的作者是來自國外的以為Python“佈道師”Dan Bader,他的部落格完全就是一個個人品牌的學校。有跟多Python技巧,有很多他錄製的Youtube視訊,國內的Pythonista們,不妨訂閱一下他的每週郵件推送。訂閱連結

今天的譯文是他部落格中的一篇,點選檢視原文

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

python-enumerate.jpg

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

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

讓我們來看一個示例:

names = ['Bob', 'Alice', 'Guido']
for index, value in enumerate(names):
    print(f'{index}: {value}')
複製程式碼

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

0: Bob
1: Alice
2: Guido
複製程式碼

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

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

enumerate()讓你的迴圈更加Pythonic

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

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

# 警告: 不建議這麼寫
for i in range(len(my_items)):
    print(i, my_items[i])
複製程式碼

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

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

修改起始索引

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

names = ['Bob', 'Alice', 'Guido']
for index, value in enumerate(names, 1):
    print(f'{index}: {value}')
複製程式碼

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

1: Bob
2: Alice
3: Guido
複製程式碼

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

enumerate()背後是如何工作的

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

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

>>> names = ['Bob', 'Alice', 'Guido']
>>> enumerate(names)
<enumerate object at 0x1057f4120>
複製程式碼

在上面這個程式碼片段中,正如你所見,我使用了和前面一樣的示例程式碼。但是,呼叫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的迭代器和資料結構解包功能。

譯者部落格:vimiix.com

相關文章