以下内容参考自《Python学习手册》
1. 匹配语法表
语法 | 位置 | 解释 |
func(value) | 调用者 | 常规参数:通过位置进行匹配 |
func(name=value) | 调用者 | 关键字参数:通过变量名匹配 |
func(*tuple) | 调用者 | 以name(一个元组)传递所有的对象,并作为独立的基于位置的参数(解包参数) |
func(**dict) | 调用者 | 以name(一个字典)传递所有的键值对,并作为独立的关键字参数(解包参数) |
def func(name) | 函数 | 常规参数:通过位置或变量名进行匹配 |
def func(name=value) | 函数 | 默认参数值,如果没有在调用中传递的话 |
def func(*name) | 函数 | 匹配并收集(在元组中)所有包含位置的参数 |
def func(**name) | 函数 | 匹配并收集(在字典中)所有包含位置的参数 |
def func(*args, name) | 函数 | 参数必须在调用中按照关键字传递 |
def func(*, name=value) | (Python3) |
2. 顺序法则
- 在函数调用中,参数必须以此顺序出现:任何位置参数(value),后面跟着任何关键字参数(name=value)和*tuple形式的组合,后面跟着**dict形式。
- 在函数头部,参数必须以此顺序出现:任何一般参数(name),紧跟着任何默认参数(name=value),如果有的话,后面是*name的形式,最后是**name形式。
3. 参数匹配顺序
- 通过位置分配非关键字参数;
- 通过匹配变量名分配关键字参数;
- 其他额外的非关键字参数分配到*name元组中;
- 其他额外的关键字参数分配到**name字典中;
- 用默认值分配给在头部未得到分配的参数。
e.g.
>>> def func(a, b=2, *args, **kwargs):
... print a
... print b
... print args
... print kwargs
...
>>> func(1, 2, 3, 4, c=5, d=6)
1
2
(3, 4)
{'c': 5, 'd': 6}
>>> func(1, 2, *(3, 4), **dict(c=5, d=6))
1
2
(3, 4)
{'c': 5, 'd': 6}
>>> func(1, *(3, 4), **dict(c=5, d=6))
1
(4,)
{'c': 5, 'd': 6}
>>> func(1, 2, b=2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func() got multiple values for keyword argument 'b'
>>> func(1, 2, c=3, d=4, 5, 6)
File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> func(1, 2, c=3, *(5, 6), **dict(d=4))
File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> func(1, 2, *(5, 6), c=3, **dict(d=4))
File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg
>>> func(1, 2, c=5, *(3, 4), **dict(d=6))
1
2
(3, 4)
{'c': 5, 'd': 6}
>>> func(1, 2, *(3, 4), c=5, **dict(d=6))
1
2
(3, 4)
{'c': 5, 'd': 6}
>>> func(1, 2, **dict(c=5, d=6), *(3, 4))
File "<stdin>", line 1
func(1, 2, **dict(c=5, d=6), *(3, 4))
^
SyntaxError: invalid syntax
4. Python3.0 Keyword-Only参数
keyword-only参数编码为命名的参数,出现在参数列表中的*args之后。所有这些参数都必须在调用中使用关键字语法来传递。
e.g. 在如下的代码中,a可能按照名称或位置传递,b收集任何额外的位置参数,并且c必须只按照关键字传递:
>>> def kwonly(a, *b, c):
... print(a, b, c)
...
>>> kwonly(1, 2, c=3)
1 (2,) 3
>>> kwonly(a=1, c=3)
1 () 3
>>> kwonly(1, 2, 3)
TypeError: kwonly() needs keyword-only argument c
我们也可以在参数列表中使用一个*字符,表示一个函数不会接受一个可变参数列表,而且*后面的所有参数都作为关键字传递。
e.g. 在以下函数中,a可以按照位置或名称传递,但b和c必须按照关键字传递,不允许其他额外的位置传递:
>>> def kwonly(a, *, b, c):
... print(a, b, c)
...
>>> kwonly(1, c=3, b=2)
1 2 3
>>> kwonly(c=3, b=2, a=1)
1 2 3
>>> kwonly(1, 2, 3)
TypeError: kwonly() takes exactly 1 positional argument (3 given)
>>> kwonly(1)
TypeError: kwonly() needs keyword-only argument b
5. 默认参数陷阱
Python会将默认参数保存为对象附加在函数本身。如果默认参数为可变对象的话,该函数的多次调用就必须格外小心,因为一次修改可能会对下一次的调用造成影响。e.g.
>>> def func(x=[]):
... x.append(1)
... print x
...
>>> func()
[1]
>>> func()
[1, 1]
>>> func()
[1, 1, 1]