首页 > 其他 > 详细

对函数部分或全部参数进行类型检查

时间:2021-06-08 09:58:15      阅读:13      评论:0      收藏:0      [点我收藏+]

对函数部分或全部参数进行类型检查

构建一个装饰器,通过对装饰器中传入类型参数,来对装饰的函数的对应参数进行类型检查。

from inspect import signature
from functools import wraps
?
def typeassert(*tyargs,**tykwargs):
   def decorator(func):
       #获取指定的强制类型参数
       sig=signature(func)
       required_types=sig.bind_partial(*tyargs,**tykwargs).arguments#OrderedDict类型,可以只对前面的参数进行in搜索判定,可以把前面的参数当作key来获取对应的类型
?
       @wraps(func)
       def wrapper(*args,**kwargs):
           #获取函数输入的各参数类型
           input_vals=sig.bind(*args,**kwargs)
?
           #对输入的每个参数,如果出现在设定的类型检查中,则进行类型检查
           for name,value in input_vals.arguments.items():
               if name in required_types:
                   if not isinstance(value,required_types[name]):
                       raise TypeError(
                           ‘Argument {} must be {}‘.format(name, required_types[name])
                          )
           return func(*args,**kwargs)
       return wrapper
   return decorator
?
@typeassert(str,z=int)#第一个位置参数为str,z必须为int
def func(x,y,z):
   return y+z
?
>>>print(func(1,2,3))
TypeError: Argument x must be <class ‘str‘>
   
@typeassert(int,y=str,z=int)#第一个位置参数为int,y为str,z必须为int
def func(x,y,z):
   print(x,y,z)
>>>func1(3,‘s‘,1)
3 s 1
>>>func1(‘hhh‘,‘s‘,1)
TypeError: Argument x must be <class ‘int‘>

另外也可以通过函数注解来实现,之前实现过,代码如下:

def para_check(func):#外函数,传入的参数是待检验函数对象本身
   sig=inspect.signature(func)#获取函数参数签名
   parameters=sig.parameters#获取参数的有序字典
   arg_names=tuple(parameters.keys())#获取参数的名称
   def wrapper(*args,**kwargs):#内函数
       check_list=[]#待检验的参数对
       for i,val in enumerate(args):#检验所有的位置参数
           arg_name=arg_names[i]
           anno=parameters[arg_name].annotation#该参数期待的类型
           check_list.append((arg_name,anno,val))
       for arg_name,val in kwargs.items():#检验所有的关键字参数
           anno=parameters[arg_name].annotation
           check_list.append((arg_name,anno,val))
?
       for check_arg in check_list:#逐个参数检验
           if not isinstance(check_arg[2],check_arg[1]):
               raise TypeError(‘the input %s expect type %s,but got %s‘%(check_arg[0],check_arg[1],type(check_arg[2])))
       return func(*args,**kwargs)
   return wrapper
?
@para_check
def test(x: int, y: int):
   return x + y
>>>print(test(1,2))
3
>>>print(test(1,‘3‘))
TypeError: the input y expect type <class ‘int‘>,but got <class ‘str‘>
?

后者不需要使用传参数的装饰器。但是明显前者更灵活,用前者进行类型检查,那么后面的函数注解就可以做其它事情而非类型检查了。

对函数部分或全部参数进行类型检查

原文:https://www.cnblogs.com/qianfanwaer/p/14860963.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!