Python 包裹传递和解包裹

包裹传递

在定义函数时,我们有时候并不知道调用的时候会传递多少个参数。 这时候,包裹 (packing) 位置参数,或者包裹关键字参数,来进行参数传递,会非常有用。

例子一
>>> def func(*name):
... print(type(name))
... print(name)
...
>>> func(1, 2, 3)
<class 'tuple'>
(1, 2, 3)
>>> func(1, 2, 3, 5, 6, 9)
<class 'tuple'>
(1, 2, 3, 5, 6, 9)

两次调用,尽管参数个数不同,都基于同一个 func 定义。在 func 的参数表中,所有的参数被 name 收集,根据位置合并成一个元组 (tuple) ,这就是包裹位置传递。
name 是包裹位置传递所用的元组名,在定义 func 时,在 name 前加 * 号。

例子二
>>> def func(**x):
... print(type(x))
... print(x)
...
>>> func(a=1, b=2)
<class 'dict'>
{'a': 1, 'b': 2}
>>> func(a=1, b=2, c=3)
<class 'dict'>
{'a': 1, 'b': 2, 'c': 3}

与上面一个例子类似, dict 是一个字典,收集所有的关键字,传递给函数 func 。参数 dict 是包裹关键字传递所用的字典,在 dict 前加 **。

解包裹

* 和 ** ,也可以在调用的时候使用,即解包裹 (unpacking) ,下面为例:

>>> def func(a, b ,c):
... print(a, b, c)
...
>>> args = (1, 2, 3)
>>> func(*args)
1 2 3
>>> kwargs = {'a': 1, 'b': 2, 'c': 3}
>>> func(**kwargs)
1 2 3

总结

包裹传递在定义函数时,元组前加 * 、字典前加 ** 。
包裹和解包裹并不是相反操作,是两个相对独立的过程。