作者:Miha_Singh

参数组:*args,**kwargs

在python中实现变长参数可以通过关键字参数以及非关键字参数来实现,使用 ** 指定字典为关键字参数, * 指定元组为非关键字参数。
当参数为*args时,表示接受一个元组;
当参数为**kwargs时,表示接受一个字典

1.非关键字参数:

定义含有非关键字参数的函数:

def func_name([位置参数或默认参数,] *non_keyword_args)

>>> def func1(arg1,arg2,*arg3):
		print('arg1:',arg1)
		print('aeg2:',arg2)
		for arg in arg3:
			print('非关键字参数:',arg)
>>> func1(1,2,3,'a',1,'b')
arg1: 1
aeg2: 2
非关键字参数: 3
非关键字参数: a
非关键字参数: 1
非关键字参数: b

对于位置参数(和默认参数)会按照顺序一一匹配或者按照参数名给出参数值,匹配完位置参数和默认参数后,如果还有额外的参数而且函数声明了非关键字参数,就将这些参数打包成元组,作为非关键字参数。
上图中,arg1匹配1,arg2匹配2,剩下的参数打包成元组传递给arg3。

2.关键字参数

定义含有非关键字参数的函数:

def func_name([位置参数或默认参数,] **keyword_args)

>>> def func2(arg1,arg2,**arg3):
		print('arg1:',arg1)
		print('arg2:',arg2)
		for k in arg3.keys():
			print('关键字参数 [',k,' : ',arg3[k],']')
>>> func2(1,2,k1='v1',k2='v2',k3='v3')
arg1: 1
arg2: 2
关键字参数 [ k1  :  v1 ]
关键字参数 [ k2  :  v2 ]
关键字参数 [ k3  :  v3 ]

当函数中定义了关键字参数,位置参数和默认参数匹配完后,对于剩下的关键字参数就会打包成字典,传递给关键字参数。arg11匹配1,arg2匹配2,剩下的参数打包成字典传递给arg3。

在以上的情况中,如果传入的参数经过位置参数和默认参数匹配完成后,还有函数无法匹配的参数则会出错,比如:

>>> f1(1,2,3,'a'=1)
SyntaxError: keyword can't be an expression

>>> func2(1,2,3,k1='v1',k2='v2',k3='v3')
Traceback (most recent call last):
  File "<pyshell#32>", line 1, in <module>
    func2(1,2,3,k1='v1',k2='v2',k3='v3')
TypeError: func2() takes 2 positional arguments but 3 were given

3.关键字参数和非关键字参数

在声明函数的参数列表的过程中,各种参数声明的顺序:

def func_name(位置参数, 默认参数, 非关键字参数, 关键字参数)

注意:顺序不可改变!
定义函数func:

>>> def func(arg1, arg2, arg3='default', *arg4, **arg5):
	print('arg1:',arg1)
	print('arg2:',arg2)
	print('aeg3:',arg3)
	for arg in arg4:
		print('non-keyword arg:',arg)
	for k in arg5.keys():
		print('keyword arg [',k,':',arg5[k],']')

在给函数传入参数时,可以提前将非关键字参数和关键字参数进行打包,例如:

>>> non_keyword_args = (1,2,3,4)
>>> keyword_args = {'k1':'v1','k2':'v2'}
>>> func(1,2,3,*non_keyword_args,**keyword_args)
arg1: 1
arg2: 2
aeg3: 3
non-keyword arg: 1
non-keyword arg: 2
non-keyword arg: 3
non-keyword arg: 4
keyword arg [ k1 : v1 ]
keyword arg [ k2 : v2 ]

但是,如果出现这样的情况呢:
func(1,2,3,4,5,k3=‘v3’,*non_keyword_args,**keyword_args)

运行试一下:

>>> func(1,2,3,4,5,k3='v3',*non_keyword_args,**keyword_args)
arg1: 1
arg2: 2
aeg3: 3
non-keyword arg: 4
non-keyword arg: 5
non-keyword arg: 1
non-keyword arg: 2
non-keyword arg: 3
non-keyword arg: 4
keyword arg [ k1 : v1 ]
keyword arg [ k2 : v2 ]
keyword arg [ k3 : v3 ]

注意:真正传入函数的关键字和非关键字参数是以我们实际传入的参数为准的,那些另外传入的非关键字和关键字参数会和我们传入的字典和元组进行打包作为最终传入的参数。