与可变长度的参数相反,这里的序列解包是指实参,同样也有 * 和 ** 两种形式。
① 调用含有多个位置参数的函数时,可以使用 Python 列表、元组、集合、字典以及其他可迭代对象作为实参,并在实参名称前加一个星号,Python 解释器将会自动进行解包,然后把序列中的值分别传递给多个单变量形参。
def func(a, b, c): # 可以接收多个位置参数的函数
print(a + b + c)
s = [1, 2, 3]
func(*s) # 对列表进行解包
t = (1, 2, 3)
func(*t) # 对元组进行解包
d = {1: 'x', 3: 'y', 5: 'z'}
func(*d) # 对字典进行解包
func(*d.values()) # 对字典的值进行解包
s = {1, 2, 3}
func(*s) # 对集合进行解包
② 如果实参是个字典,可以使用两个星号对其进行解包,会把字典转换成类似于关键参数的形式进行参数传递。对于这种形式的序列解包,要求实参字典中的所有键都必须是函数的形参名称,或者与函数中两个星号的可变长度参数相对应。
def func(a, b, c=9): # 带有位置参数和默认值参数的函数
print(a, b, c)
d = {'a': 1, 'b': 2, 'c': 3} # 要解包的字典
func(*d)
func(*d.values())
func(**d)
def func(a=3, b=4, c=5): # 带有多个默认值参数的函数
print(a, b, c)
d = {'a': 1, 'b': 2, 'c': 3} # 要解包的字典
func(**d) # 对字典元素进行解包
def func(**parameter): # 接收字典形式可变长度参数的函数
for i in parameter.items():
print(i)
print(parameter)
d = {'f': 10, 'm': 20, 'n': 30}
func(**d) # 对字典元素进行解包
③ 如果一个函数需要以多种形式来接收参数,定义时一般把位置参数放在最前面,然后是默认值参数,接下来是一个星号的可变长度参数,最后是两个星号的可变长度参数;调用函数时,一般也按照这个顺序进行参数传递。
调用函数时如果对实参使用一个星号 * 进行序列解包,那么这些解包后的实参将会被当作普通位置参数对待,并且会在关键参数和使用两个星号 ** 进行序列解包的参数之前进行处理。
def func(a, b, c): # 定义函数
print(a, b, c)
func(*(1, 2, 3)) # 调用,序列解包
func(1, *(2, 3)) # 位置参数和序列解包同时使用
func(1, *(2,), 3)
# 一个星号的序列解包相当于位置参数,优先处理,引发异常
# TypeError: func() got multiple values for argument 'a'
# func(a=1, *(2, 3))
# func(b=1, *(2, 3)) # 重复给 b 赋值,引发异常
func(c=1, *(2, 3))
# 序列解包不能在关键参数解包之后
# SyntaxError: iterable argument unpacking follows keyword argument unpacking
# func(**{'a': 1, 'b': 2, 'c': 3}, *(3,))
# 一个星号的序列解包相当于位置参数,优先处理,引发异常
# TypeError: func() got multiple values for argument 'a'
# func(*(3,),**{'a':1,'b':2})
func(*(3,), **{'c': 10, 'b': 20})