Pythonのデコレータで関数の型チェック

『エキスパートPythonプログラミング』を少しづつ読み進めています。序盤からジェネレータについて自分の知らなかった使い方が載っていたりして読み進めるのが楽しいな。BTSを使ったバグ管理、unittestモジュールとnoseを使ったTDDなど、実際の開発プロセスまで踏み込んだ解説が載っているようです。

エキスパートPythonプログラミング

エキスパートPythonプログラミング

この本を読んでいる途中に思いついた、パラメータ付きデコレータでの関数の型チェックを試してみました。1つの引数をとり1つの引数を返す関数の型チェックをします。

パラメータにタプルを受け付ける事でより高度な型チェックができそうです。高階関数の型チェックなどもできるようになると面白そうですね。

#! /usr/bin/local/python2.6
# coding: utf-8

import functools
def declare1(argtype, rettype):
    def _declare1(function):
        @functools.wraps(function)
        def __declare1(x):
            if not isinstance(x, argtype):
                raise TypeError("argument type is must be instance of '%s'" % argtype)
            r = function(x)
            if not isinstance(r, rettype):
                raise TypeError("return value type is must be instance of '%s'" % rettype)
            return r
        return __declare1
    return _declare1

def main():
    @declare1(int, int)
    def succ(n):
        return n + 1
    @declare1(int, int)
    def invalid_succ(n):
        return n + 1.0
    for i,f in enumerate(["succ(1)", "succ(2.0)", "invalid_succ(1)"]):
        try:
            eval(f)
        except Exception, e:
            print i,"error:",e
        else:
            print i,"no error"        

if __name__ == '__main__':
    main()

実行結果

0 no error
1 error: argument type is must be instance of '<type 'int'>'
2 error: return value type is must be instance of '<type 'int'>'