HOWTO · Python

如何在 Python 中將字典的鍵轉成列表

了解如何用 list()、迴圈、列表推導式或解包語法取得 Python 字典的鍵列表,並分辨 dict_keys 檢視物件與列表。

本頁內容

若要將 Python 字典的鍵 轉成列表,直接使用 list(my_dict);list(my_dict.keys()) 也會得到相同結果。這兩種寫法都透過 list() 建構子建立新的鍵列表。單獨呼叫 my_dict.keys() 會得到 dict_keys 檢視物件;它可以迭代,卻不能像列表一樣用索引取值。需要列表物件時再轉換;如果只要逐一處理鍵,通常直接迭代字典就夠了。

dict.keys() 取得 Python 字典的鍵

dict.keys() 方法會傳回目前字典鍵的檢視物件。之後若修改字典,檢視物件會反映變更;由它建立的列表則是獨立的資料快照。在 Python 3.7 及更新版本中,迭代字典會依鍵的插入順序進行;以下輸出採用這項順序保證。

state_capitals = {
    "California": "Sacramento",
    "Pennsylvania": "Harrisburg",
    "Texas": "Austin",
}

keys_view = state_capitals.keys()
print(keys_view)
for state in keys_view:
    print(state)

keys_list = list(keys_view)
print(keys_list)
print(list(state_capitals))
print(keys_list[0])

state_capitals["Nevada"] = "Carson City"
print(list(keys_view))
print(keys_list)
dict_keys(['California', 'Pennsylvania', 'Texas'])
California
Pennsylvania
Texas
['California', 'Pennsylvania', 'Texas']
['California', 'Pennsylvania', 'Texas']
California
['California', 'Pennsylvania', 'Texas', 'Nevada']
['California', 'Pennsylvania', 'Texas']

list(keys_view) 與 list(state_capitals) 都會建立列表。後者之所以可行,是因為迭代字典會取得鍵。若直接對檢視物件使用索引,會引發 TypeError。空字典轉成列表會得到 [];若再對這個空列表取索引,則會引發 IndexError。

使用迴圈取得 Python 字典的鍵

如果收集鍵時還需要逐一處理,可以明確寫出迴圈。使用 for key in state_capitals:其中的 in 是必要的關鍵字,迴圈取得的是鍵,而不是值。

state_capitals = {
    "California": "Sacramento",
    "Pennsylvania": "Harrisburg",
    "Texas": "Austin",
}

keys = []
for key in state_capitals:
    keys.append(key)
print(keys)
['California', 'Pennsylvania', 'Texas']

若字典為空,迴圈不會執行,keys 會維持空列表。如果只是單純取得鍵,沒有其他逐項處理,list(state_capitals) 更簡潔。

使用列表推導式取得 Python 字典的鍵

列表推導式 能以一行寫出相同的收集迴圈。若要加上篩選條件或轉換每個鍵,這種寫法很適合;若只要複製鍵,使用 list() 建構子更簡單。

state_capitals = {
    "California": "Sacramento",
    "Pennsylvania": "Harrisburg",
    "Texas": "Austin",
}

keys = [key for key in state_capitals]
print(keys)
['California', 'Pennsylvania', 'Texas']

字典為空時,這個列表推導式也會得到 []。

使用 Python 字典解包運算子 * 取得鍵

可迭代物件的解包語法 * 能將字典的鍵放進列表:[*state_capitals]。PEP 448 在 Python 3.5 擴充了解包語法;這項版本相容性來自語法規範,並非在此以 Python 3.5 實際執行驗證。元組和集合也能使用解包語法。

state_capitals = {
    "California": "Sacramento",
    "Pennsylvania": "Harrisburg",
    "Texas": "Austin",
}

keys_list = [*state_capitals]
keys_tuple = (*state_capitals,)
keys_set = {*state_capitals}
print(keys_list)
print(keys_tuple)
print(sorted(keys_set))
['California', 'Pennsylvania', 'Texas']
('California', 'Pennsylvania', 'Texas')
['California', 'Pennsylvania', 'Texas']

集合會去除重複元素,而且不保證顯示順序;範例使用 sorted(),讓輸出內容的順序可預期。在 Python 3.7 及更新版本中,元組和列表會保留字典的迭代順序。如果結果必須是列表,就使用列表寫法。

比較各種方法的執行效能

如果轉換速度很重要,請用實際使用的 Python 直譯器,以及與真實資料規模相近的字典測量。以下程式會印出 Python 版本,並對同一個含 100 筆資料的字典,各執行五輪、每輪轉換 10,000 次,再回報其中最快一輪的平均單次時間。每次計時的運算都會建立新列表;迴圈寫法每次轉換也會重新建立用來存放結果的列表。

import platform
from timeit import repeat

state_capitals = {str(number): number for number in range(100)}
methods = {
    "list(d.keys())": "list(state_capitals.keys())",
    "list(d)": "list(state_capitals)",
    "loop": "keys = []\nfor key in state_capitals:\n    keys.append(key)",
    "comprehension": "[key for key in state_capitals]",
    "unpacking": "[*state_capitals]",
}

print("Python", platform.python_version())
for name, statement in methods.items():
    times = repeat(statement, globals=globals(), number=10_000, repeat=5)
    print(f"{name}: {min(times) / 10_000:.9f} seconds per conversion")

印出的時間會受直譯器、電腦及字典大小影響,因此沒有固定輸出,也沒有在所有環境都最快的方法。一般程式碼可優先選用易讀的 list(state_capitals);只有當轉換成本對程式有明顯影響時,才需要比較其他寫法。