高阶函数是通过组合简单函数成一个复杂表达式的函数。你可以理解成,函数套函数。函数式编程是一种编程范式,这部分内容可以体现 Python 在函数式编程上的应用。
1、lambda
匿名函数(lambda),这个函数没有函数名,用于一行创建一个函数,并返回一个函数对象,也是一种语法糖。
定义一个匿名函数,功能就是参数加1:
my_lb = lambda x: x + 1
普通函数的写法就是:
def add_one(n):
return n + 1
你看,确实很简洁哈,my_lb 不是函数名哈,有函数名它就不是匿名函数了,而是函数对象,咱可以调用它。
print(my_lb(1))
我个人觉得,匿名函数很尴尬,基本上都是用在下面几个高阶函数里面的,如果你平时也想用它,大多数情况下是不符合社区规范的。简单的表达式还行,复杂的表达式可读性太差。
传言 Python 之父 Guido 也不推荐使用它,甚至曾想过移除它,后来放弃了,估计是不好搞。就像 GIL 一样,大家都知道不好,但是这么多年下来太多库都用到了,哪是你想删就能删的,社区不答应,我也不答应。
2、map
map 函数是给一个序列做映射,然后返回结果序列。
简单通俗讲就是:拿到一个序列,给序列中元素一顿操作之后,返回序列。
my_map = map(lambda x: x + 1, [1, 2, 3])
print(my_map)
my_list = list(my_map)
print(my_list)
[2, 3, 4]
你看,map 返回的是一个对象,转 list 之后每个元素的加了1。
3、reduce
reduce 函数就是对一个序列做累积,即将序列中前一个元素和后一个元素进行逻辑组合,然后结果再和后面一个元素组合。
简单通俗讲就是:拿到一个或多个序列,给序列中元素一顿操作之后,返回操作结果。
from functools import reduce
my_rd = reduce(lambda x, y: x + y, [1, 2, 3])
print(my_rd)
6
你看,把列表中的元素都相加了,注意组合关系不一定是相加,你可以换成相乘试试。
乍一看和上面的 map 是一个意思哈,确实用法一样,区别就是 reduce 函数里面的 lambda 函数有两个参数,而 map 函数参数理论上可以多个,但是每个参数对应一个序列,也就是说,有多少个参数,就要有多少个序列。
4、filter
filter 函数用于过滤的,即将序列中的每个元素进行判断,然后返回为 True 的元素。
my_ft = filter(lambda x: x % 2 == 1, [1, 2, 3])
print(my_ft)
my_list = list(my_ft)
print(my_list)
[1, 3]
判断序列中哪些数是奇数,filter 返回的是一个对象,转列表之后,可以看到结果。
5、sorted
sorted 函数用于排序,好多同学可能用过它的参数 reverse=False 升序(默认),reverse=True 降序,但是还有个参数 key 可能没咋用过,这里可以给表达式。
my_st = sorted([1, 5, 3])
print(my_st)
my_st = sorted([1, 5, 3], reverse=True)
print(my_st)
[1, 3, 5]
[5, 3, 1]
数字排序还是挺好用的哈,处理简单的字符串也都可以,但是如果是处理比较复杂字符串排序就有点费劲了,不信试试看:
test_list = ["test_mi_001","test_ki_012","test_go_008","test_lt_003"]
我想让这个列表按照结尾的序号排序:
my_st = sorted(test_list)
print(my_st)
['test_go_008', 'test_ki_012', 'test_lt_003', 'test_mi_001']
排了个寂寞,无论是升序还是降序都是不行的。
所以需要使用参数 key,加表达式:
my_st = sorted(test_list, key=lambda x: x.split("_")[-1])
print(my_st)
['test_mi_001', 'test_lt_003', 'test_go_008', 'test_ki_012']
唉,这就对了,我们在表达式里面将结尾的序号取出来,key 就是关键字,意思就是按照我取出来的关键字排序。这里稍微理解一下哈,里面的表达式比较灵活,你也可以用正则表达式来做:
import re
my_st = sorted(test_list, key=lambda x: re.findall(r"\d+", x))
也都是可以的哈,没毛病。
它不仅可以对列表排序,只要是可迭代对象都可以,列表对象的内建方法 sort 也可以这样用,但区别是 sort 是对原列表进行排序,不返回新列表。
这里再补充一个小知识,我们经常往一个列表中去添加数据,然后对其进行排序,这样做没啥问题,但是如果数据量大了之后,性能会比较低。
维护一个排序序列,建议使用Python 的标准库 bisect 来做,它是采用二分查找算法,性能较高。
6、zip
zip 就是将多个序列打包成一个个元组,然后返回由这些元组组成的列表。
a = [1, 2, 3]
b = [4, 5, 6]
c = zip(a, b)
print(c)
my_list = list(c)
print(my_list)
[(1, 4), (2, 5), (3, 6)]
zip 返回的是一个对象,实际上是一个迭代器对象。
转列表之后,可以看到,相当于是把元素纵向分别取出来,放到一个元组里面,然后元组组成一个列表。做数据处理的时候经常用到,了解一下。