今日は 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を用意して実現することが多いが、これは型だもんなぁ。