Python 3.4.0 の新機能 (3) - Single-dispatch generic functions

  • 17
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

今日は Single-dispatch generic functions (PEP-443)。Generic functionは汎用関数と訳されることも多いが、言語によって微妙に違う使われ方をしている。Pythonでは「引数の型によって動作が異なる複数の関数に同じ名前をつける」という意味合いで使われているようだ。

と書いてもさっぱりわからないので、例示。引数の型によって出力が異なる関数を考える。Generic functionsを使わないとこんな感じ。

def print_func(arg):
    arg_type = type(arg)
    if arg_type is int:
        print("found integer:", arg)
    elif arg_type is list:
        print("found list:", arg)
    else:
        print("found something:", arg)

print_func(1)
print_func(['a','b','c'])
print_func(1.23)

入力された引数の型をif文で一つずつチェックしながら処理する。
実行結果はこう。

found integer: 1
found list: ['a', 'b', 'c']
found something: 1.23

これを、Single-dispatch generic functionsで書くとこうなる。

from functools import singledispatch

@singledispatch
def print_func(arg):
    print("found something:", arg)

@print_func.register(int)
def _(arg):
    print("found integer:", arg)

@print_func.register(list)
def _(arg):
    print("found list:", arg)

print_func(1)
print_func(['a','b','c'])
print_func(1.23)

ベースになる関数をsingledispatch decoratorで修飾し、それに型ごとの処理をregisterメソッドを使って追加していく感じ。どちらが良いのかは微妙だが、型ごとの処理がもっと長くなる場合は一つのif文に入れるよりもこちらの方がすっきりするかも。

結果は上と一緒なので省略。

にしてもあまり使い道が思いつかない。ある値を見てDispatchするのはよくやっていて、例えばHeaderの値からその後に続くデータの形式がわかるのでそういうデータ群のparsingとか。そういう場合は、値から関数を引くDictを用意して実現することが多いが、これは型だもんなぁ。