Pythonの辞書(dict)は、ハッシュ可能な_キー_を_値_に対応付けるデータ構造で、他のプログラミング言語ではサイズ変更可能なハッシュテーブル、ハッシュマップ、[連想配列][associative-array)として知られています。
辞書は、Pythonで唯一の組み込みマッピング型です。
Keysはハッシュ可能でなければならず、辞書全体で一意でなければなりません。
キーの型にはnumbers、str、tuples(_イミュータブル_な値)などがあります。
lists、dicts、setsのような_ミュータブル_なデータ構造を含めることはできません。
Python 3.7以降、dictのキーの順序は、エントリを挿入した順序になることが保証されています。
valuesはどのようなデータ型やデータ構造でもかまいません。
値は_いくらでも_入れ子にできるので、リストのリストやサブ辞書、その他のカスタムあるいは複合的なデータ構造を含めることもできます。
keyがわかっていれば、辞書はvalueを(平均して)一定の時間で取り出せます(エントリの数には依存しません)。
listやarrayの中から値を探す場合(indexの位置がわからない場合)と比べると、dictはメモリをかなり多く使いますが、取り出しは非常に高速です。
辞書は、要素の集まりが大きく、頻繁にアクセスして更新する必要がある場面で特に役立ちます。
辞書はさまざまな方法で作成できます。
最もわかりやすいのは、dict()コンストラクターを使う方法と、dictの_リテラル_を宣言する方法の2つです。
dict()クラスのコンストラクターdict()(辞書クラスのコンストラクター)は、keyとvalueのペアの任意のイテラブルに対して使うことも、一連の<name>=<value>_引数_に対して使うこともできます。
#Passing a list of key,value tuples.
>>> wombat = dict([('name', 'Wombat'),('speed', 23),('land_animal', True)])
{'name': 'Wombat', 'speed': 23, 'land_animal': True}
#Using key=value arguments.
>>> bear = dict(name="Black Bear", speed=40, land_animal=True)
{'name': 'Black Bear', 'speed': 40, 'land_animal': True}
dictは、波括弧({})でkey : valueのペアを囲む_辞書リテラル_として直接書くこともできます。
>>> whale = {"name": "Blue Whale", "speed": 35, "land_animal": False}
{'name': 'Blue Whale', 'speed': 35, 'land_animal': False}
辞書のエントリには、角括弧([])に入れた_key_を使ってアクセスできます。
keyがdictに存在しない場合は、KeyErrorがスローされます。
>>> bear["speed"]
40
>>> bear["color"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'color'
.get(<key>, <default value>)メソッドを使ってエントリにアクセスすると、KeyErrorを避けられます。
>>> bear.get("color", 'not found')
'not found'
エントリのvalueは、その_key_に代入することで変更できます。
#Assigning the value "Grizzly Bear" to the name key.
>>> bear["name"] = "Grizzly Bear"
{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True}
>>> whale["speed"] = 25
{'name': 'Blue Whale', 'speed': 25, 'land_animal': False}
新しいkey:valueのペアも、同じように_追加_できます。
# Adding a new "color" key with a new "tawney" value.
>>> bear["color"] = 'tawney'
{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True, 'color': 'tawney'}
>>> whale["blowholes"] = 1
{'name': 'Blue Whale', 'speed': 25, 'land_animal': False, 'blowholes': 1}
.pop(<key>)メソッドを使うと、辞書のエントリを削除できます。
.pop()は(key、value)のペアを削除し、valueを返します。
.get()と同様、.pop(<key>)は2番目の引数(dict.pop(<key>, <default value>))を受け付けます。この引数は、keyが見つからない場合に返されます。
これにより、KeyErrorが発生するのを防げます。
#Using .pop() removes both the key and value, returning the value.
>>> bear.pop("name")
'Grizzly Bear'
#The "name" key is now removed from the dictionary.
#Attempting .pop() a second time will throw a KeyError.
>>> bear.pop("name")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'name'
#Using a default argument with .pop() will prevent a KeyError from a missing key.
>>> bear.pop("name", "Unknown")
'Unknown'
for item in dictやwhile itemを使って辞書をループすると、デフォルトでは_keys_だけが繰り返されます。
同じループの中で、_角括弧_を使えば_values_にもアクセスできます。
>>> for key in bear:
>>> print((key, bear[key])) #this forms a tuple of (key, value) and prints it.
('name', 'Black Bear')
('speed', 40)
('land_animal', True)
.items()メソッドを使うこともできます。これは(key、value)のタプルを自動的に返します。
#dict.items() forms (key, value tuples) that can be unpacked and iterated over.
>>> for key, value in whale.items():
>>> print(key, ":", value)
name : Blue Whale
speed : 25
land_animal : False
blowholes : 1
同様に、.keys()メソッドはkeysを、.values()メソッドはvaluesを返します。
この演習では、在庫管理システムを扱います。
在庫はアイテム名ごとに整理し、利用できるアイテムの数を把握しておく必要があります。
在庫へのアイテムの追加も扱う必要があります。与えられた配列の中にアイテムが現れるたびに、在庫内のそのアイテムの数量を1増やします。また、要求されたときに数量を1減らして、在庫からアイテムを削除する処理も扱う必要があります。
最後に、与えられた在庫内のすべてのキーと値のペアを、tuplesのlistとして返す関数を実装する必要があります。
アイテムの入力配列から「在庫」を作成するcreate_inventory(<input list>)関数を実装します。それぞれのアイテム名と対応する数量を組み合わせたdictを返すようにします。
>>> create_inventory(["coal", "wood", "wood", "diamond", "diamond", "diamond"])
{"coal":1, "wood":2, "diamond":3}
渡された在庫にアイテムの配列を追加するadd_items(<inventory dict>, <item list>)関数を実装します。
>>> add_items({"coal":1}, ["wood", "iron", "coal", "wood"])
{"coal":2, "wood":2, "iron":1}
アイテムのlistを受け取るdecrement_items(<inventory dict>, <items list>)関数を実装します。そのアイテムがlistに現れるたびに、アイテムの個数から1を減らします。
>>> decrement_items({"coal":3, "diamond":1, "iron":5}, ["diamond", "coal", "iron", "iron"])
{"coal":2, "diamond":0, "iron":3}
在庫内のアイテムの個数は、0を下回らないようにします。入力のlistにアイテムが現れる回数が、在庫にある個数を超えた場合、そのアイテムの数量は0のままにします。個数が0になったあとは、それ以上減らす要求は無視します。
>>> decrement_items({"coal":2, "wood":1, "diamond":2}, ["coal", "coal", "wood", "wood", "diamond"])
{"coal":0, "wood":0, "diamond":1}
在庫からアイテムとその個数を完全に削除するremove_item(<inventory dict>, <item>)関数を実装します。
>>> remove_item({"coal":2, "wood":1, "diamond":2}, "coal")
{"wood":1, "diamond":2}
在庫にそのアイテムが見つからない場合、関数は元の在庫をそのまま返します。
>>> remove_item({"coal":2, "wood":1, "diamond":2}, "gold")
{"coal":2, "wood":1, "diamond":2}
在庫を受け取り、(item, quantity)タプルの配列を返すlist_inventory(<inventory dict>)関数を実装します。この配列には、_利用可能_なアイテム(数量が0より大きいもの)だけを含めます。
>>> list_inventory({"coal":7, "wood":11, "diamond":2, "iron":7, "silver":0})
[('coal', 7), ('diamond', 2), ('iron', 7), ('wood', 11)]