Python 中的 '*args' 和 '**kwargs'

在看别人的 python 代码时,会发现一些函数的入参是 *args**kwargs ,那么这两个是用来干嘛的呢,接下来进行测试和研究一下它们的用法

类型

首先看一下它们是什么类型,这样好方便之后研究怎么用

1
2
3
4
5
def func(*args,**kwargs):
print('args:',type(args))
print('kwargs:',type(kwargs))

func()
1
2
args: <class 'tuple'>
kwargs: <class 'dict'>

可以发现 *args 是元组 ( tuple )类型,而 **kwargs 是字典 ( dict ) 类型

传参

那么怎么进行传参呢,可以再进行测试一下

1
2
3
4
5
6
7
def func(*args,**kwargs):
print('args:',type(args))
print('-->',args)
print('kwargs:',type(kwargs))
print('-->',kwargs)

func(1,2)
1
2
3
4
args: <class 'tuple'>
--> (1, 2)
kwargs: <class 'dict'>
--> {}

可以发现,明明函数是要求两个入参,但是输入了两个入参后都被传去 *args 里了,那么怎么把值传到 **kwargs 里呢,可以再来测试一下

1
2
3
4
5
6
7
def func(*args,**kwargs):
print('args:',type(args))
print('-->',args)
print('kwargs:',type(kwargs))
print('-->',kwargs)

func({'a': 1, 'b' : 2})
1
2
3
4
args: <class 'tuple'>
--> ({'a': 1, 'b': 2},)
kwargs: <class 'dict'>
--> {}

可以发现即便是直接放一个字典类型进去,他还是会放到 *args 中,所以现在可以简单的先下个结论, *args 是用来接收入参并放到元组中,但是问题是还是不知道 **kwargs 是干什么用的,所以再改下代码来测试一下

1
2
3
4
def func(**kwargs):
print('kwargs:',kwargs)

func({'a': 1, 'b' : 2})
1
2
3
4
5
6
7
8
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_14972/513502206.py in <module>
2 print('kwargs:',kwargs)
3
----> 4 func({'a': 1, 'b' : 2})

TypeError: func() takes 0 positional arguments but 1 was given

可以发现报错了,而且报错信息的大意是需要 0 个参数,但现在有 1 个(我英语不太好,翻译可能不准确),可是入参明明是规定了个 **kwargs 并且这个 **kwargs 是个字典,而我传参也是个字典啊,换种方式再试试

1
2
3
4
def func(**kwargs):
print('kwargs:',kwargs)

func(1,2)
1
2
3
4
5
6
7
8
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_14972/3682828006.py in <module>
2 print('kwargs:',kwargs)
3
----> 4 func(1,2)

TypeError: func() takes 0 positional arguments but 2 were given

同样的错误,我们想想还有没有其他传参方式,好像是有的,那么再来试试

1
2
3
4
def func(**kwargs):
print('kwargs:',kwargs)

func(a = 1,b = 2)
1
kwargs: {'a': 1, 'b': 2}

可以发现,这次成功了,也就是说它会把入参当变成字典

使用

知道了这些,那么就来使用一下

1
2
3
4
5
6
7
8
def func(a,b,*args):
total = a + b
for i in args:
total += i
return total

val = func(1, 2, 3, 4)
print(val)
1
10

这样就可以做到参数可变了,或者是这样

1
2
3
4
5
def func(a,b):
print(a + b)

kwargs = {'a':1,'b':2}
func(**kwargs)
1
3