python3の関数アノテーションを試してみました
ネタ的には今更なんですけど、よくわかっていなかったので試してみました。
予め言っておきますと初歩的な内容なので期待しないで下さい。
引数の情報を取得する為に
http://docs.python.org/3.2/library/inspect.html#inspect.getfullargspec
や
http://code.google.com/p/anntools/
を参考にさせて頂きました。
以下のようなtest.pyを用意してみます。
# -*- coding: utf-8 -*- from functools import wraps from inspect import getfullargspec class ArgumentError(Exception): def __init__(self, arg_name, val, typ): super(ArgumentError, self).__init__() print('引数 {} の {} は {} と型が違います'.format(arg_name, val, typ)) class RetValError(Exception): def __init__(self, retval, typ): super(RetValError, self).__init__() print('{} は 戻り値の型が {} ではありません'.format(retval, typ)) def validate(func): @wraps(func) def _validate(*args, **kwargs): argSpec = getfullargspec(func) for name, value in zip(argSpec.args, args): obj_type = func.__annotations__[name] if not isinstance(value, obj_type): raise ArgumentError(name, value, obj_type) result = func(*args, **kwargs) ret_type = func.__annotations__['return'] if not isinstance(result, ret_type): raise RetValError(result, ret_type) print('OK') return result return _validate @validate def hoge(a: int, b: str = '!') -> str: val = str(a) + b return val
実際にどうなるのか試してみます。
>>> from test import hoge >>> hoge(1) OK '1!' >>> hoge('1') 引数 a の 1 は <class 'int'> と型が違います Traceback (most recent call last): File "<stdin>", line 1, in <module> File "test.py", line 26, in _validate raise ArgumentError(name, value, obj_type) test.ArgumentError >>> hoge(1, 'a') OK '1a' >>> hoge(1, 3) 引数 b の 3 は <class 'str'> と型が違います Traceback (most recent call last): File "<stdin>", line 1, in <module> File "test.py", line 26, in _validate raise ArgumentError(name, value, obj_type) test.ArgumentError
実装次第で色々出来そうです。
今のところ僕の中では型判定以外の利用方法があまり浮かばないのですが
今後色々と出てくると思いますし楽しみです。