CTC 教育サービス
[IT研修]注目キーワード Python Power Platform 最新技術動向 生成AI Docker Kubernetes
こんにちは、菱沼です。
今回も「きれいなPythonプログラミング(マイナビ出版)」という書籍を利用して学習します。
前回は、スライス構文について学びつつ、リストをコピーする方法について確認しました。
今回は、Pythonの辞書を安全に使うときに便利なメソッド(get、setdefault)と、辞書クラス(defaultdict)ついて学びます。
Pythonの辞書は変数名 = { "キー名" : 値 , "キー名" : 値}という書式で作成することができます。
値(value)はキー(key)と紐づけて保管されており、呼び出したいときはキー名を指定します。もし該当のキーがない場合にはKeyErrorというエラーが発生するようになっています。
データがたくさんあるときには取り出したい値を見つけやすいので便利な機能です。
今回はその辞書を、Pythonicを意識して、エラーを発生させずに、安全に使いたい時に便利なメソッド2つを学びます。
まずはget()メソッドを使い、KeyErrorを発生させずに辞書の中にキーがあれば値を取得し、なければデフォルト値を返します。書籍ではPythonicになっているか、なっていないかで書き方が比較されています。
では引用です。
------------------------------------
P.103
存在しない辞書のキーにアクセスしようとするとKeyErrorというエラーが発生するため、それを回避しようとして、次のようなコードを書くことがあります。
# パイソニックでないコードの例
numberOfPets= {’dogs’: 2}
if ’cats’ in numberOfPets:
print(’I have’, numberOfPets[’cats’], ’cats.’)
else:
print(’I have 0 cats.’)
I have 0 cats.
(中略)
# パイソニックなコードの例
numberOfPets= {’dogs’: 2}
print(’I have’, numberOfPets.get(’cats’, 0), ’cats.’)
I have 0 cats.
------------------------------------
numberOfPets という辞書の中のキーに、catsが設定されているものがあるかを判定するようなプログラムになっています。上下、どちらのプログラムも同じ結果を出すものではありますが、文字数や見やすさが全然違いますね。
違いを見ていくと、Pythonicでないものはif文を利用し、Pythonicとされるものはget()メソッドが利用されています。
get()メソッドを使えば、キーが存在しなかった場合でも、例外(KeyError)を発生させずに、二つ目の引数に設定したデフォルト値を返すようにできます。デフォルト値を設定しなかった場合はNoneが返されます。
このプログラムではcatsというキーがなかった場合のデフォルト値には0が指定されていますので、「I have 0 cats.」という答えが返されます。もしcatsに1という値が設定されていた状態で辞書に入っていたのなら、「I have 1 cats.」という答えが返されます。
このプログラムは「キーの有無を確認する」というのではなく、「キーがあれば値を取得する、なければ0を返す」ことが目的だったため、get()を使ったほうがより簡潔でわかりやすくなります。
if文を使って何かするとすれば、キーの有無によって処理を分岐させたいというようなときになります。
では次にsetdefault()メソッドについて学びます。
get()メソッドでは、キーがない場合にはデフォルト値を返すだけでしたが、setdefault()メソッドはキーがない時にはデフォルト値を返すだけでなく、辞書にキーとデフォルト値を追加することができます。キーがある場合には何も変更は行いません。
では引用文です。
------------------------------------
P.103
# パイソニックでないコードの例
numberOfPets = {’dog’: 2}
if ’cats’ not in numberOfPets:
numberOfPets[’cats’] = 0
numberOfPets[’cats’] += 10
numberOfPets[’cats’]
10
# パイソニックなコードの例
numberOfPets = {’dog’: 2}
numberOfPets.setdefault(’cats’, 0)
0
numberOfPets[’cats’] += 10
numberOfPets[’cats’]
10
------------------------------------
Pythonicでない例ではcatsが辞書にあるかどうかを判定した後、無いのならcatsを辞書に加え、値には0を入れます。その後、catsの値に10を加算するというものになっています。
一方、Pythonicなコードの例では、setdefault()メソッドを使うことで、キーの存在確認と、存在しない場合の初期化({’cats’: 0}の追加)を1行で行っています。その後、catsの値に10を加算しています。
catsが辞書に加わったタイミングはこちら。setdefaultが実行されたタイミングで'cats': 0が追加されているのがわかります。

