抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

为什么有这篇

使用@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
# coding: utf8
def args_demo(*args):
print(type(args))
print(args)

args_demo(1, 2)

运行结果

1
2
<class 'tuple'>
(1, 2)

可以看到args实际传过来后是一个元祖的形式,虽然我传的是1,2,自动组装成了(1, 2)。

翻阅文档知道以tuple形式传值的时候可以加*号。看下加和不加有什么区别。

1
2
3
4
5
6
7
8
9
10
11
12
13
# coding: utf8
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
# coding: utf8
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

结论

  1. args可传字符串,数字,布尔型,列表,元祖和字典等。顺序获取,任何值对他来说都是一个value,不存在key值。
  2. 传值可以依次传递,逗号隔开,也可以放入一个tuple中,传值的时候在tuple前加号。

**kwargs的理解和使用

分析过程

同理,我们来看下kwargs是什么类型。

1
2
3
4
5
6
# coding: utf8
def kwargs_demo(**kwargs):
print(type(kwargs))
print(kwargs)

kwargs_demo(x=1)

运行结果

1
2
<class 'dict'>
{'x': 1}

可以看到args实际传过来后是一个字典的形式,虽然我传的是x=1,但是自动组装成了{“x”: “1”}的形式。

那我如果直接传dict格式呢?查阅文档,kwargs传值跟args类似,可以在前面加**

试验一下

1
2
3
4
5
6
7
8
9
# coding: utf8
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是不可以的。

结论

  1. kwargs可接受参数类型为 dict 和 具体的a=1,b=2这类参数。
  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)

评论