在前面讨论闭包概念的时候,我们了解了函数名称可以赋值给其它变量,被赋值的变量称为函数的引用,当该变量被使用时,就会执行变量所引用的函数。
上面的代码定义了add函数,用于求两数的和,需要传入a和b两个参数。然后将add赋值给sum变量,此时sum变量指向了add函数,执行sum变量和执行add函数效果是一样的,调用的都是同一个函数,输出结果都是数字2。
现在需要对add函数进行改动,要求add函数求两数绝对值的和。我们可以在add函数中添加abs函数,先求出a和b的绝对值,然后再求和。
在上面的代码中使用abs函数先求出a和b的绝对值,然后再求和,这样就解决了前面对add函数提出的需求。不过需求是不断变化的,现在新的需求又来了,要求add函数在支持绝对值求和的基础上,对a和b进行预处理,如果传入的是浮点,需要把浮点转换为整型。程序员需要如何应对这种不断变化的需求呢?唯一的办法是在编写程序时提高程序的灵活性和可扩展性,当需求发生变化时,尽量以小的代价满足用户需求。
在add函数的需求变化中,主要还是对传入的参数进行预处理。如果我们把参数预处理工作封装到另外一个函数中,将这个预处理函数和参数一同传给add函数,add函数仅执行求和操作就可以了,不需要关心传传入什么参数。把适应需求变化的工作都放在预处理函数中,这样就实现了add函数的灵活性和可扩展性。
这段代码相对前面的代码有了较大变动。定义了一个prepare函数,用于对传入add函数的参数做预处理工作。add函数增加了一个函数参数,这个函数参数用于接收另外一个函数的名称或引用变量,在add函数中,可以调用以参数方式传入的函数,调用方式和直接调用函数一样。
函数可以作为参数传递给调用函数,主要是函数的引用起了作用。当函数名称或引用变量做为实参传递给函数时,实际上是把函数的引用变量给传递过去了。
一个更实际的例子是用传入的转换函数简单将一个序列的数转换为相同的类型。例如传入Python的内建函数int()或float()来执行转换。
上面的代码定义了convert转换函数,convert转换函数需要传递一个函数引用和列表序列进来,传递的函数引用可以是Python的内建函数int()或float(),传入的函数将传入的列表元素转换为整型或浮点类型。上面的代码执行后,输出结果如下图所示。