標準ライブラリのcollectionsモジュールの中に、defaultdictというクラスがあり、これを使うとキーが存在しないときに、自動で初期値を辞書に追加してくれるのだそうです。
collectionsモジュールに含まれるdefaultdictクラスを使うので、使いたいときにはimportをする必要があります。
1)import collections
2)from collections import defaultdict
ではここで引用です。
------------------------------------
P.104
collections.defaultdictクラスを使用すると、KeyErrorを完全になくすことができます。
(中略)collections.default()を呼び出し、デフォルト値に使用するデータ型を渡すことで、デフォルトの辞書を作成します。例えばcollections.defaultdict()にintを渡せば、キーが存在しない場合のデフォルト値に0を使う辞書のようなオブジェクトを作ることができます。
------------------------------------
defaultdict自体の書式はこうなります。
辞書名 = collections.defaultdict(初期値を生成する関数, 初期データ)
本文中に書かれているintを書くのは引数のところです。
この引数に入れられるのはint(0)/str(空文字)/list([])/dict({})/set(set())などがあるとのこと。
ではここで書籍のサンプルコードを見てみます。
------------------------------------
P.104
import collections
scores = collections.defaultdict(int)
scores
defaultdict(<class ’int’>, {})
scores[’Al’] += 1
scores
defaultdict(<class ’int’>, {’Al’: 1})
scores[’Zophie’]
0
scores[’Zophie’] += 40
scores
defaultdict(<class ’int’>, {’Al’: 1, ’Zophie’: 40})
int()関数を呼び出しているのではなく引数として渡しているので、collections.defaultdict(int)ではintの後の小かっこを省略しています。
------------------------------------
さきにcollections.defaultdict()でデフォルト値を設定した後に、辞書に対してキーを指定して加算などの処理を行っています。このプログラムでは最初、辞書の中身はありませんでしたが、AlやZophieというキーに対する加算処理が実行された結果、scoreに2つのキーと値が追加されて行っています。
例えばAlに対して20を加算するという処理を行うと、単純にAlの値は21になります。
scores[’Al’] +=20
scores
defaultdict(<class ’int’>, {’A1’: 21, ’Zophie’: 40})
なので、defaultdictを使っておくと、キーが存在しない場合は初期値が自動的に生成され、その後に加算処理が行われ、キーがあったときにはすでに入っている値に対しての加算処理等が行われるというのがわかりました。
ではここで、さきほどのお犬様、お猫様の辞書のサンプルコードを、defaultdictを使ったものに変えてみます。同じもので比較しないとわかりにくい質なんです...。

catsをprintしようとしたタイミングで辞書にcatsが追加されたことがわかりますね。
追加するという処理についてはsetdefaultと被るところがあります。setdefaultの時はこう書かれていました。ちょっと比較...。
numberOfPets = {’dog’: 2}
numberOfPets.setdefault(’cats’, 0)
0
numberOfPets[’cats’] += 10
numberOfPets[’cats’]
10
setdefaultよりdefaultdictのほうが楽かも...。
では次に、listをデフォルト値として指定した場合のサンプルコードです。------------------------------------
P.104、105
またlistを渡すと空のリストをデフォルト値として使用することができます。
import collections
booksReadBy = collections.defaultdict(list)
booksReadBy[’Al’].append(’Oryx and Crake’)
booksReadBy[’Al’].append(’American Gods’)
len(booksReadBy[’Al’])
2
len(booksReadBy[’Zophie’])
0
考えられるすべてのキーに対してデフォルト値が必要な場合は、通常の辞書を使用して逐一setdefault()メソッドを呼び出すよりもcollections.defaultdict()を使用するほうがはるかに簡単です。
------------------------------------
listをデフォルト値に設定する場合は、listの中身は空っぽの状態でキーごとに空のリストが自動的に生成される仕組みになるようです。
それではきりが良いのでこちらで終了です。
今回もお付き合いいただきありがとうございました。
[IT研修]注目キーワード Python Power Platform 最新技術動向 生成AI Docker Kubernetes