Pythonのdictクラスには、辞書を扱うための便利なメソッドがたくさん用意されています。
その一部は、dictのコンセプトですでに紹介しました。
ここでは、さらにいくつかのメソッドと、辞書を繰り返し処理したり操作したりするためのテクニックを紹介します。
<dict>.setdefault()は、KeyErrorを発生させずにキーを自動的に追加します。<dict>.fromkeys(<iterable>, <default value>)は、任意の数のイテラブルから新しいdictを作成します。<dict>.keys()、<dict>.values()、<dict>.items()は、便利なイテレーターを提供します。sorted(<dict>.items())を使うと、dictの項目を簡単に並べ替えられます。<dict_one>.update(<dict_two>)は、あるdictを、別のdictの重複する値で更新します。<dict> | <other_dict>と<dict> |= <other_dict>は、演算子を使って2つのdictをマージまたは更新します。reversed(<dict>.keys())、reversed(<dict>.values())、reversed(<dict>.items())は、_逆順_のビューを生成します。<dict>.popitem()は、keyとvalueのペアを削除して返します。setdefault()
辞書のコンセプトでは、<dict>.get(<key>, <default value>)が、辞書にkeyが見つからない場合に既存のvalueまたはdefault valueを返し、それによってKeyErrorを避けられることをすでに扱いました。
これは、余分なエラー処理を書きたくないけれど、探しているkeyが必ずあるとは限らない場合に便利です。
同じように「安全な」(KeyErrorを出さずに)挿入操作には、<dict>.setdefault(<key>, <default value>)メソッドがあります。
<dict>.setdefault(<key>, <default value>)は、keyが辞書に見つかればvalueを返します。
keyが見つからなければ、(key, default value)のペアを_挿入_し、default valueを返して使えるようにします。
>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'}
# Looking for the value associated with key "Rock Brown".The key does not exist,
# so it is added with the default value, and the value is returned.
>>> palette.setdefault('Rock Brown', '#694605')
'#694605'
# The (key, default value) pair has now been added to the dictionary.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Rock Brown': '#694605'}
fromkeys()
さまざまなkeysとデフォルト値で辞書をすばやく埋めるには、クラスメソッド fromkeys(<iterable>, <default value>)が、keysのイテラブルを繰り返し処理して新しいdictを作成します。
すべてのvaluesは、指定したdefault valueに設定されます。
>>> new_dict = dict.fromkeys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'], 'fill in hex color here')
{'Grassy Green': 'fill in hex color here',
'Purple Mountains Majesty': 'fill in hex color here',
'Misty Mountain Pink': 'fill in hex color here'}
.popitem()で(key, value)ペアを削除して返す.popitem()は、辞書から(key, value)のペアを1つ削除して返します。
ペアは後入れ先出し(LIFO)の順で返されます。
辞書が空の場合、popitem()を呼び出すとKeyErrorが発生します。
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
>>> palette_I.popitem()
('Misty Mountain Pink', '#f9c5bd')
>>> palette_I.popitem()
('Purple Mountains Majesty', '#8076a3')
>>> palette_I.popitem()
('Grassy Green', '#9bc400')
# All (key, value) pairs have been removed.
>>> palette_I.popitem()
Traceback (most recent call last):
line 1, in <module>
palette_I.popitem()
KeyError: 'popitem(): dictionary is empty'
.keys()、.values()、.items()メソッドは、辞書のイテラブルビューを返します。
これらのビューを使うと、項目を変更せずに簡単にループできます。
ビューは_動的_でもあります。元になっている辞書のデータが変わると、対応するview objectにもその変更が反映されます。
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
# Using .keys() returns a list of keys.
>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'])
# Using .values() returns a list of values.
>>> palette_I.values()
dict_values(['#9bc400', '#8076a3', '#f9c5bd'])
# Using .items() returns a list of (key, value) tuples.
>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', '#8076a3'), ('Misty Mountain Pink', '#f9c5bd')])
# Views are dynamic. Changing values in the dict
# changes all of the associated views.
>>> palette_I['Purple Mountains Majesty'] = (128, 118, 163)
>>> palette_I['Deep Red'] = '#932432'
>>> palette_I.values()
dict_values(['#9bc400', (128, 118, 163), '#f9c5bd', '#932432'])
>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'Deep Red'])
>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', (128, 118, 163)), ('Misty Mountain Pink', '#f9c5bd'), ('Deep Red', '#932432')])
.keys()、.values()、.items()をもっと詳しくPython 3.7以降では、dictsは項目が挿入された順序を保持するため、.keys()、.values()、.items()を使うと先入れ先出し(FIFO)で繰り返し処理できます。
Python 3.8以降では、ビューは_逆順にもたどれる_ようになりました。
これにより、reversed(<dict>.keys())、reversed(<dict>.values())、reversed(<dict>.items())を使うと、キー、値、または(key, value)のペアを後入れ先出し(LIFO)の順で繰り返し処理できます。
>>> palette_II = {'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
>>> for item in palette_II.items():
... print(item)
...
('Factory Stone Purple', '#7c677f')
('Green Treeline', '#478559')
('Purple baseline', '#161748')
>>> for item in reversed(palette_II.items()):
... print(item)
...
('Purple baseline', '#161748')
('Green Treeline', '#478559')
('Factory Stone Purple', '#7c677f')
.update()で辞書を結合する<dict_one>.update(<dict_two>)を使うと、2つの辞書を_結合_できます。
このメソッドは、<dict_two>の(key,value)ペアを取り出し、<dict_one>に書き込みます。
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple Baseline': '#161748'}
>>> palette_I.update(palette_II)
# Note that new items from palette_II are added.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple Baseline': '#161748'}
2つの辞書でキーが_重複_する場合、dict_oneのvalueは、dict_twoの対応するvalueで_上書き_されます。
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
>>> palette_III = {'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189)}
>>> palette_I.update(palette_III)
# Overlapping values in palette_I are replaced with
# values from palette_III
>>> palette_I
{'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189),
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559', 'Purple baseline': '#161748'}
|と|=)演算子を使って辞書をマージまたは更新するPython 3.9では、dictsをマージする別の方法として、union演算子が導入されました。
dict_one | dict_twoは、dict_oneとdict_twoの(key, value)ペアからなる新しい辞書を作成します。
両方の辞書に同じキーがある場合、dict_twoの値が優先されます。
>>> palette_I = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
>>> new_dict = palette_I | palette_II
>>> new_dict
...
{'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
dict_one |= otherは<dict_one>.update(<other>)と似た動作をしますが、この場合、otherにはdictまたは(key, value)ペアのイテラブルを指定できます。
>>> palette_III = {'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189)}
>>> new_dict |= palette_III
>>> new_dict
...
{'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189),
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
辞書には組み込みのソートメソッドがありません。
しかし、組み込み関数sorted()を.items()と組み合わせれば、dictの_ビュー_をソートできます。
ソートしたビューを使えば、新しい辞書を作成できます。
_ソートキー_を指定しない限り、デフォルトでは辞書のkeysを基準にソートされます。
# Default ordering for a dictionary is last in, first out (LIFO).
>>> color_palette = {'Grassy Green': '#9bc400',
'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
# The default sort order for a dictionary uses the keys.
>>> sorted_palette = dict(sorted(color_palette.items()))
>>> sorted_palette
{'Factory Stone Purple': '#7c677f',
'Grassy Green': '#9bc400',
'Green Treeline': '#478559',
'Misty Mountain Pink': '#f9c5bd',
'Purple Mountains Majesty': '#8076a3',
'Purple baseline': '#161748'}
# A sort key can be provided in the form
# of an anonymous function (lambda).
>>> value_sorted_palette = dict(sorted(color_palette.items(), key=lambda color: color[1]))
>>> value_sorted_palette
{'Purple baseline': '#161748',
'Green Treeline': '#478559',
'Factory Stone Purple': '#7c677f',
'Purple Mountains Majesty': '#8076a3',
'Grassy Green': '#9bc400',
'Misty Mountain Pink': '#f9c5bd'}
辞書のキーと値を確実に入れ替えるには少し手間がかかりますが、dict.items()を使ったloopや、辞書内包表記で実現できます。
安全に入れ替えるには、dictのキーと値の両方が_ハッシュ可能_であることが前提です。
color_reference = {'Purple Mountains Majesty': '#8076a3',
'Misty Mountain Pink': '#f9c5bd',
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}
# Creating a new dictionary to hold the swapped entries.
>>> swapped_color_reference = {}
# Iterating through the dictionary, using values as keys.
>>> for key, value in color_reference.items():
... swapped_color_reference[value] = key
>>> swapped_color_reference
{'#8076a3': 'Purple Mountains Majesty',
'#f9c5bd': 'Misty Mountain Pink',
'#7c677f': 'Factory Stone Purple',
'#478559': 'Green Treeline',
'#161748': 'Purple baseline'}
# A dictionary comprehension can also be used to swap entries.
>>> swapped = {value: key for key, value in
color_reference.items()}
>>> swapped
{'#8076a3': 'Purple Mountains Majesty',
'#f9c5bd': 'Misty Mountain Pink',
'#7c677f': 'Factory Stone Purple',
'#478559': 'Green Treeline',
'#161748': 'Purple baseline'}
dictに格納された値が一意でない場合は、キーと値を入れ替える前に追加のチェックが必要になります。
# Things become more complicated if there are duplicates in
# potential key values.This dict is arranged by hex, RGB, and HSL
# keys, but values repeat.
>>> extended_colors = {'#8076a3': 'Purple Mountains Majesty',
(128, 118, 163): 'Purple Mountains Majesty',
(21, 28, 0, 36): 'Purple Mountains Majesty',
'#f9c5bd': 'Misty Mountain Pink',
(249, 197, 189): 'Misty Mountain Pink',
(0, 21, 24, 2): 'Misty Mountain Pink',
'#7c677f': 'Factory Stone Purple',
(124, 103, 127): 'Factory Stone Purple',
(2, 19, 0, 50): 'Factory Stone Purple',
'#478559': 'Green Treeline',
(71, 133, 89): 'Green Treeline',
(47, 0, 33, 48): 'Green Treeline'}
# New empty dictionary for holding swapped entries.
>>> consolidated_colors = {}
# Iterating over (key, value) pairs using .items()
>>> for key, value in extended_color_reference.items():
... if value in consolidated_colors: # <--Check if key has already been created.
... consolidated_colors[value].append(key)
... else:
... consolidated_colors[value] = [key] # <--Create a value list with the former key in it.
>>> consolidated_colors
{'Purple Mountains Majesty': ['#8076a3', (128, 118, 163), (21, 28, 0, 36)],
'Misty Mountain Pink': ['#f9c5bd', (249, 197, 189), (0, 21, 24, 2)],
'Factory Stone Purple': ['#7c677f', (124, 103, 127), (2, 19, 0, 50)],
'Green Treeline': ['#478559', (71, 133, 89), (47, 0, 33, 48)]}
辞書とその操作方法について詳しく知りたいなら、公式チュートリアルと公式ライブラリリファレンスが絶好の出発点です。
Real PythonとFinxterにも、Pythonの辞書に関する非常に詳しい記事があります。
ソートについてさらに詳しくは、PythonドキュメントのソートのHOW TOをご覧ください。