Python常用高阶函数map/sorted/filter/reduce

python中高阶函数的定义为:接收函数作为参数,或者把函数作为结果返回的函数就是高阶函数(higher-order function)

在函数式编程范式中,最常见的高阶函数有map、filter、reduce和sorted。
下面着重使用python自定义函数来实现他们的功能,这样更有助于加深理解和记忆

一丶sorted

首先先来介绍个小技巧,在jupyer notebook中,如果遇到我们想调用的函数,却又不知道如何传参,以及想知道这个函数更多的细节时,我们可以sorted?来查看这个函数的帮助文档。
如果想知道更全的知识点,可以查看Python官方文档。

Signature: sorted(iterable, /, *, key=None, reverse=False)
Docstring:
Return a new list containing all items from the iterable in ascending order.

A custom key function can be supplied to customize the sort order, and the
reverse flag can be set to request the result in descending order.
Type:      builtin_function_or_method

我们很清楚的看到,他可以接受一个可迭代对象,然后有两个可选的默认仅限关键字参数Key和reverse,返回值为一个新的list
下面我们来用python的自定义函数来实现soreted的功能实现

def sorted1(iterable,reverse = True ,key = None):
    newlist = []
    for i in iterable:
        # 这里的key和下面的key的作用是相同的,并不会修改原值
        ci = i if key is None else key(i)
        for j, k in enumerate(newlist):
            # key用来定义排序顺序,并不会修改原值
            ck = k if key is None else key(k)
            # 下面这两行用来控制reverse的参数,来控制排序是按升序还是降序
            control = ci > ck if reverse == True else ci < ck  
            if control:
                newlist.insert(j,i)
                break  # 找到合适的位置
        else:
            newlist.append(i)
    return newlist
sorted1([1,2,3,4,5],reverse=True,key = lambda x : 100 - int(x))

[5, 4, 3, 2, 1]

上面这个函数实现了和sorted一样的功能。
key实际上传入的是一个函数对象,然后分别作用在原序列的元素上,返回值用来比较,这也是sorted排序的关键地方
reverse用来控制升序还是降序

下面来普及个冷知识,其实字符串之间也是可以比较大小的。
Strings (instances of str) compare lexicographically using the numerical Unicode code points (the result of the built-in function ord()) of their characters.
String 通过内置函数ord()获得每个字符的unicode编码进行比较大小。先比较两个对象的第0个元素,大小关系即为对象的大小关系,如果相等,则继续比较后续元素,先终止迭代的认为是小的

In [1]: "ac" > "abb" > "ab"

Out[1]: True  

这里用的是链式比较,等价于

In [2]: "ac" > "abb" and "abb" > "ab"

Out[2]: True
二丶map
Init signature: map(self, /, *args, **kwargs)
Docstring:     
map(func, *iterables) --> map object

Make an iterator that computes the function using arguments from
each of the iterables.  Stops when the shortest iterable is exhausted.
Type:           type
Subclasses: 

接收两个参数,function和可迭代对象,可以同时多个可迭代对象
返回值为一个类似generator的迭代器

def map1(function,*iterable):
    for args in zip(*iterable):
        yield function(*element)
list(map1(lambda x :x+1 ,[1,2,3]))

[2, 3, 4]

map将传入的函数依次作用于序列的每个元素,并把结果作为新的iterable返回

三丶filter
Init signature: filter(self, /, *args, **kwargs)
Docstring:     
filter(function or None, iterable) --> filter object

Return an iterator yielding those items of iterable for which function(item)
is true. If function is None, return the items that are true.
Type:           type
Subclasses:  

这次我们先用python自定义函数来实现filter
的功能

def filter1(function,iterable):
    for i in iterable:
        if function is None:  
            if i:
                yield i
        else:
            if function(i):
                yield i
g = filter1(None, [0,1,2,3])
for i in g:
    print(i)

1
2
3

filter接收两个参数,function和iterable, 他会把传入的函数依次作用于每个元素,然后根据返回值是True或者False来决定是保留还是丢弃元素。
如果function是None,就返回bool值为真的元素

四丶reduce
Docstring:
reduce(function, sequence[, initial]) -> value

Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
Type:      builtin_function_or_method

reduce从functools模块中导入
很明显可以看到,reduce接收三个参数,其中一个为可选参数,返回值为单一的值(single value)
照例还是先用python自定义函数来实现reduce功能

def reduce1(function,sequence,initial = None):
    it = iter(sequence)  # def 函数实现的关键在于将传入的可迭代sequence转换成iterator迭代器
    if initial is None:
        value = next(it) # 因为it现在是一个迭代器,而这里的value恰当的当的迭代器的第一个元素赋值给了value,呼应了下面的for循环遍历
    else:
        value = initial
    for element in it: # 这里如果it不是迭代器,我们可以直接[1:]开始迭代好像也可以
        value = function(value,element)
    return value
    
reduce1(lambda x,y : x*y, [1, 2, 3, 4], 3)

72

function为函数对象,这个函数必须接收两个参数
sequence为一个序列,函数作用在这个序列上,reduce把结果继续和序列的下一个元素做累计计算,起效果相当于

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

initial为初始值,可选参数

五丶map/reduce/filter的替代方案

函数式语言通常会提供map、filter和reduce的三个高阶函数,filter和map还是内置函数,在python3中,由于引入了列表推导式和生成器表达式,他们变得不那么重要了,列表推导和生成器具有map和filter的功能,而且更易于阅读。

In [3]: def func(n):
   ...:     return n * 2

In [6]: list(map(func,range(5)))
Out[6]: [0, 2, 4, 6, 8]

In [5]: [func(n) for n in range(5)]
Out[5]: [0, 2, 4, 6, 8]

In [7]: list(map(func,filter(lambda x : x % 2, range(6))))
Out[7]: [2, 6, 10]

In [9]: [func(n) for n in range(6) if n % 2]
Out[9]: [2, 6, 10]

在python3中,map和filter返回一种迭代器,因此他们的替代品就是生成器表达式
在python2中,reduce是内置函数,但是在python3中放到functools模块中了,这个函数最常用于求和,自从python2.3开始,最好使用内置的sum函数,在可读性和性能方便,这是一项重大改善

In [10]: from functools import reduce

In [11]: from operator import add

In [12]: reduce(add,range(100))
Out[12]: 4950

In [13]: sum(range(100))
Out[13]: 4950

sum和reduce的通用思想是把某个操作连续运用在序列的元素上,累计之前的结果,把一系列的值规约成一个值。

any和all也是内置的归约函数。
all(iterable)
如果iterable的每个元素都为真值,则返回True, all([ ])返回True

any(iterable)
如果iterable中有元素是真值,就返回True,any([ ])返回False

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值