もっと便利な道具

INPUT · スライド

まだ無いキーに初期値を用意する

01 / 07

グループ分けで書いていた形

果物を文字数ごとにまとめたい。空の辞書を用意して for で回すところまでは同じだね。

でも今度は、値がリストになる。だからまだ無いキーのときは、先に空のリストを置いてからでないと append できない。

この if の3行が、毎回ついてまわる定型文だよ。

kudamonos = ["りんご", "もも", "みかん", "かき", "ぶどう"]guruupu = {}for k in kudamonos:    n = len(k)    if n not in guruupu:        guruupu[n] = []    guruupu[n].append(k)print(guruupu)

実行結果

{3: ['りんご', 'みかん', 'ぶどう'], 2: ['もも', 'かき']}

02 / 07

defaultdict なら if が要らない

defaultdict(デフォルトディクト)は、まだ無いキーを触ったときに、勝手に初期値を用意してくれる辞書だよ。

作るときに「初期値は何か」を渡す。defaultdict(list) なら空のリストが用意される。

だから guruupu[3] がまだ無くても、いきなり append できる。if の3行がまるごと消えたね。

from collections import defaultdictkudamonos = ["りんご", "もも", "みかん", "かき", "ぶどう"]guruupu = defaultdict(list)for k in kudamonos:    guruupu[len(k)].append(k)print(dict(guruupu))

実行結果

{3: ['りんご', 'みかん', 'ぶどう'], 2: ['もも', 'かき']}

03 / 07

そのまま表示すると読みにくい

defaultdict をそのまま print すると、初期値の情報まで一緒に出てくる。

中身が同じでも、こう出されると読みにくいよね。だから表示するときは dict(...) に変換するのがおすすめだよ。

もちろん中身はまったく同じ。見せかたを変えているだけだよ。

from collections import defaultdictguruupu = defaultdict(list)guruupu["あか"].append("りんご")print(guruupu)print(dict(guruupu))

実行結果

defaultdict(<class 'list'>, {'あか': ['りんご']})
{'あか': ['りんご']}

04 / 07

defaultdict(int) で数える

初期値に int を渡すと、用意されるのは 0 になる。

つまり kazoe[t] += 1 を、キーがあるか気にせずに書ける。前のレッスンの Counter と同じことが、自分の手で書けるようになったね。

数えるだけなら Counter のほうが短い。でも defaultdict は足す値を自由に決められるので、こちらのほうが融通がきくよ。

from collections import defaultdicttanngos = ["あか", "あお", "あか"]kazoe = defaultdict(int)for t in tanngos:    kazoe[t] += 1print(dict(kazoe))

実行結果

{'あか': 2, 'あお': 1}

05 / 07

触っただけでキーができる

ひとつ気をつけるところがある。読んだだけでキーが増えるんだ。

kazoe["みどり"] と書いた時点で、"みどり" が 0 として辞書に入ってしまう。ふつうの辞書のつもりで中身を確かめると、いつの間にか増えていて驚くよ。

「あるかどうか」を調べたいだけのときは、in を使おう。in なら勝手に増えないよ。

from collections import defaultdictkazoe = defaultdict(int)print(kazoe["みどり"])print(dict(kazoe))print("あお" in kazoe)print(dict(kazoe))

実行結果

0
{'みどり': 0}
False
{'みどり': 0}

06 / 07

Counter と使い分ける

似ているので、目安を置いておこう。

  • 数えるだけ … Counter。1行で終わるし most_common も付いてくる
  • まとめる・足しこむ … defaultdict。リストに入れる、点数を足す、など中身を自由に決められる

迷ったら、やりたいことが「数える」で言い切れるかどうかで選べばいいよ。

from collections import defaultdictkiroku = [("ゆい", 30), ("はると", 20), ("ゆい", 50)]goukei = defaultdict(int)for namae, ten in kiroku:    goukei[namae] += tenprint(dict(goukei))

実行結果

{'ゆい': 80, 'はると': 20}

07 / 07

定型文が消えるということ

Counter も defaultdict も、無くても書ける道具だった。実際このレッスンの最初に、無い場合のコードをちゃんと書いたよね。

それでも覚える価値があるのは、消えるのが毎回まったく同じ、考えなくていい行だからだよ。その行が消えたぶん、本当に考えるべきところが目立つようになる。

名前と、どういうときに出番が来るか。この2つを覚えて帰ってくれれば十分だよ。