前言
最近开始开发 QtLib 库,将一些 Qt 的黑科技功能进一步集成到一起。
在这个过程中会遇到某些复杂的函数,当中需要大量的可选参数,而且很多参数是不同模式下才需要的。
由于 Python 没有 C++ 那种对函数重载的功能,如果写多个同名函数,会覆盖掉前面的函数。
因此我只好在参数上做判断进行过滤。
那么怎样才能快速判断传入的参数是否合法,如果全部都要写判断就太浪费时间了。
自己开发一个参数验证库也觉得的很麻烦,总觉得应该有人也遇到和我一样的问题,因此我开始网上搜索现成的库。
系列文章推荐
后来在简书上搜到了非常棒的系列文章,介绍了三个不同的参数验证库。
前面两个库比较小巧,功能相对简陋,但是可用。
第三个的 voluptuous 是非常成熟的库了,在github上有上千颗星,非常推荐。
我看完了三篇文章之后可以看到三个库都有大量的功能是重合的,而 voluptuous 在使用上更胜一筹。
上面的文章有很详细的使用方法介绍,我感觉也非常受用。
voluptuous 使用介绍
其实上面的文章也有很详细的使用说明。
我简单说用代码的形式罗列有用的点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| from voluptuous import Schema schema = Schema({ 'text': str, 'active': bool, 'index': int, })
data = { 'text': 1, 'active': True, 'index': 1, }
data = schema(data)
Traceback (most recent call last): File "c:/Users/Administrator/Desktop/hexo/source/_posts/Python/officail_explore/test.py", line 14, in <module> data = schema(data) File "D:\Program Files\Autodesk\Maya2017\Python\lib\site-packages\voluptuous\schema_builder.py", line 267, in __call__ return self._compiled([], data) File "D:\Program Files\Autodesk\Maya2017\Python\lib\site-packages\voluptuous\schema_builder.py", line 589, in validate_dict return base_validate(path, iteritems(data), out) File "D:\Program Files\Autodesk\Maya2017\Python\lib\site-packages\voluptuous\schema_builder.py", line 427, in validate_mapping raise er.MultipleInvalid(errors) voluptuous.error.MultipleInvalid: expected str for dictionary value @ data['text']
|
通过定义数据类型,可以将传参进行判断。
参数传递不正确就会报错提醒
1 2 3 4 5 6 7 8 9
| from voluptuous import Required, All, Length, Range schema = Schema({ Required('q'): All(str, Length(min=1)), Required('per_page', default=5): All(int, Range(min=1, max=20)), 'page': All(int, Range(min=0)), })
|
更多用法还是参考上面的文章介绍。
singledispatch 原生库
后来再研究 dayu_widget UI库 的时候发现里面使用了 singledispatch 库
查了一下原来 singledispatch 在 Python3 的官方包 functools 里面引入了。
可以通过这个库来实现类似上面说的C++函数重载的效果,也就是传入不同的参数函数调用不同。
由于是 python3 才有的新特性,如果要在 Python2 中使用需要使用第三方做好的兼容库来实现。 pypi地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| from singledispatch import singledispatch @singledispatch def fun(arg, verbose=False): if verbose: print("generic usage") print(arg)
@fun.register(int) def _(arg, verbose=False): if verbose: print("int usage") print(arg)
@fun.register(list) def _(arg, verbose=False): if verbose: print("list usage") for i, elem in enumerate(arg): print(i, elem)
fun("1",True) fun(1,True) fun([1],True)
|
也可以将已有的函数注册为特定函数的重载函数。
1 2 3 4
| def nothing(arg, verbose=False): print("Nothing.") fun.register(type(None), nothing) fun(None,True)
|
也可以通过 dispatch 方法获取特定调用的函数
1 2 3 4
| fun.dispatch(list)
fun.dispatch(int)("5",True)
|
总结
上面就是我最近接触到用来简化参数调用的方法。
singledispatch 可以很方便将函数拆解成不同类型调用,把一个复杂函数的功能分割出来。
voluptuous 则是用于快速验证传入参数是否是预想的类型。
两者结合对于复杂程序开发非常方便。
有时间的话要研究一下 singledispatch 这种黑科技是怎么在 Python2 中实现的。