Edited at

辞書型のKeyError対策

More than 3 years have passed since last update.

辞書内に存在しないキーにアクセスしようとするとKeyErrorが生成される.

これに対する対策を以下に述べる.


あらかじめキーが存在することを調べる

>>> pythons = {'Chapman': 'Graham', 'Cleese': 'John',

... Jones': 'Terry', 'Palin': 'Michael'}
>>> 'Marx' in pythons
False


get()関数を使用する

>>> pythons.get('Cleese')

'John'

キーが存在しなければ,指定したオプション値が返される.

>>> pythons.get('Marx', 'Not a Python')

'Not a Python'

キーが存在しない際,オプションを指定していなければNoneが返される.

>>> ret = pythons.get('Marx')

>>> ret is None
True


setdefault()を使用する

キーが辞書になければ,第2引数に指定した値とともに辞書に追加される.

>>> periodic_table = {'Hydrogen', 1, 'Helium': 2}

>>> print(periodic_table)
{'Helium': 2, 'Hydrogen': 1}
>>>
>>> carbon = periodic_table.setdefault('Carbon', 12) # 辞書に'Carbon'はないので追加される
12
>>> periodic_table
{'Helium': 2, 'Carbon': 12, 'Hydrogen': 1}

すでにキーが辞書にある場合は元の値が返され,辞書は一切変更されない.

>>> helium = periodic_table.setdefault('Helium', 947)

>>> helium
>>> periodic_table
{'Helium': 2, 'Carbon': 12, 'Hydrogen': 1}


defaultdict()を使用する

defaultdict()は,辞書作成時にあらかじめデフォルト値を設定する.


defaultdict()の引数には関数を指定する.

from collections import defaultdict

periodic_table = defaultdict(int)

こうすると,存在しないキーにアクセスした場合,int()の値( = 0)が設定される.

>>> periodic_table['Hydrogen'] = 1

>>> periodic_table['Lead']
0
>>> periodic_table
defaultdict(<class 'int'>, {'Lead': 0, 'Hydrogen': 1})

defaultdict()に渡す関数は独自に定義したものでも良い.


この場合は,no_idea()の値が設定されるようになる.

>>> from collections import defaultdict

>>>
>>> def no_idea():
... return 'Huh?'
...
>>> bestiary = defaultdict(no_idea)
>>> bestiary['A'] = 'Abominable Snowman'
>>> bestiary['B'] = 'Basilisk'
>>> bestiary['A']
'Adominable Snowman'
>>> bestiary['B']
'Basilisk'
>>> bestiary['C']
'Huh?'

lambdaを使えば,defaultdict()呼び出しの中でデフォルト作成関数を定義できる.

>>> bestiary = defaultdict(lambda: 'Huh?')

>>> bestiary = ['E']
'Huh?'

なお,今回のコードは以下の文献からお借りした(一部改変).


  • Bill Lubanovic著「入門 Python3」(オライリー・ジャパン発行)

    ISBN 978-4-87311-738-6


追記

コメントでご指摘を頂きました.

例外を捕捉するという方法でも可能です.

try:

result = cache[x]
except KeyError:
result = 'blah blah blah...'
cache[x] = result