函数部分或全部参数的类型检查构建一个装饰器,通过在装饰器中传递类型参数,对被装饰函数的相应参数进行类型检查。frominspectimportsignaturefromfunctoolsimportwrapsdeftypeassert(*tyargs,**tykwargs):defdecorator(func):#获取指定的强制类型参数sig=signature(func)required_types=sig.bind_partial(*tyargs,**tykwargs).arguments#OrderedDict类型,只能搜索判断前面的参数,可以把前面的参数作为key得到对应的类型@wraps(func)defwrapper(*args,**kwargs):#获取函数输入eachparametertypeinput_vals=sig.bind(*args,**kwargs)#对于每一个输入参数,如果出现在集合类型检查中,则对name,valueininput_vals.arguments.items()进行类型检查:ifnameinrequired_types:如果不是isinstance(value,required_types[name]):raiseTypeError('Argument{}mustbe{}'.format(name,required_types[name]))returnfunc(*args,**kwargs)returnwrapperreturndecorator@typeassert(str,z=int)#第一个位置参数是str,z必须是intdeffunc(x,y,z):returny+z>>>print(func(1,2,3))TypeError:Argumentxmustbe@typeassert(int,y=str,z=int)#第一个位置参数是int,y是str,z必须是intdeffunc(x,y,z):print(x,y,z)>>>func1(3,'s',1)3s1>>>func1('hhh','s',1)TypeError:参数x必须是也可以通过函数注解来实现。它以前已经实施过。代码如下:defpara_check(func):#外部函数,传入的参数是自己要检查的函数对象sig=inspect.signature(func)#获取函数参数签名parameters=sig.parameters#获取有序的dictionaryofparametersarg_names=tuple(parameters.keys())#获取参数的名称defwrapper(*args,**kwargs):#innerfunctioncheck_list=[]#待测试的参数为i,valinenumerate(args):#检查所有位置参数arg_name=arg_names[i]anno=parameters[arg_name].annotation#参数的期望类型check_list.append((arg_name,anno,val))forarg_name,valinkwargs.items():#检查所有关键字参数anno=parameters[arg_name].annotationcheck_list.append((arg_name,anno,val))forcheck_argincheck_list:#一一检查参数ifnotisinstance(check_arg[2],check_arg[1]):raiseTypeError('输入%s期望类型%s,但得到%s'%(check_arg[0],check_arg[1],type(check_arg[2])))returnfunc(*args,**kwargs)returnwrapper@para_checkdeftest(x:int,y:int):returnx+y>>>print(test(1,2))3>>>print(test(1,'3'))TypeError:输入yexpecttype,butgot后者不需要使用传参装饰器,但前者显然更灵活,前者用于类型检查,所以后面的函数注释可以做其他事情而不是非类型检查。