python 中 * 与 ** 的参数传递
在 python 中,经常可以看到定义函数或调用函数时 f(*arg)
和 f(**args)
类型的参数,本文主要讲述这两个形式的参数的含义以及应用。
定义函数时参数加上 *
和 **
首先这两个类型的参数都表示不确定具体参数个数,怎么理解这句话呢?通常在定义函数的时候,定义了几个参数,调用是也要传入几个参数 (默认参数除外,可传可不传),但是只要在定义函数的时候将参数写成 *
或 **
的形式,就可以传入多个参数。如下面的例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def a(*args):
print type(args)
for i in args:
print i
...
1,2,3,4) a(
<type 'tuple'>
1
2
3
4
3,2,3]) a([
<type 'tuple'>
[3, 2, 3]
a()
<type 'tuple'>
从上面的例子可以看到,通过 *
声明的参数在调用是可以传入 0~n 个参数,且不管传入的参数为何类型,在函数内部都被存放在以形参名为标识符的 tuple 中,无法进行修改。
同理,通过 **
声明的参数也是可以传入多个参数,但是传入的参数类型需要为 k1=v1,k2=v2.....
的类型,且参数在函数内部将被存放在以形式名为标识符的 dictionary 中,这种方法在需要声明多个默认参数的时候特别有用。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def a(**args):
print type(args)
print args
for k, v in args.items():
print k,v
print args['k1']
...
1, k2=2, k3=3, k4=4) a(k1=
<type 'dict'>
{'k3': 3, 'k2': 2, 'k1': 1, 'k4': 4}
k3 3
k2 2
k1 1
k4 4
1
下面显示了如何通过这两个参数使代码变得简洁 (注意 *args
和 **kwargs
可以同时在函数的定义中,但是 *args 必须在 **kwargs 前面)1
2
3
4
5
6
7
8
9
10
11def sum(*values, **options):
s = 0
for i in values:
s = s + i
if "neg" in options and options["neg"]:
s = -s
return s
s = sum(1, 2, 3, 4, 5) # returns 15
s = sum(1, 2, 3, 4, 5, neg=True) # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15
除此之外,*args
和 **kwargs
也可以和命名参数一起混着用。命名参数首先获得参数值,然后所有的其他参数都传递给 *args
和 **kwargs
. 命名参数在列表的最前端。例如:
def table_things(titlestring, *args, **kwargs)
调用函数时参数加上 *
和 **
除了在定义函数时可以加上 *
或 **
, 还可以在调用函数时加上 *
或 **
, 表示将输入的 集合(序列)类型参数拆开,见下面的例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14def sum(a, b):
return a + b
# values = set()
# values.add(1)
# values.add(2)
values = (1, 2)
# values = [1,2]
# values = {1:3, 2:4}
s = sum(*values)
无论是集合、列表、元组还是字典, 在作为参数输入时加上 *
,表示将里面的元素拆开,然后一个个传进去,所以上面执行的结果相当于 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
2
3
4
5
6
7
8def parrot(voltage, state='a stiff', action='voom'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.", end=' ')
print("E's", state, "!")
...
"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"} d = {
parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
上面的 parrot(**d)
相当于 parrot(voltage = "four million", state = "bleedin' demised", action = "VOOM")
通过上面的方法,可以先将所有参数用字典封装,再通过 **
传递。
结合定义函数时参数加上 **
有以下例子:1
2
3
4
5
6
7
8def b(**args):
for k,v in args.items():
print k,v
...
'keke':1, 'hehe':2} val = {
b(**val)
keke 1
hehe 2
参考: http://stackoverflow.com/questions/2921847/what-does-the-star-operator-mean-in-python https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists