7. *args和**kwargs
7.1. *args
*args
用来将 不定数量 的参数打包成 tuple
给函数体使用。
例一:
1def foo(x, *args):
2 print "x:", x
3 for k in range(len(args)):
4 print "args[{}]:".format(k), args[k]
1>>> foo(1, 100, '200k', 300)
2x: 1
3args[0]: 100
4args[1]: 200k
5args[2]: 300
6
7>>> args = [1,2,'abc']
8>>> foo('A', *args)
9x: A
10args[0]: 1
11args[1]: 2
12args[2]: abc
13
14>>> foo('A', args) ## 注:此时把args当做一个参数,参数类型为列表
15x: A
16args[0]: [1, 2, 'abc']
例二:
1def foo(x, var1, var2, var3):
2 print "x:", x
3 print "var1:", var1
4 print "var2:", var2
5 print "var3:", var3
1>>> args = [1,2,'A'] # list
2>>> foo(1, args)
3TypeError: foo() takes exactly 4 arguments (2 given)
4>>> foo(1, *args)
5x: 1
6var1: 1
7var2: 2
8var3: A
9
10>>> args = (1,2,'A') # tuple
11>>> foo(1, args)
12TypeError: foo() takes exactly 4 arguments (2 given)
13>>> foo(1, *args)
14x: 1
15var1: 1
16var2: 2
17var3: A
7.2. **kwargs
**kwargs
打包 不定数量 的键值对参数成 dict
给函数体使用。
例一:
1def foo(**kwargs):
2 for key, val in kwargs.items():
3 print "{} : {}".format(key, val)
1>>> foo(var1=1, var2='a', var3=[1,2,3])
2var1 : 1
3var3 : [1, 2, 3]
4var2 : a
例二:
1def foo(x, var1=2, var2='a'):
2 print "x:", x
3 print "var1:", var1
4 print "var2:", var2
1>>> dict_input = {"var1": 10, "var2": "A"}
2>>> foo(1, dict_input)
3x: 1
4var1: {'var1': 10, 'var2': 'A'}
5var2: a
6
7>>> foo(1, **dict_input)
8x: 1
9var1: 10
10var2: A
7.3. arg,*args,**kwargs
位置参数、*args、**kwargs三者的顺序必须是(arg,*args,**kwargs)。
1def foo(arg, *args, **kwargs):
2 print "arg:", arg
3 print "args:", args
4 print "kwargs:", kwargs
1>>> foo(1, 2, 3, 4, x=1, y='b')
2arg: 1
3args: (2, 3, 4)
4kwargs: {'y': 'b', 'x': 1}
5
6>>> foo(1, x=1, y='b', 2, 3, 4)
7SyntaxError: non-keyword arg after keyword arg
位置参数、默认参数、**kwargs三者的顺序必须是(位置参数,默认参数,**kwargs)。
1def foo(x, y=1, **kwargs): ## 不能出现 (x=1,y,**kwargs)
2 print "x:", x
3 print "y:", y
4 print "kwargs:", kwargs
1>>> foo(4, var1=1, var2='b')
2x: 4
3y: 1
4kwargs: {'var1': 1, 'var2': 'b'}
7.4. 仅限位置参数
在函数定义中, /
表示在它之前的形参是仅限位置形参(Positional-Only Argument),仅限位置形参没有外部可用的名称。
在调用接受仅限位置形参的函数时,参数只会基于它们的位置被映射到形参。
在 /
之后的参数可以是位置参数,也可以是键值对参数。
1>>> def foo(a, /, b):
2... print(a, b)
3...
4>>> foo(1, 3)
51 3
6>>> foo(1, b=3)
71 3
8>>> foo(a=1, b=3)
9Traceback (most recent call last):
10 File "<stdin>", line 1, in <module>
11TypeError: foo() got some positional-only arguments passed as keyword arguments: 'a'
12
13>>> def foo(a, b):
14... print(a, b)
15...
16>>> foo(1, 2)
171 2
18>>> foo(a=1, b=2)
191 2
7.5. 命名关键字参数
Python3 的命名关键字参数(Keyword-Only Argument),以独立的 *
为标记,强制用户在调用函数的时候必须写出 *
之后的参数名。
1>>> def foo(a, *, b=0, c):
2... print(a, b, c)
3...
4>>> foo(1,2,3)
5Traceback (most recent call last):
6 File "<stdin>", line 1, in <module>
7TypeError: foo() takes 1 positional argument but 3 were given
8>>> foo(1,c=2,b=3)
91 3 2
10>>> foo(1, c=2)
111 0 2
12>>> foo(1, b=2)
13Traceback (most recent call last):
14 File "<stdin>", line 1, in <module>
15TypeError: foo() missing 1 required keyword-only argument: 'c'
7.6. 默认参数与可变类型
默认参数是在函数定义的时候就被计算的,默认参数值存储在函数的 __defaults__
属性中,每次调用函数都是从这个属性中读取默认参数值。
当默认参数值是可变类型的时候,这个默认值可能会因为函数调用而改变。
1>>> def foo(n, l=[]):
2... l.append(n)
3... return l
4...
5>>> foo.__defaults__
6([],)
7>>> foo(1)
8[1]
9>>> foo(2)
10[1, 2]
11>>> foo.__defaults__
12([1, 2],)
为了避免这种预期之外的结果,可以使用 None
作为默认参数值,在函数体中增加一个判断。
1>>> def bar(n, l=None):
2... if l is None: l = []
3... l.append(n)
4... return l
5...
6>>> bar.__defaults__
7(None,)
8>>> bar(1)
9[1]
10>>> bar(2)
11[2]
12>>> bar.__defaults__
13(None,)
7.7. 参考资料
大话Python中*args和**kargs的使用
python函数——形参中的:*args和**kwargs
函数的参数