3
3

More than 3 years have passed since last update.

Pythonらしいコードを書く(辞書編)

Posted at

はじめに

Pythonを学習するにあたって、せっかくなので、Pythonらしい書き方というものを調べてみました。
Pythonらしさは、Pythonの効率の良いコードと同意だからです。

参考にしたスライド
https://speakerdeck.com/pyconslides/transforming-code-into-beautiful-idiomatic-python-by-raymond-hettinger-1
http://kesin.hatenablog.com/entry/2013/05/12/004541

辞書の使い方

これぞPythonらしさというもので、辞書の使い方は非常に重要かつ基本的なテクニックです。
何かとお世話になる辞書には、うまいやり方がありそうです。

キーでループ

辞書を指定しても、辞書オブジェクトのkeysメソッドを使っても、キーでのループが可能です。

d = {'kaijo': 'red', 'shinmei': 'blue', 'ooiwa': 'yellow', 'pegie': 'pink', 'asuka': 'green'}
for k in d:
    print(k)

for k in d.keys():
    print(k)

キー、バリューのループ

キーと値とをループさせる方法としては、上段のキーによるループをして、キーから値を取得する方法が考えられます。
Pythonの辞書にはitemsメソッドがあり、これを利用することで、辞書からキーを用いて値を取得することが必要なくなります。また、値の変数が自由に決められるため、読みやすいコードになります。

d = {'kaijo': 'red', 'shinmei': 'blue', 'ooiwa': 'yellow', 'pegie': 'pink', 'asuka': 'green'}
for k in d:
    print(k, '->', d[k])

for k, v in d.items():
    print(k, '->', v)

辞書を2つのリストから作成する

キーのリストと値のリストが既にあるような場合では、これらを合成することで辞書を作成することができます。
for文を使わずにできます。

from itertools import izip

keys = ['kaijo', 'shinmei', 'ooiwa', 'pegie', 'asuka']
values = ['red', 'blue', 'yellow', 'pink', 'green']

d = dict(izip(keys, values))

インデックス的な連番をつけた辞書にしたい場合はenumerateを使うと作成できます。

values = ['red', 'blue', 'yellow', 'pink', 'green']

d = dict(enumerate(values))

辞書を使ったカウント

英語の文章に同じ単語がいくつ出現するか、などの処理をするときには、以下のような処理が想像しやすいです。

colors = ['red', 'green', 'red', 'blue', 'green', 'red']

d = {}
for color in colors:
    if not color in d:
        d[color] = 0
    d[color] += 1

辞書のgetメソッドは指定したキーがいくつあるかを返しますが、キーがない場合は、引数で与えた値を返します。
それを利用して以下のように書けます。

colors = ['red', 'green', 'red', 'blue', 'green', 'red']

d = {}
for color in colors:
    d[color] = d.get(color, 0) + 1

collectionsモジュールのdefaultdictは、キーがない場合に追加する機能を持っています。
それを利用して以下のようにも書けます。
getを使うより読みやすくなります。

from collections import defaultdict

colors = ['red', 'green', 'red', 'blue', 'green', 'red']

d = defaultdict(int)
for color in colors:
    d[color] += 1

辞書を使ったグルーピング

例えば単語のリストがあったとして、単語の文字数でグルーピングしたいといったような場合には、わかりやすいコードとして、キーがないときにデフォルト値(この場合は名前を格納するリスト)を設定する方法があります。
デフォルト値を格納するところはsetdefaultメソッドが使えます。

names = ['raymond', 'rachel', 'matthew', 'ronger', 'betty', 'melissa', 'judith', 'charlie']

d = {}
for name in names:
    key = len(name)
    if not key in d:
        d[key] = []
    d[key].append(name)

d2 = {}
for name in names:
    key = len(name)
    d2.setdefault(key, []).append(name)

これを先程のdefaultdictを使うと以下のように書けます。
if文がなくなってエレガントになりました。

from collections import defaultdict

names = ['raymond', 'rachel', 'matthew', 'ronger', 'betty', 'melissa', 'judith', 'charlie']

d = defaultdict(list)
for name in names:
    key = len(name)
    d[key].append(name)
3
3
2

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
3
3