python函数进阶之高阶函数
在某些时候,我们会遇到这样的函数,比如python中的map函数,这个函数是一个映射函数,它的的作用是对一个可迭代对象的进行一定规则的映射,比如,我们得到一个列表[1,2,3,4,5],这个时候我们想得到它们每个元素的平方再组成的一个列表,这个时候,我们就可以直接用map函数将这个列表中的每个元素映射成它的平方值。在map函数首先要传入你要映射的规则,然后传入可迭代对象,就可以得到映射之后的值了。例如
nums = [1,2,3,4,5] # 定义一个列表
nums1 = list(map(lambda x:x ** 2,nums)) # 映射规则是一个匿名函数,我们前面讲过匿名函数,然后映射后放入另一个列表num1
print(nums) # [1, 2, 3, 4, 5]
print(nums1) # [1, 4, 9, 16, 25]
当然也可以写成分解动作
nums = [1,2,3,4,5] # 定义一个列表
a = lambda x:x ** 2
nums1 = list(map(a,nums)) # 映射规则是一个匿名函数,我们前面讲过匿名函数,然后映射后放入另一个列表num1
print(nums) # [1, 2, 3, 4, 5]
print(nums1) # [1, 4, 9, 16, 25]
而实际上可以用一个列表推导式更优雅,但是我们这里讨论这个,重点不是这个。
那么问题来了,map函数的第一个参数竟然可以是一个函数,没错,它是一个函数参数,万事万物都是对象,而函数的参数可以是任意数据类型的对象,因此,函数可以是函数参数,而且函数也可以作为另一个函数的返回值。这种函数的参数又是另一个函数的参数或者返回值的函数,就叫高阶函数。
高阶函数有什么用呢?它最大的特点,叫做解耦合
,在程序的世界,我们将代码分为很多个模块,我们希望不同代码模块之间是的关系性不是那么的强或者叫做依赖不是那么强,这样才会在一些代码出现问题时,尽量不会牵连到更多的代码,这叫程序的耦合性,关系性越强,我们说他们之间的耦合度越高,通常来说,我们希望代码是耦合度越低越好。那么,解耦合就是降低耦合度。其次,解耦合后,函数的通用性强了。例如,这里举一个之前举过的例子看看高阶函数的作用。
在介绍《你知道可变参数、位置参数、lambda函数吗》时我们举了这样一个多数求和的例子
def calc(*args, **kwargs):
result = 0
for arg in args:
result += arg
for value in kwargs.values():
result += value
return result
但在这里我们不但想让它能做加法,还希望它能后做乘法,或者更多的二元运算,而看上去代码好像不好改了,因为第四行和第六行已经确定是做加法了,那么,我们是否可以将这里替换成一个函数呢?而这个函数我们先不告诉它运算规则,再通过参数传入的方式将这个规则传进来(将规则放进函数,将函数作为参数传入)。我们想让它做什么样的二元运算就传入什么样的函数参数,这样是不是就可以实现了一个函数做多种二元运算的功能。
def calc(*args, init_value, op, **kwargs): # 这里由于我们做不同二元运算的初始值要不同,所以我们也将它用参数传入,
#op是要传入的函数名
result = init_value
for arg in args:
result = op(result, arg)
for value in kwargs.values():
result = op(result, value)
return result
现在,如果我们先要做加法
def calc(*args, init_value, op, **kwargs): # 这里由于我们做不同二元运算的初始值要不同,所以我们也将它用参数传入,
#op是要传入的函数名
result = init_value
for arg in args:
result = op(result, arg)
for value in kwargs.values():
result = op(result, value)
return result
def add(x,y):
return x + y
print(calc(1,2,3,5,init_value = 0, op = add,a = 6,b = 7)) # 24
同样想要做乘法时:
def mul(x, y):
return x * y
print(calc(1,2,3,5,init_value = 1, op = mul,a = 6,b = 7)) # 1260 ,记得将初始值改为1
是不是通用性就更好了呢?不知道你注意到没有,传入函数参数时,我只传入了函数的名字add和mul,这里很重要,请一定重视:
将函数作为参数和调用函数是有显著的区别的
调用函数需要在函数名后面跟上圆括号,而把函数作为参数时只需要函数名即可。
调用函数需要在函数名后面跟上圆括号,而把函数作为参数时只需要函数名即可。
调用函数需要在函数名后面跟上圆括号,而把函数作为参数时只需要函数名即可。
重要的事说三边。好了,高阶函数我们就先讲到这里。
如果对你有帮助,不要忘记点赞、关注、评论加收藏哦!