为什么有这篇
使用@pytest.mark.parametrize进行批量传值。由于该装饰器单个变量接收的是list,而对于一个具体的接口模板,例如一个查询结构,有页码,分页大小,排序等字段,我想只传部分,不想传全部,我想直接在批量传值的时候进行任意参数组合,调用同一个方法。这个方法内再去做获取参数,依据情况,发送接口。
原代码
1 2 3 4 5 6 7 8 9 10
| def setPageInfo(self, sorts="", currentPage=1, pageSize=10, enableCount="true"): """ 设置分页排序信息 :param sorts: 排序 :param currentPage: 页码 :param pageSize: 每页多少条 :param enableCount: :return: """ self.pageInfo = {"sorts": sorts, "currentPage": currentPage, "pageSize": pageSize, "enableCount": enableCount}
|
当函数的参数不确定时,可以使用args和 **kwargs,args 没有key值,**kwargs 有key值。
*args的理解和使用
分析过程
我们先看一下args的类型是什么,为什么可以接受多个参数。
1 2 3 4 5 6
| def args_demo(*args): print(type(args)) print(args)
args_demo(1, 2)
|
运行结果
可以看到args实际传过来后是一个元祖的形式,虽然我传的是1,2,自动组装成了(1, 2)。
翻阅文档知道以tuple形式传值的时候可以加*号。看下加和不加有什么区别。
1 2 3 4 5 6 7 8 9 10 11 12 13
| def args_demo(*args): print(type(args)) print(args) print("\t") <class 'tuple'> (1, 2, 3)
<class 'tuple'> ((1, 2, 3),)
<class 'tuple'> (1, 2, 3)
|
可以看到,不论怎么传,最终都是tuple, 传值的时候直接传tuple,对args来说这是一个一个整体,当作一个value。 当传 *tuple的时候,会把tuple内的值一一取出,再塞到args中。
再来看一下args实际传值可接收的类型
1 2 3 4 5 6 7 8 9 10 11 12 13
| def args_demo(param1, *args): print("params1 is %s" % param1)
index = 1 for value in args: print( "the "+ str(index) + " is "+ str(value)) index +=1 print('\n')
args_demo("第一个参数个", ["1", "L", "p"], ["2", "3", "4"]) args_demo("第一个参数个", 2, 3, (1, 2), True) args_demo("第一个参数个", {"a": "1", "b": "2"}, "2", 1)
|
运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| params1 is 第一个参数个 the 1 is:['1', 'L', 'p'] the 2 is:['2', '3', '4']
params1 is 第一个参数个 the 1 is:2 the 2 is:3 the 3 is:(1, 2) the 4 is:True
params1 is 第一个参数个 the 1 is:{'a': '1', 'b': '2'} the 2 is:2 the 3 is:1
|
结论
- args可传字符串,数字,布尔型,列表,元祖和字典等。顺序获取,任何值对他来说都是一个value,不存在key值。
- 传值可以依次传递,逗号隔开,也可以放入一个tuple中,传值的时候在tuple前加号。
**kwargs的理解和使用
分析过程
同理,我们来看下kwargs是什么类型。
1 2 3 4 5 6
| def kwargs_demo(**kwargs): print(type(kwargs)) print(kwargs)
kwargs_demo(x=1)
|
运行结果
可以看到args实际传过来后是一个字典的形式,虽然我传的是x=1,但是自动组装成了{“x”: “1”}的形式。
那我如果直接传dict格式呢?查阅文档,kwargs传值跟args类似,可以在前面加**
试验一下
1 2 3 4 5 6 7 8 9
| def kwargs_demo(**kwargs): for key in kwargs: print("key is %s value is %s" % (key, kwargs[key])) print("\n")
kwargs_demo(**{"X": "1", "y": "2"}) kwargs_demo(x=1, y=2) kwargs_demo({"X": "1", "y": "2"})
|
结果
1 2 3 4 5 6 7 8 9
| key is X, value is 1 key is y, value is 2 key is x, value is 1 key is y, value is 2
Traceback (most recent call last): File "D:/Python Project/NewLand/不确定参数/kwargsdemo.py", line 20, in <module> kwargs_demo({"X": "1", "y": "2"}) TypeError: kwargs_demo() takes 0 positional arguments but 1 was given
|
可以看到,通过dict格式传值,传过去的dict变成kwargs,感觉上是一种平行过度,换了个名字,依然还是dict。
而如果使用x=1, y=2这类方式传值,传几个,转换后的dict里就有几个key和value。
而如果不加,直接传dict是不可以的。
结论
- kwargs可接受参数类型为 dict 和 具体的a=1,b=2这类参数。
- kwargs实际是一个字典,方法内部使用的时候可以遍历取值。获取定义好key name,使用get方式尝试获取值,完成想做的操作。
args和kwargs一起使用
先上结论:
- args和kwargs一般使用的时候,如果遇到func还有其他知道参数,一般把args和kwargs放在后面。
- 如果args和kwargs同时在func出现,必须args在前,*kwargs在后。传值遵循的规则和单独使用的时候一样,只需要注意传值的顺序。
附实际使用时的代码:
1 2 3 4 5 6 7 8 9 10
| def kwargs_demo2(args, *kwargs): print(args) for key in kwargs: print("key is %s, value is %s" % (key, kwargs[key])) print("\t")
kwargs_demo2((1), 2, 3, **{"X": "1", "y": "2"}) kwargs_demo2((1, 2), 3, x=1, y=2) kwargs_demo2(*(1, 2, 3), x=1, y=2) kwargs_demo2((1, 2, 3), *{"X": "1", "y": "2"})
|
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| (1, 2, 3) key is X, value is 1 key is y, value is 2
((1, 2), 3) key is x, value is 1 key is y, value is 2
(1, 2, 3) key is x, value is 1 key is y, value is 2
(1, 2, 3) key is X, value is 1 key is y, value is 2
|
最终问题的解决方案
更改后
1 2 3 4 5 6 7 8 9 10 11 12 13
| def setPageInfo(self, **kwargs): """ 设置分页排序信息 :param kwargs: sorts: 排序 currentPage: 页码 pageSize: 每页多少条 :return: """ sorts = kwargs.get("sorts", "") currentpage = kwargs.get("currentpage", "1") pageSize = kwargs.get("pageSize", "10")
|
在批量传参的时时候,如此调用:
1 2 3
| @pytest.mark.parametrize("pageinfo", [{"sorts": "a.billNo-desc-false"}, {"currentPage": "2", "pageSize": "50"},{"sorts": "a.billDate-desc-false", "currentPage": "2", "pageSize": "20"}]) def test_demo1(pageinfo): setPageInfo(*pageinfo)
|