python参数类型错误是什么?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
在python中,不知道函数参数类型是一个很正常的事情,特别是在一个大项目里。
我见过有些项目里,每一个函数体的前十几行都在检查参数类型,这实在是太麻烦了。而且一旦参数有改动,这部分也需要改动。
下面我们用装饰器来实现,函数参数的强制类型检查。
首先,这个装饰器,要接受类型参数,和指定函数参数的类型参数。也就是一个列表和一个dict
得到functools import wrapsdef typeassert (* type_args,, * * type_kwargs): ,,,def 装饰(函数): ,,,,,,,@wraps(函数) ,,,,,,,def 包装器(* args,, * * kwargs): ,,,,,,,,,,,return func (* args,, * * kwargs) ,,,,,,,return wrapper ,,, return 装饰
那么,接下来,在装饰器中,我们需要获取函数参数列表,并且要和类型参数表映射。
这要借助Python的一个标准库——inspect 这个库一般用于Python代码调试
得到inspect import signaturefrom functools import wrapsdef typeassert (* type_args,, * * type_kwargs): ,,,def 装饰(函数): ,,,,,,,sig =,签名(函数) ,,,,,,,bound_types =, sig.bind_partial (* type_args,, * * type_kwargs) .arguments ,,,,,,,@wraps(函数) ,,,,,,,def 包装器(* args,, * * kwargs): ,,,,,,,,,,,return func (* args,, * * kwargs) ,,,,,,,return wrapper ,,, return 装饰
上面的代码中,我们使用检查中的签名方法获取了函数的签名对象,然后使用bind_partial方法创建了(* type_args, * * type_kwargs)到func参数的映射(也就是一个字典)。
接下来就简单了,我们只需要再获取(* args, * * kwargs)的类型,使用isintance函数进行比较就好。
得到inspect import signaturefrom functools import wrapsdef typeassert (* type_args,, * * type_kwargs): ,,,def 装饰(函数): ,,,,,,,sig =,签名(函数) ,,,,,,,bound_types =, sig.bind_partial (* type_args,, * * type_kwargs) .arguments ,,,,,,,@wraps(函数) ,,,,,,,def 包装器(* args,, * * kwargs): ,,,,,,,,,,,bound_values =, sig.bind (* args,, * * kwargs) ,,,,,,,,,,,for 名字,,value 拷贝bound_values.arguments.items (): ,,,,,,,,,,,,,,,if name 拷贝bound_types: ,,,,,,,,,,,,,,,,,,,if not isinstance(价值,bound_types[名字]): ,,,,,,,,,,,,,,,,,,,,,,,raise TypeError (& # 39; Argument  {}, must be {} & # 39; .format(名字,,bound_types[名字])) ,,,,,,,,,,,return func (* args,, * * kwargs) ,,,,,,,return wrapper ,,, return 装饰
运行如下代码
@typeassert (int, int) def 添加(x, y): return x + y 打印(添加(“u",, 2))
能看到报错如下
Traceback (most recent call 最后): File 才能“c: \陈\ \用户桌面\ typeassert.py",, line 32岁,拷贝& lt; module> ,,,印刷(添加(“u",, 2)) File 才能“c: \陈\ \用户桌面\ typeassert.py",, line 22日包装拷贝 ,,,& # 39;Argument {}, must be {} & # 39; .format(名字,,bound_types[名字]) TypeError: Argument x  must be & lt; class & # 39; int # 39;在
很贴心的提醒了我们哪一个参数应该是什么类型。你甚至可以自己改动这个装饰器,让它还能告诉你传进去了什么错误参数(特别是写爬虫的时候,参数很难掌握,一旦报错,还得重跑一遍才知道为什么)。
你也可以指定某一个参数的类型,譬如
@typeassert (int,, z=str) def 显示器(x, y, z): ,,,print (x, y, z)
这时你会发现,y的类型就像原生的Python函数一样,什么都行,而x必须是int, z必须是str。