Python 3.0 Hacks

第7回 関数アノテーションでスマートにプラスアルファの実現

この記事を読むのに必要な時間:およそ 3 分

アノテーションでoverloading

今度はアノテーションを使ってoverloading(多重定義)を実現してみましょう。

overloadingとは静的型付け言語では一般的な機能で,名前は同じだけど引数の型が異なる関数を別々に定義しておき,関数を呼び出すときには引数の型を元に,どの関数を使うかを決定するものです。

たとえばJavaのPrintStreamクラスでは println()メソッドをオーバーロードしていて,次のように使うことができます。

public class Test {
    static public void main(String[] args) {
        // System.out は PrintStream型
        System.out.println(3); // println(int) が呼ばれる. => "3"
        System.out.println(2 == 3); // println(boolean) が呼ばれる. => "false"
        System.out.println("foobar"); // println(String) が呼ばれる. => "foobar"
    }
}

もちろんPythonのprint関数(Python 3以前はprint文)も,いろいろな型のオブジェクトをうまく扱っているのですが,自分で渡された型に応じて動作を変える関数を作ろうとすると,自分で型チェックを行い分岐しなければなりませんでした。

from __future__ import print_function

def myprint(obj):
    if isinstance(obj, int):
        myprint_int(obj)
    elif isinstance(obj, str):
        myprint_str(obj)
    elif ...

def myprint_int(obj):
    print("<int>", obj, "</int>", sep="")

def myprint_str(obj):
    print("<str>", obj, "</int>", sep="")

...

このようにisinstance()の列を書いていると,overloadingのある静的片付け言語の方が楽かも……なんて思うこともあります。この手間を省く動的overloadingをGuido氏が実装したものが,PythonのSubversionリポジトリの中にあります

この中のprettyprinter.pyというサンプルで,overloadしている場所はこうなっています。

@overloaded
def pprint(self, obj):
    self.write(repr(obj))

@pprint.register(object, list)
def pprint_list(self, obj):
    if not obj:
        # ...

先ほどのPython 2.6+anntoolsと同じで,デコレータに型を指定しています。これをアノテーションを使うように書き換えてみました。

@overloaded
def pprint(self, obj):
    self.write(repr(obj))

@pprint.register
def pprint_list(self, obj: list):
    if not obj:
        # ...

アノテーションで型指定していない引数は自動でobject型として扱うようにしたので,selfの型指定が不要になりました。こちらの方が引数の順番を変えるのも楽そうです。

おわりに

いくつかのサンプルを挙げてみたのですが,デコレータだけでは記述が面倒だった関数の引数や戻り値に対する情報の紐づけが,アノテーションを使うことでスマートにできるようになるのを実感できたでしょうか?

Python 2.6ではアノテーションが使えないこともあり,アノテーションを使ったツールやフレームワークはまだあまりないのですが,Python 3.xが主流になるころには,いろいろなフレームワークでアノテーションを使ったスマートな機能が実現されていることでしょう。

著者プロフィール

稲田直哉(いなだ なおき)

KLab株式会社 Kラボラトリー所属。

数年前,久しぶりにPerlを使おうと思ったらPerlのコードを全く書けなくなっていた。自分の記憶力のなさに絶望し,Pythonを始める。IPythonを知って,Python無しには生活できなくなる。

2008年,Pythonドキュメント翻訳プロジェクトに参加し,不定期に翻訳中。一緒に翻訳してくれる方募集中。