对函数局部或全副参数进行类型查看
构建一个装璜器,通过对装璜器中传入类型参数,来对装璜的函数的对应参数进行类型查看。
from inspect import signaturefrom functools import wrapsdef 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必须为intdef 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必须为intdef 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_checkdef 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'>
后者不须要应用传参数的装璜器。然而显著前者更灵便,用前者进行类型查看,那么前面的函数注解就能够做其它事件而非类型查看了。