Python 函数参数解包

Python 函数参数解包***操作符有一个非常棒但有点神秘的功能,那就是用来从序列和字典中“解包”函数参数。

下面来定义一个简单的函数作为例子:

def print_vector(x, y, z):
    print('<%s, %s, %s>' % (x, y, z))

从中可以看到,该函数接受三个参数(xyz)并美观地打印出来。使用这个函数能在程序中漂亮地打印三维向量:

>>> print_vector(0, 1, 0)
<0, 1, 0>

如果用其他数据结构来表示三维向量,那么使用print_vector函数进行打印就会出问题。例如用元组或列表表示三维向量的话,在打印时就必须明确指定每个组件的索引:

>>> tuple_vec = (1, 0, 1)
>>> list_vec = [1, 0, 1]
>>> print_vector(tuple_vec[0],
                 tuple_vec[1],
                 tuple_vec[2])
<1, 0, 1>

使用普通函数调用加上多个参数既笨拙也没有必要。如果能够将向量对象“炸开”成三个组件,一次性将所有内容传递给print_vector函数,那岂不是更好?

(当然,也可以简单地重新定义print_vector,让其只接受一个表示向量对象的参数。但这里只是要举一个简单的例子,所以先忽略这个方法。)

幸好Python中用*操作符进行函数参数解包能更好地处理这种情况:

>>> print_vector(*tuple_vec)
<1, 0, 1>
>>> print_vector(*list_vec)
<1, 0, 1>

在函数调用时,在可迭代对象前面放一个*解包这个参数,将其中的元素作为单独的位置参数传递给被调用的函数。

这种技术适用于任何可迭代对象,包括生成器表达式。在生成器上使用*操作符会消耗生成器中的所有元素,并将它们传递给函数:

>>> genexpr = (x * x for x in range(3))
>>> print_vector(*genexpr)

*操作符用于将元组、列表和生成器等序列解包为位置参数。除此之外,还有用于从字典中解包关键字参数的**操作符。假设用下面这个字典对象表示前面的向量:

>>> dict_vec = {'y': 0, 'z': 1, 'x': 1}

那么可以将该字典传递给print_vector,然后使用**操作符解包:

>>> print_vector(**dict_vec)
<1, 0, 1>

由于字典是无序的,因此解包时会匹配字典键和函数参数:x参数接受字典中与'x'键相关联的值。

Python 3.6开始,字典是有序的,但仅仅是指插入顺序,不是某种“自动排序”。

如果使用单个星号(*)操作符来解包字典,则所有的键将以随机顺序传递给函数:

>>> print_vector(*dict_vec)
<y, x, z>

Python的函数参数解包功能带来了很多灵活性。也就是说,不一定要为程序所需的数据类型实现一个类,使用简单的内置数据结构(如元组或列表)就足够了,这样有助于降低代码的复杂度。

Python 函数参数解包 关键要点

  • ***操作符可用于从序列和字典中“解包”函数参数。

  • 高效使用参数解包有助于为模块和函数编写更灵活的接口。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程