Pythonの辞書 初心者向けガイド


## dict(辞書)の使い方
Pythonの辞書はキーを渡して値を取り出す。
しかし、指定するキーに対応するエントリが辞書に入っていないとエラーになってしまう点が要注意である。

```python:keyerror.py
# -*- coding:utf-8 -*-
import traceback
dct = {"ham": 100, "jam": 300}  # eggがない。

try:
    # eggはないからKeyErrorになってしまう。
    egg = dct["egg"]
except KeyError:
    traceback.print_exc()
```

指定するキーが辞書に存在することが保証されない場合は、dict.getで探せばエラーにならない。代替値も指定できる。

```python:dictget.py
# -*- coding:utf-8 -*-
dct = {"ham": 100, "jam": 300}
print("dict.get => %s" % dct.get("egg", "orz"))
```

辞書に入っているときは入っている値を取り出すが、入っていない場合に任意の値を辞書に入れたいときはdict.setdefaultを使う。

```python:dictsetdefault.py
# -*- coding:utf-8 -*-
dct = {"ham": 100, "jam": 300}

# キーに対応するエントリがない場合に代入したいときはsetdefault
egg = dct.setdefault("egg", "knuckle")
print("dict.get => %s, egg=%s" % (dct["egg"], egg))

# 既にeggが存在するので上書きされない。
egg = dct.setdefault("egg", "mens")
print("dict.get => %s, egg=%s" % (dct["egg"], egg))
```

## ちょっと凝った構造の辞書を作るときはdefaultdict
複雑な構造の辞書を作るときはdefaultdictが有用。
コンストラクタにはキーに対応するエントリがなかった場合の代替値を作るファクトリを渡す。以下の例ではキーごとにlistで値を保持する辞書を作る。

```python:defaultdictusage.py
# -*- coding:utf-8 -*-
from collections import defaultdict

alt = defaultdict(list)
keys = tuple("imagawa")
values = (1, 1, 2, 2, 3, 4, 5)

for k, v in zip(keys, values):
    alt[k].append(v)
print(alt)
```

## collectionsついでにnamedtupleも紹介
defaultdictはcollectionsモジュールに入っているが、collectionsモジュールには他にnamedtupleというものがある。
これを使うとtupleなのだが属性アクセスもできるオブジェクトを定義できる。

```python:namedtupleusage.py
# -*- coding:utf-8 -*-
from collections import namedtuple

Role = namedtuple("Role", "user course")
roles = [Role(x, y) for x, y in ((45, 6), (52, 3))]

for role in roles:
    print("user=%s, course=%s" % (role.user, role.course))
    # 添字アクセスももちろんできる。
    assert role[0] is role.user and role[1] is role.course
```

## サンプルコード
```python:samplecode.py
# -*- coding:utf-8 -*-
import traceback


dct = {"ham": 100, "jam": 300}  # eggがない。

try:
    # eggはないからKeyErrorになってしまう。
    egg = dct["egg"]
except KeyError:
    traceback.print_exc()


# dict.getで探せばエラーにならない。代替値も指定できる。
print("dict.get => %s" % dct.get("egg", "orz"))

# キーに対応するエントリがない場合に代入したいときはsetdefault
egg = dct.setdefault("egg", "knuckle")
print("dict.get => %s, egg=%s" % (dct["egg"], egg))

# 既にeggが存在するので上書きされない。
egg = dct.setdefault("egg", "mens")
print("dict.get => %s, egg=%s" % (dct["egg"], egg))


# 複雑な構造の辞書を作るときはdefaultdictが有用。
from collections import defaultdict
alt = defaultdict(list)
keys = tuple("imagawa")
values = (1, 1, 2, 2, 3, 4, 5)
for k, v in zip(keys, values):
    alt[k].append(v)
print(alt)


# 名前付きタプル namedtuple.
from collections import namedtuple
Role = namedtuple("Role", "user course")
roles = [Role(x, y) for x, y in ((45, 6), (52, 3))]
for role in roles:
    print("user=%s, course=%s" % (role.user, role.course))
    # 添字アクセスももちろんできる。
    assert role[0] is role.user and role[1] is role.course
```

### 実行結果
```text:result.txt
Traceback (most recent call last):
  File "samplecode.py", line 9, in <module>
    egg = dct["egg"]
KeyError: 'egg'
dict.get => orz
dict.get => knuckle, egg=knuckle
dict.get => knuckle, egg=knuckle
defaultdict(<type 'list'>, {'i': [1], 'a': [2, 3, 5], 'm': [1], 'w': [4], 'g': [2]})
user=45, course=6
user=52, course=3
```