Python高阶函数及函数柯里化

  • 2019 年 10 月 18 日
  • 笔记

1 Python高阶函数

  接收函数为参数,或者把函数作为结果返回的函数为高阶函数。

 1.1 自定义sort函数

  要求:仿照内建函数sorted,自行实现一个sort函数。内建函数sorted函数是返回一个新的列表,可以设置升序或降序,也可以设置一个排序的函数,自定义的sort函数也要实现这个功能。

  sort函数实现思路:新建一个列表,遍历原列表,和新列表的值一次比较决定如何插入到新列表中。

  sort函数版本一的实现,代码如下:

 1 def sort(iterable):   2     ret = []   3     for x in iterable:   4         for i, y in enumerate(ret):   5             if x > y:  # 找到比ret中大的位置上的数插入相应位置,降序排序   6                 ret.insert(i, x)   7                 break   8         else:  # 不大于,说明x在ret中是最小的,直接将其追加至ret后   9             ret.append(x)  10     return ret  11  12 if __name__ == '__main__':  13     lst = [1,2,3,4,5,6,7,8]  14     print(sort(lst))

View Code

  上述代码只能实现的,升序的排列方式,那么现在想通过一个参数来控制排列的方式,该如何实现呢?看如下代码:

 1 def sort(iterable, reverse=False):   2     ret = []   3     for x in iterable:   4         for i, y in enumerate(ret):   5             flag = x > y if reverse else x < y  # 默认排序方式为升序   6             if flag:  # 找到比ret中大的位置上的数插入相应位置,降序排序   7                 ret.insert(i, x)   8                 break   9         else:  # 不大于,说明x在ret中是最小的,直接将其追加至ret后  10             ret.append(x)  11     return ret

View Code

  通过对reverse参数的boole值进行判断,看使用降序还是升序,那么能不能将对x,y大小的判断的功能抽象出来,作为一个排序的函数传给sort函数?看如下代码:

 1 def comparator(x, y):   2     if x > y:   3         return False   4     else:   5         return True   6   7 def sort(iterable, reverse=False, key=None):   8     ret = []   9     for x in iterable:  10         for i, y in enumerate(ret):  11             flag = key(x, y) if reverse else not key(x, y)  12             if flag:  # 找到比ret中大的位置上的数插入相应位置,默认降序排序  13                 ret.insert(i, x)  14                 break  15         else:  # 不大于,说明x在ret中是最小的,直接将其追加至ret后  16             ret.append(x)  17     return ret

View Code

  该代码中在调用sort函数,每次都得传入一个函数才能实现排序,那么能不能用一个函数的表达式作为一个默认值参数进行传入呢?这就要用到匿名函数,代码如下:

 1 def sort(iterable, reverse=False, key=lambda a,b:a>b):   2     ret = []   3     for x in iterable:   4         for i, y in enumerate(ret):   5             flag = key(x, y) if not reverse else not key(x, y)   6             if flag:  # 找到比ret中大的位置上的数插入相应位置,默认降序排序   7                 ret.insert(i, x)   8                 break   9         else:  # 不大于,说明x在ret中是最小的,直接将其追加至ret后  10             ret.append(x)  11     return ret

View Code

  一步一步的将代码实现到这,已经将sort函数从最初实现的简单排序,改成最终的可以设置升序和排序,以及设置排序的规则的函数。这样就将sort函数改成了一个高阶函数。

1.2 内建函数-高阶函数

1.2.1 sorted函数

  sorted(iterable[, key][, reverse]),内置函数sorted函数中可选的key参数用于提供一个函数,它会应用到各个元素上进行排序。例如,如果想根据单词的长度进行排序,只需将len函数传给key参数,如下示例:

   任何单参数函数都能作为key参数的值,再比如实现:将每个单词的字母反转后,在对其进行排序。实现如下:

    在函数式编程中,Python 3中常用的高阶函数还有,map、filter。

1.2.2 filter函数

  filter(function, iterable),过滤可迭代对象的元素,返回一个迭代器。function是一个具有单参数的函数,返回bool值。

1 list(filter(lambda x: x%3==0, [1,9,55,150,-3,78,28,123]))  # 过滤出数列中能被3整除的数字

1.2.3 map函数

  map(function, *iterables),对多个可迭代对象的元素按照指定的函数进行映射,返回一个迭代器。

list(map(lambda x:2*x+1, range(5)))  dict(map(lambda x: (x%5,x) , range(500)))

  在Python 3中,map和filter返回生成器(一种迭代器),因此现在它们的直接替代品是列表推导式和生成器表达式。

2 柯里化Currying

  柯里化指的是将原来接收两个参数的函数变成新的接收一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数。其形式相当于将z = f(x, y)转换成z = f(x)(y)的形式。举例:

 1 # 将加法函数柯里化   2 def add(x, y):   3     return x + y   4   5 # 柯里化   6 def add(x):   7     def inc(y):   8         return x + y   9     return inc  10  11 foo = add(2)  12 print(foo(3))  13 # 相当于  14 print(add(2)(3))

View Code

  通过柯里化的过程可知,在柯里化时使用嵌套函数就可以将函数转换成柯里化函数。