LoginSignup
20

More than 5 years have passed since last update.

pythonの辞書で,存在しないキーにアクセスされたら任意の値で初期化する

Last updated at Posted at 2014-07-15
import collections
word_count = collections.defaultdict(int)
for word in ["foo", "bar", "foo", "foobar"]:
    word_count[word] += 1
print word_count
# >>> defaultdict(<type 'int'>, {'foobar': 1, 'foo': 2, 'bar': 1})

辞書型にどんなキーが与えられるかわからない場合に,存在しないキーだったらfooで初期化する,という状況はよくあり,collections.defaultdictがそれを満たしてくれます.defaultdict(int)とすると↑のように初めてのアクセスで0に初期化してくれるわけですが,これは結局どういうことかというと

import collections
word_count = {}
for word in ["foo", "bar", "foo", "foobar"]:
    if not word in word_count:
        word_count[word] = int()
    word_count[word] += 1
print word_count

これと同じ処理になるわけです.結局引数なしの関数で何らかの値を返すものであればいいわけですね.だからlambdaを使ってdefaultdict(lambda: [])とかしてやると結構わかりやすい.追記: この空リストを生成する例だと,lambdaを使うまでもなくlist()を渡したほうが読みやすいです.lambdaを使うべきは下のようなもう少し複雑な例.

さっきの例を発展させると,各アルファベットの出現頻度を数えるとかもできます.

import collections
word_count = collections.defaultdict(lambda: [0 for i in range(26)])
for word in ["foo", "bar", "foo", "foobar"]:
    for chara in word:
        word_count[word][ord(chara)-ord("a")] += 1
print word_count
# >defaultdict(<function <lambda> at 0x10e5147d0>, {'foobar': [1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], 'foo': [0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'bar': [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]})

defaultdict()自体もdefaultdictを返すわけで,defaultdict(defaultdict(lambda: {"name": "null", "age": 20}))とかももちろんできます.

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20