如果一个函数需要以多种形式来接收参数,定义时一般把位置参数放在最前面,然后是默认值参数,接下来是一个星号的可变长度参数,最后是两个星号的可变长度参数;调用函数时,一般也按照这个顺序进行参数传递。调用函数时如果对实参使用一个星号*进行序列解包,那么这些解包后的实参将会被当做普通位置参数对待,并且会在关键参数和使用两个星号**进行序列解包的参数之前进行处理。
# 定义函数
>>> def demo(a, b, c):
print(a, b, c)
# 调用函数,序列解包
>>> demo(*(1, 2, 3))
1 2 3
# 位置参数和序列解包同时使用
>>> demo(1, *(2, 3))
1 2 3
>>> demo(1, *(2,), 3)
1 2 3
# 一个星号的序列解包相当于位置参数,优先处理,重复为a赋值,引发异常
>>> demo(a=1, *(2, 3))
TypeError: demo() got multiple values for argument 'a'
# 重复给b赋值,引发异常
>>> demo(b=1, *(2, 3))
TypeError: demo() got multiple values for argument 'b'
# 一个星号的序列解包相当于位置参数,尽管放在后面,但是仍会优先处理
>>> demo(c=1, *(2, 3))
2 3 1
# 序列解包不能在关键参数解包之后,否则会引发异常
>>> demo(**{'a':1, 'b':2}, *(3,))
SyntaxError: iterable argument unpacking follows keyword argument unpacking
# 一个星号的序列解包相当于位置参数,优先处理,重复为a赋值,引发异常
>>> demo(*(3,), **{'a':1, 'b':2})
TypeError: demo() got multiple values for argument 'a'
>>> demo(*(3,), **{'c':1, 'b':2})
3 2 1