对函数局部或全副参数进行类型查看

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

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'>

后者不须要应用传参数的装璜器。然而显著前者更灵便,用前者进行类型查看,那么前面的函数注解就能够做其它事件而非类型查看了。