python 中 * 与 ** 的参数传递
在 python
中,经常可以看到定义函数或调用函数时f(*arg)
和f(**args)
类型的参数,本文主要讲述这两个形式的参数的含义以及应用。
定义函数时参数加上 *
和
**
首先这两个类型的参数都表示不确定具体参数个数,怎么理解这句话呢?通常在定义函数的时候,定义了几个参数,调用是也要传入几个参数(默认参数除外,可传可不传),但是只要在定义函数的时候将参数写成*
或**
的形式,就可以传入多个参数。如下面的例子:
1 | def a(*args): |
从上面的例子可以看到,通过 *
声明的参数在调用是可以传入0~n个参数,且不管传入的参数为何类型,在函数内部都被存放在以形参名为标识符的tuple中,无法进行修改。
同理,通过**
声明的参数也是可以传入多个参数,但是传入的参数类型需要为k1=v1,k2=v2.....
的类型,且参数在函数内部将被存放在以形式名为标识符的dictionary中,这种方法在需要声明多个默认参数的时候特别有用。
1 | def a(**args): |
下面显示了如何通过这两个参数使代码变得简洁(注意 *args
和
**kwargs
可以同时在函数的定义中,但是 *args 必须在 **kwargs
前面)
1 | def sum(*values, **options): |
除此之外,*args
和 **kwargs
也可以和命名参数一起混着用。命名参数首先获得参数值,然后所有的其他参数都传递给
*args
和 **kwargs
.命名参数在列表的最前端.例如:
def table_things(titlestring, *args, **kwargs)
调用函数时参数加上 *
和
**
除了在定义函数时可以加上 *
或**
,
还可以在调用函数时加上*
或**
,
表示将输入的
集合(序列)类型参数拆开,见下面的例子:
1 | def sum(a, b): |
无论是集合、列表、元组还是字典,
在作为参数输入时加上*
,表示将里面的元素拆开,然后一个个传进去,所以上面执行的结果相当于s = sum(1, 2)
,由于字典比较特殊,传入参数时只会拆开
key 然后传入。下面结合上面定义函数时参数加上*
来讲述这个
*
的含义,例子如下: 1
2
3
4
5
6
7
8def sum(*args):
print args[0]
...
1,2) val = (
sum(val)
(1, 2)
sum(*val)
1
上面的sum函数输出传入的第一个参数,由于sum(val)
将整个val元组作为参数传入,相当于sum((1,2))
,所以会输出(1,2);而sum(*val)
则会将val拆开,相当于sum(1,2)
,因此输出为
1
而在调用参数时加上**
,作用也是将传入的参数拆开,只是输入的参数必须为字典,且每个
key
必须要为函数的某个形参,key对应的value为该参数的值。详见下面的例子:
1 | def parrot(voltage, state='a stiff', action='voom'): |
上面的parrot(**d)
相当于parrot(voltage = "four million", state = "bleedin' demised", action = "VOOM")
通过上面的方法,可以先将所有参数用字典封装,再通过
**
传递。
结合定义函数时参数加上**
有以下例子:
1 | def b(**args): |
参考: http://stackoverflow.com/questions/2921847/what-does-the-star-operator-mean-in-python https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists