在Python 3中,一切皆是对象,函数也不例外。因此可以让一个变量指向函数,下面以内置的绝对值函数abs()为例做简单介绍。
一般情况下,下面所示这种调用方式是广为熟悉的:
如前所述,函数本身也是一种对象,因此可以将函数赋值给一个变量,然后通过变量来调用对应函数,效果与直接调用函数相同,如图2-24所示。
图2-24 函数对象
在了解函数是对象后,就容易理解map()与reduce()函数了。这两个函数是Python 3的内置函数。map()函数接受两个参数:第一个是函数对象,第二个是可迭代对象,比如列表。map()函数依次把第一个参数指定的函数应用到第二个参数指定的可迭代对象的每个元素上,并把结果作为迭代器类型返回,具体示例代码如图2-25所示。
图2-25 map()函数
在图2-25所示代码中,首先定义了函数f(),作用是求传入参数的平方。然后把f()作为对象,将其与一个从1到6的列表传入map()函数,最后使用list()函数列出所有返回值对象。可以看出,这段代码把求解平方的函数f()作用到列表中的所有元素上。
reduce()函数会首先使用传入的函数对序列中的第一个元素进行计算,然后对结果序列的下一个元素做累积计算,重复直到序列中的每个元素都完成计算。可以使用如下方式表示,能够更直观地展现效果:
在图2-26中,使用一段程序对列表的数求和,实现方式使用了reduce()函数。
图2-26 reduce()函数
在Python 3中,函数是支持嵌套的,即在函数定义中嵌套另一个函数的定义。当一段代码中存在函数嵌套,一个内层函数对外层函数作用域(非全局作用域)的变量进行引用,那么内层函数就被称为闭包。闭包需要满足如下三个条件。
(1)存在于嵌套关系的函数中。
(2)嵌套的内层函数引用了外层函数的变量。
(3)嵌套的外层函数将内层函数名作为返回值。
因为闭包的概念比较复杂,为了方便理解,通过如下示例代码进行介绍:
上述代码按照后面所标序号进行运行。第1~3步调用outMultiply()函数(第1步),把3作为参数n传递给外层函数outMultiply()(第2步),同时返回内层函数对象给time3(第3步);第4~6步调用time3对应的内层函数对象(第4步),把9作为参数x传递给内层函数inMultiply()(第5步),计算3与9相乘的结果并返回给print()函数输出(第6步)。最终,输出结果为27。
按照变量的生命周期看,外层函数 outMultiply()执行完毕,参数 n 应该被销毁。但后续对内层函数 inMultiply()调用的时候,程序仍能给出正确结果。究其原因是,time3是闭包,包含内层函数的对象,依然记得外层函数的作用域,所以还可以正常运行。