2021年11月2日 星期二

Python 學習筆記 : 內建函式 enumerate() 的用法

內建函式 enumerate() 也是用來配對的, 但它是將傳入的序列型態物件 (元組, 串列, 字串) 與一組連續整數 (預設是 0 起始的整數) 配對成 tuple , 然後打包成 enumerate 物件傳回, 語法如下 :

enum=enumerate(序列 [, start=0])  

可見 enumerate() 其實是簡單版的 zip() 函式, 瞭解 zip() 函式用法後再來看 enumerate() 就很容易理解, 它相當於是幫傳入的序列型態物件加上一組明確的連動索引, 這對資料處理很有用處. 關於 zip() 函式用法參考 :


enumerate 物件與 zip 物件一樣都是可迭代與迭代器物件, 可用 for 迴圈或 next() 函式走訪其元素 (為 tuple), 也可以用 list(), tuple(), 或 dict() 轉換成串列, 元組, 或字典. 但迭代器的特性是一旦被走訪完畢或被轉換成 tuple, list, 與 dict, 其內容將被清空, 無法第二次走訪或做轉換, 必須重新建立 enumerate 物件, 關於可迭代與迭代器參考 : 


例如 :  

>>> company=['台積電', '聯發科', '台塑']       
>>> enum=enumerate(company)                   # 呼叫 enumerate() 做連續數值配對
>>> enum    
<enumerate object at 0x0000024D07D4BC18>     
>>> type(enum)                                                # enumerate() 傳回 enumerate 物件
<class 'enumerate'>    
>>> hasattr(enum, '__iter__')                         # enumerate 物件是可迭代物件
True    
>>> hasattr(enum, '__next__')                        # enumerate 物件是迭代器物件
True    
>>> for i in enum:                                             # 用 for 迴圈走訪 enumerate 物件
    print(i)    
    
(0, '台積電')
(1, '聯發科')
(2, '台塑')
>>> list(enum)                                                   # 走訪後 enumerate 物件已清空
[]  
>>> enum=enumerate(company)                    # 重新建立 enumerate 物件
>>> list(enum)                                                   # 轉成串列
[(0, '台積電'), (1, '聯發科'), (2, '台塑')]
>>> enum=enumerate(company)                    # 重新建立 enumerate 物件
>>> tuple(enum)                                               # 轉成元組
((0, '台積電'), (1, '聯發科'), (2, '台塑'))
>>> tuple(enum)                                               # 轉換後 enumerate 物件已清空
()
>>> enum=enumerate(company)                    # 重新建立 enumerate 物件
>>> dict(enum)                                                  # 轉成字典
{0: '台積電', 1: '聯發科', 2: '台塑'}

可見由於 enumerate() 是兩兩配對, 且配對時是以連續整數做為第一元素, 因此 enumerate 物件轉成字典完全沒有問題, 不像 zip() 因為可以將多個序列配對, 所以不一定能轉成字典 (兩兩配對時才能轉成字典), 而且可能有 key 重複問題. 

enumerate() 預設是將序列中的元素與 0 起始的連續整數配對, 但也可以用 start 參數指定起始整數, 例如 : 

>>> company=['台積電', '聯發科', '台塑', '玉山金', '統一超']     
>>> enum=enumerate(company, start=10)          # 用 index 參數指定起始整數
>>> list(enum)      
[(10, '台積電'), (11, '聯發科'), (12, '台塑'), (13, '玉山金'), (14, '統一超')] 

可見與序列元素配對的整數改為從 10 起算了. 這個 start 參數在資料處理上很實用, 例如有蠻多編號或索引系統是 1 起始. 

使用 enumerate() 函式可以讓程式碼更簡潔, 更有 Python 風格 (Pythonic), 利用 enumerate 物件所配對的連續數值可用來做為關聯到其它序列資料的索引, 例如 :

>>> students=['Peter', 'Tony', 'Amy', 'Kelly']    
>>> grades=[100, 95, 80, 92]    
>>> for index, student in enumerate(students):    
    grade=grades[index]    
    print('Name:', student, 'Grade:', grade)    
    
Name: Peter Grade: 100
Name: Tony Grade: 95
Name: Amy Grade: 80
Name: Kelly Grade: 92

此例將 students 序列傳入 enumerate() 做數值配對後, 利用走訪 enumerate 物件解包其 tuple 元素, 取得配對之索引與元素, 然後用此索引存取 grades 串列取得分數, 這種寫法具有 Python 的簡潔風格. 此例不使用 enumerate() 的寫法如下 : 

>>> students=['Peter', 'Tony', 'Amy', 'Kelly']    
>>> grades=[100, 95, 80, 92] 
>>> for index in range(len(students)):    
    student=students[index]                             # 利用 [索引] 取值
    grade=grades[index]                                   # 利用 [索引] 取值
    print('Name:', student, 'Grade:', grade)     
    
Name: Peter Grade: 100
Name: Tony Grade: 95
Name: Amy Grade: 80
Name: Kelly Grade: 92

雖然也沒有很冗長, 但使用 len() 與 range() 套疊, 以及 [] 運算子取值就有點 "老實與樸拙". 

沒有留言 :