HOWTO · Python

Python で辞書のキーをリストとして取得する方法

Python の辞書のキーを list()、ループ、リスト内包表記、アンパックでリストにする方法と、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 回変換する測定を 5 回行って、その最短時間を報告します。計測対象の各処理は毎回新しいリストを作り、ループ方式も変換のたびに空の格納先を作ります。

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) を選び、変換のコストがプログラムで実際に問題になる場合だけ、ほかの方法を比較してください。