Il fut un temps où je voulais définir un type en python, alors j'ai écrit un décorateur de fonction pour le moment Si on me disait d'utiliser cython, je n'aurais pas d'enfants, mais ...
type_definiton.py
from inspect import getargspec, getcallargs
def type_definition(*types):
def type_checker(func):
argspec = getargspec(func)
arg_length = len(argspec.args)
kwargs_index = -1 if argspec.keywords else 0
vargs_index = -1 + kwargs_index if argspec.varargs else 0
arg_type = zip(argspec.args, types[:arg_length])
vargs_type = types[vargs_index] if vargs_index else None
kwargs_type = types[kwargs_index] if kwargs_index else None
def new_func(*args, **kwargs):
argdetail = getcallargs(func, *args, **kwargs)
# check type of args
for name, _type in arg_type:
if name in argdetail:
if not type(argdetail[name]) == _type:
raise ValueError(
"Invalid Type: " + name + " is not " + str(_type)
)
if vargs_type:
for value in argdetail[argspec.varargs]:
if not type(value) == vargs_type:
raise ValueError(
"Invalid Type: " + argspec.varargs \
+ " is not " + str(vargs_type)
)
if kwargs_type:
for value in argdetail[argspec.keywords].values():
if not type(value) == kwargs_type:
raise ValueError(
"Invalid Type: " + argspec.keywords \
+ " is not " + str(kwargs_type)
)
# do func
return func(*args, **kwargs)
return new_func
return type_checker
J'écrirai un exemple d'utilisation
example.py
@type_definition(int, int, str)
def foo(a, b, c=0):
return a + b + int(c)
foo(1, 1)
# -> 2
foo(1, 1, 1)
# ValueError: Invalid Type: c is not <type 'str'>
foo(1, 1, "1")
# -> 3
Recommended Posts