Python 生成器及高阶函数 filter map reduce

时间:2021-10-11 19:44:42

讲到生成器,往前可以讲到列表生成式,往后可以讲到迭代器

今天就复习一下生成器,再另外多复习一下高阶函数



如何定义一个生成器

方法1:

首先,像列表生成式,我们用得很普遍了

如 L=[x for x in range(1,5)]

这样生成的结果就是[1,2,3,4]

那生成器是什么呢?他其实是一个对象,并不是一个具体的序列形式

比如,我们把列表生成式的外壳[ ] 改成( ),他的返回对象就是一个生成器了


Python 生成器及高阶函数  filter map reduce

你如果用dir(b)来检查b这个生成器对象的话,你会发现,他有一个属性叫做__next__,什么意思呢?就是每用一次这个函数,他都会返回一轮迭代并停止

比如下图,你可以用b.__next__或者next(b),两者都行

Python 生成器及高阶函数  filter map reduce

但是,当你的迭代超出范围了以后,他就会报错StopIteration了。


如果需要避免这样的报错的话,你可以用for循环来从中取值

Python 生成器及高阶函数  filter map reduce



方法2:

另外一种产生生成器的方法,则是定义的函数中,包含了关键字yield,那么这个函数就不是一个特殊的函数

比如,我们来举个例子,下面的例子,由于函数里面包含了yield,所以每一次函数运行到yield的时候,就会提取当轮的数据,并停止,只有当你再次执行next的时候,再从停止的位置开始,继续往下走,走到下一次yield的时候

Python 生成器及高阶函数  filter map reduce



特殊情况:

生成器可以来说是一个惰性的结构,需要后续的操作来消耗他,所以对于生成器来说内容被消耗完了,怎么办?

比如前面碰到的,会有StopIteration的错误发生,那是否可以优雅地避免呢?

你就可以使用try功能,比如下面的例子

a=(x for x in range(1,5))

while True:
try:
print (a.__next__())
except StopIteration as e:
print (e.value)
break

当while循环消耗完所有的迭代内容后,触发stopiteration错误时,自动停止,这样就避免了触发报警信息.

Python 生成器及高阶函数  filter map reduce



最后自己做一个例子:

写一个指定范围内,3的倍数的生成器,并以列表打印出来

def triple(n):
x=1
while x<=n:
if x%3==0:
yield x
x+=1
else:
x+=1
continue
return 'done'

a= [x for x in triple(1000)]
print (a)

Python 生成器及高阶函数  filter map reduce


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------


高阶函数

接着,来讲讲高阶函数,主要有这几种filter,map,reduce


首先是filter

filter函数,接受2个参数,一个已定义的函数或lambda表达式,和一个可迭代的对象

他的作用过程是,将第二个可迭代对象的内部参数,一个一个传入function内部使用,如果返回值是True,则加入结果,反之,则不加入

最终,生成一个迭代器,由所有返回结果为True的元素组成。

Python 生成器及高阶函数  filter map reduce


如果function定义了,那么,他返回的是上面说的形式

如果function 是None,那么,他返回的是可迭代对象内部,不是False的元素

a=[1,2,3,4,5,6,7,8,9]
def test_filter(s):
if s%2==0:
return True
else:
return False

print (list(filter(test_filter,a)))

注意,filter返回的是一个可迭代对象,你需要用list这样的操作方式来将他显性地显示出来

另外还需要注意,定义的函数需要以bool值来返回,这样有利于判断

Python 生成器及高阶函数  filter map reduce


再缩略一些,就用lambda函数

Python 生成器及高阶函数  filter map reduce



map函数

接着是map函数

同样也是传入function和可迭代对象,他的工作过程是将iterable内的元素一一放进function内,并返回所有结果的迭代器

注意:如果有多个iterable同时传入,那么,取值时候就是从2个iterable内同步取值,如果2个iterable长度不一样,则以短的结束时候为准

Python 生成器及高阶函数  filter map reduce

a=[1,2,3,4,5,6,7,8,9]
def test_map(s):
return s+5


print (list(map(test_map,a)))

结果如下

Python 生成器及高阶函数  filter map reduce

如果用lambda函数来写,也行

Python 生成器及高阶函数  filter map reduce


我们再来看看,同时传入多个iterable参数的时候的情况

如果函数定义的参数只有一个,但是传入参数有2个,就会报错

Python 生成器及高阶函数  filter map reduce


再来看下形参和实参一致的情况下,2个参数长度不一致的情况,如下

a=map(lambda x,y:x+y,range(1,10),range(1,5))

Python 生成器及高阶函数  filter map reduce





reduce函数

reduce函数的话,说穿了也是讲给定iterable内部函数传入指定函数的工作过程,但是,他在每一次迭代后,都会和上一次进行累加

内部指定的这个function函数,必须接受2个参数

说起来有点拗口,先看看定义


Python 生成器及高阶函数  filter map reduce


来看下面的例子

from functools import reduce

a=[1,2,3,4,5]
def f(a,b):
return a+b


print (reduce(f,a))


他其实就是  f(f(f(f(1,2),3),4),5) 的这样一个过程
Python 生成器及高阶函数  filter map reduce


当然,你也可以设定第三个参数,初始值,如果你设定了初始值,那么,他在第一轮的时候,就不是取第1,2个参数了,而是用第1个参数传入函数计算后,结果加上初始值

比如下面

from functools import reduce

a=[1,2,3,4,5]
def f(a,b):
return a+b


print (reduce(f,a,100))
结果如下

Python 生成器及高阶函数  filter map reduce

所以,reduce函数在做累加运算的时候比较有用


最后看一个稍微复杂点的例子

from functools import reduce

def fn(x, y):
return x * 10 + y

def char2num(s):
return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]

print (reduce(fn,map(char2num,'13579')))


char2num函数作用是把字符串转化成整数,他用的map函数,返回了一个iterator.

而最后,通过reduce函数,将这个iterator内部的元素(已经是整型了的元素),通过fn函数,累加起来,拼成结果。