Day 21:5 个常用的高阶函数,3 个创建迭代器的函数
发布日期:2022年3月12日 18:02 阅读: 293 访问: 293
今天介绍 8 个实用的内置函数。高阶函数filter(function, iterable) 过滤器,过滤掉不满足函数 function 的元素,重新返回一个新的迭代器。这个函数大概等价于下面自定义函数 filter_self:d
今天介绍 8 个实用的内置函数。
高阶函数
filter(function, iterable)
过滤器,过滤掉不满足函数 function 的元素,重新返回一个新的迭代器。这个函数大概等价于下面自定义函数 filter_self:
def filter_self(function,iterable):
return iter([ item for item in iterable if function(item)])
filter_self 函数接收一个 function 作为参数,满足条件的元素才得以保留。
调用 filter_self,筛选出满足指定身高的学生。其条件是,男生身高超过 1.75,女生身高超过 1.65。
class Student():
def __init__(self,name,sex, height):
self.name = name
self.sex = sex
self.height = height
def height_condition(stu):
if stu.sex == 'male':
return stu.height > 1.75
else:
return stu.height > 1.65
students = [Student('xiaoming','male',1.74),
Student('xiaohong','female',1.68),
Student('xiaoli','male',1.80)]
students_satisfy = filter_self(height_condition,students)
for stu in students_satisfy:
print(stu.name)
打印结果:
xiaohong
xiaoli
解释下 height_condition 函数,其第一个参数是可迭代对象 iterable 中的一个元素,这是值得注意的。
以上使用自定义过滤函数,下面使用 Python 内置的 filter 函数,也实现一遍学生身高筛选功能。
students_satisfy = filter(height_condition,students)
for stu in students_satisfy:
print(stu.name)
打印结果如下,与上面使用自定义过滤函数实现的结果相同。
xiaohong
xiaoli
map(function, iterable, …)
它将 function 映射于 iterable 中的每一项,并返回一个新的迭代器。
如下,map 函数实现每个元素加 1:
In [10]: mylst = [1,3,2,4,1]
In [12]: result = map(lambda x: x+1, mylst)
In [13]: result
Out[13]: <map at 0x214b38353c8>
In [14]: list(result)
Out[14]: [2, 4, 3, 5, 2]
同时注意到,map 函数支持传入多个可迭代对象。
当传入多个可迭代对象时,输出元素个数等于较短序列长度。
如下,传入两个列表,function 就需要接受两个参数,取值分别对应第一、第二个列表中的元素。
找到同时满足第一个列表的元素为奇数,第二个列表对应位置的元素为偶数的元素。
In [63]: xy = map(lambda x,y: x%2==1 and y%2==0, [1,3,2,4,1],[3,2,1,2])
In [64]: for i in xy:
...: print(i)
False
True
False
False
借助 map 函数,还能实现向量级运算。
In [65]: lst1 = [1,2,3,4,5,6]
In [66]: lst2 = [3,4,5,6,3,2]
In [68]: def vector_add(x,y):
...: return list(map(lambda i,j: i+j, x,y))
In [69]: vector_add(lst1,lst2)
Out[69]: [4, 6, 8, 10, 8, 8]
同时还支持,向量长度不等的加法运算:
In [65]: lst1 = [1,2,3,4,5,6]
In [70]: lst3 = [1,2]
In [71]: vector_add(lst1,lst3)
Out[71]: [2, 4]
reduce(function, iterable[, initializer])
提到 map,就会想起 reduce,前者生成映射关系,后者实现归约。
reduce 函数位于 functools 模块中,使用前需要先导入。
In [72]: from functools import reduce
reduce 函数中第一个参数是函数 function。function 函数,参数个数必须为 2,是可迭代对象 iterable 内的连续两项。
计算过程,从左侧到右侧,依次归约,直到最终为单个值并返回。
In [73]: reduce(lambda x,y: x+y,list(range(10)))
Out[73]: 45
以上 reduce 的完整过程,参考下面的演示动画:
reversed(seq)
重新生成一个反向迭代器,对输入的序列实现反转。
In [155]: rev = reversed([1,4,2,3,1])
In [156]: for i in rev:
...: print(i)
1
3
2
4
1
反转过程,动画演示如下:
sorted(iterable, *, key=None, reverse=False)
实现对序列化对象的排序
key 参数和 reverse 参数必须为关键字参数,都可省略。
In [1]: a = [1,4,2,3,1]
In [2]: sorted(a,reverse=True)
Out[2]: [4, 3, 2, 1, 1]
如果可迭代对象的元素也是一个复合对象,如下为字典。
依据依据为字典键的值,sorted 的 key 函数就会被用到。
In [80]: a = [{'name':'xiaoming','age':20,'gender':'male'},
...: {'name':'xiaohong','age':18,'gender':'female'},
...: {'name':'xiaoli','age':19,'gender':'male'}]
In [81]: b = sorted(a,key=lambda x: x['age'],reverse=False)
In [82]: b
Out[82]:
[{'name': 'xiaohong', 'age': 18, 'gender': 'female'},
{'name': 'xiaoli', 'age': 19, 'gender': 'male'},
{'name': 'xiaoming', 'age': 20, 'gender': 'male'}]
排序的可视化图,如下所示:
迭代器
iter(object[, sentinel])
返回一个严格意义上的可迭代对象,其中,参数 sentinel 可有可无。
In [21]: lst = [1,3,5]
In [22]: it = iter(lst)
In [23]: it
Out[23]: <list_iterator at 0x214b3886188>
In [26]: it.__next__()
Out[26]: 1
In [27]: it.__next__()
Out[27]: 3
In [28]: it.__next__()
Out[28]: 5
In [29]: it.__next__()
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-29-74e64ed6c80d> in <module>
----> 1 it.__next__()
StopIteration:
it 迭代结束后,在 __next__ 时,触发 StopIteration 异常,即迭代器已经执行到最后。
下面的 for 和 in 结合,我们都比较熟悉,iterable 为可迭代对象,依次迭代输出元素。
for ele in iterable:
print(ele)
对象 iterable 要想支持以上这类结构,需要满足什么条件呢?
只要 iterable 对象支持可迭代协议,即自定义了 __iter__ 函数,便都能配合 for 依次迭代输出其元素。
如下,TestIter 类实现了迭代协议,__iter__ 函数。
class TestIter(object):
def __init__(self):
self._lst = [1,3,2,3,4,5]
#支持迭代协议(即定义有 __iter__() 函数)
def __iter__(self):
print ("__iter__ is called!!")
return iter(self._lst)
所以,对象 t 便能结合 for,迭代输出元素。
t = TestIter()
for e in t: # 因为实现了 __iter__ 方法,所以 t 能被迭代
print(e)
打印结果,如下所示:
__iter__ is called!!
1
3
2
3
4
5
完整过程,动画演示:
next(iterator,[, default])
返回可迭代对象的下一个元素:
In [129]: it = iter([5,3,4,1])
In [130]: next(it)
Out[130]: 5
In [131]: next(it)
Out[131]: 3
In [132]: next(it)
Out[132]: 4
In [133]: next(it)
Out[133]: 1
当迭代到最后一个元素 1 时,再执行 next,就会抛出 StopIteration,迭代器终止运行。
In [135]: next(it)
----------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-135-bc1ab118995a> in <module>
----> 1 next(it)
StopIteration:
案例:定制一个递减迭代器
编写一个迭代器,通过循环语句,对某个正整数,依次递减 1,直到 0。
实现类 Descrease,继承于 Iterator 对象,重写两个方法:
- __iter__
- __next__
from collections.abc import Iterator
class Decrease(Iterator):
def __init__(self, init):
self.init = init
def __iter__(self):
return self
def __next__(self):
while 0 < self.init:
self.init -= 1
return self.init
raise StopIteration
调用递减迭代器 Decrease:
descend_iter = Decrease(6)
for i in descend_iter:
print(i)
打印结果:
5
4
3
2
1
0
核心要点:
- __next__ 名字不能变,实现定制的迭代逻辑
- raise StopIteration:通过 raise 中断程序。
enumerate(iterable, start=0)
enumerate 是很有用的一个内置函数,尤其要用到列表索引时。
它返回可枚举对象,也是一个迭代器。
In [93]: s = ["a","b","c"]
In [95]: for i ,v in enumerate(s):
...: print(i,v)
...:
0 a
1 b
2 c
也可以手动执行 next,依次输出一个 tuple。
In [96]: enum = enumerate(s)
In [97]: next(enum)
Out[97]: (0, 'a')
In [98]: next(enum)
Out[98]: (1, 'b')
In [99]: next(enum)
Out[99]: (2, 'c')
小结
今天,与大家一起学习:
5 个 重要的高阶函数
- filter:根据条件筛选元素
- map:映射可迭代对象
- reduce:归约可迭代对象
- reversed:反转可迭代对象
- sorted:排序可迭代对象
3 个 有用的迭代器函数
- iter:返回一个迭代器
- next:返回迭代器的下一项
- enumerate:返回对象的枚举迭代器
动画对应短视频下载链接:
https://pan.baidu.com/s/1MrnrXEnl54XDYYwkZbSqSA
提取码:634k