迭代器, 高阶函数(map, filter, reduce, sorted) , 递归函数
1, 迭代器:
1.1 可迭代对象: 如果成员中包括__iter__这个方法, 就是可迭代对象, 包括容器类型的数据,range函数,迭代器
from collections import Iterable,Iterator res = isinstance(range(8),Iterable) print(res) # True 判断这个数据类型是不是一个可迭代对象 res1 = isinstance(range(8),Iterator) print(res1) # False 判断这个数据类型是不是一个迭代器
1.2 迭代器定义: 迭代器 : 能被next调用,并不断返回下一个值得对象,叫做迭代器
概念: 迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果而继续,单纯的重复不是迭代
特征: 不依赖索引,通过next指针迭代所有数据,一次只取一个,可以大大节省空间,迭代无限量的数据
如果是迭代器的话就一定是可迭代对象,但是一个可迭代对象不一定是迭代器
1,3 如何判断一个对象是不是迭代器
可以使用dir()函数来获取这个对象里面的成员,如果成员中包含__iter__和__next__那这个对象就是一个迭代器
我们也可以直接打印这个对象, 如果返回一个"list_iterator object"那也可以判断是一个迭代器,也可以用type()来获取, 也可以用isinstance来判断
list1 = [1,2,"字符",9.9] it = iter(list1) # 方式一: res = "__iter__" in dir(it) and "__next__" in dir(it) print(res) # True # 方式二: print(it) # <list_iterator object at 0x000001F41C4DF1D0> print(type(it)) # <class 'list_iterator'> # 方式三: from collections import Iterator,Iterable res = isinstance(it,Iterator) print(res) # True
1.4 迭代器取值方式:
list1 = [1,2,"字符",9.9] it = iter(list1) # print(it) # <list_iterator object at 0x000001976367F1D0> # 调用迭代器里面的元素: # 方式一: 用next()方法 res = next(it) print(res) # 1 res = next(it) print(res) # 2 res = next(it) print(res) # 字符 res = next(it) print(res) # 9.9 # res = next(it) # print(res) # StopIteration 此时迭代器里的元素已经调用完,再调用的话就会报错,因为迭代器是一直向下执行的,不会再回过头去取值 it2 = iter(list1) res2 = next(it2) print(res2) # 1 如果要重新取迭代器里面的值的话,就要重置这个迭代器,也就是将容器类型重新转化成迭代器 # 方式二: 用for和next配合使用来取值 list1 = [1,2,"字符",9.9] it = iter(list1) for i in range(len(list1)): res = next(it) print(res) # 这个是将值一次性全部取出来,如果数据量比较大的话,就不推荐这种方式 list1 = [1, 2, "字符", 9.9] it = iter(list1) for i in range(2): res = next(it) print(res) # 这个是只取出迭代器里面的前面两个值,如果数据量比较大,而我们只需要前面某些数据的话,推荐这种方式 # 方式三: 直接使用for循环遍历迭代器里面的值 list1 = [1, 2, "字符", 9.9] it = iter(list1) for i in it: print(i) # 遍历出迭代器里的所有值 # 方式四: 将迭代器强转为列表类型 list1 = [1, 2, "字符", 9.9] it = iter(list1) list1 = list(it) print(list1) # [1, 2, '字符', 9.9]
2, 高阶函数: 能把函数当做参数传递的就是高阶函数
2.1 map函数: map(func,iterabal)
把iterabal里面的数据一个一个拿出来,放到func函数里面去处理,把处理的结果放到迭代器中,返回迭代器
func可以值内置函数,也可以是自定义函数
iterabal是可迭代对象
2,1,1 map函数小案例:
# 案例一: 将列表里面的字符串元素变成整型 #方法一: list1 = ["1","2","3","4"] # ==> [1,2,3,4] from collections import Iterator,Iterable it = map(int,list1) res = isinstance(it,Iterator) print(res) # True 所以map函数取值应该遵循迭代器取值的方法 list2 = list(it) print(list2) # [1, 2, 3, 4] # 方法二: it = map(lambda n:int(n),list1) list2 = list(it) print(list2) # [1, 2, 3, 4] # 案例二: # 方法一: list1 = [1,2,3,4] # ==> [1,4,9,16] def func1(n): return n**2 it = map(func1,list1) list2 = list(it) print(list2) # [1, 4, 9, 16] # 方法二: it = map(lambda n:n**2,list1) list2 = list(it) print(list2) # [1, 4, 9, 16] # 案例三: # dic = {97:"a",98:"b",99:"c"} 给["a","b","c"] => 返回 [97,98,99] # 方法一: dict1 = {97:"a",98:"b",99:"c"} list1 = ["a","b","c"] def func1(n): for k,v in dict1.items(): if str(n) in v: return k it = map(func1,list1) res = list(it) print(res) # [97, 98, 99] # 方法二: def func1(n): dict2 = {} for k,v in dict1.items(): dict2[v]=k return dict2[n] it = map(func1,list1) res = list(it) print(res) # [97, 98, 99]
2.2 filter函数: 主要是在自定义函数中过滤数据,如果函数返回True,代表保留数据,如果函数返回False,代表舍弃该数据,返回的也是一个迭代器
2,2,1 filter 函数案例:
list1 = [1,2,3,4,5,6,7] # 需要保留奇数 # 方法一: def func1(n): if n %2 == 1: return True else: return False it = filter(func1,list1) list2 = list(it) print(list2) # [1, 3, 5, 7] # 方法二: it = filter(lambda n:True if n%2 == 1 else False,list2) list2 = list(it) print(list2) # [1, 3, 5, 7]
2.3 reduce函数: 一次性从可迭代对象中拿出两个值,放到func函数中进行处理,把运算出来的结果再和可迭代对象的第三个值再放到函数中处理,以此类推,最后返回计算后的结果
2,3,1 reduce()案例
# 案例一: list1 = [5,4,8,8] # 方法一: def func1(x,y): return x*10+y from functools import reduce res = reduce(func1,list1) print(res,type(res)) # 5488 <class 'int'> # 方法二: from functools import reduce res= reduce(lambda x,y:x*10+y,list1) print(res,type(res)) # 5488 <class 'int'> # 案例二:将字符串"123"变成123,不使用int方法 str1 = "123" def dictvar(n): dict1 ={"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9} return dict1[n] it = map(dictvar,str1) list1 = list(it) print(list1) # [1, 2, 3] 首先将字符串类型的数字转为整型的数字 def func1(x,y): return x*10+y from functools import reduce res = reduce(func1,list1) print(res,type(res)) # 123 <class 'int'>
2.4 sorted函数 sorted(iterable,reverse=False,key=函数) 按照自定义或者内置函数对可迭代数据进行排序,其中reverse可以选择是升序还是倒序,返回排序后的列表,功能比sort强大很多, sorted能对所有的容器类型数据进行排列
2.4.1 使用方式:
# 按照升序 tuple1 = (2,83,6,78) list1 = sorted(tuple1) print(list1) # [2, 6, 78, 83] # 按照倒序 set1 = {2,84,52,58,23} list1 = sorted(set1,reverse=True) print(list1) # [84, 58, 52, 23, 2] # 按照函数定义的功能排序 list1 = [26,84,52,1,32] def func1(n): return n%10 res = sorted(list1,key=func1) print(res) # [1, 52, 32, 84, 26]
3. 递归函数: 自己调用自己的函数就叫做递归函数,递归层数理论上是1000层,但是实际随电脑配置而定,996层,997层都是有可能的
3.1 递归函数小案例:
def digui1(n): print(n) if n < 8: digui1(n+1) digui1(3) # 最为简单的一种递归操作,在递归函数"回"的过程中没有代码块执行 def digui2(n): print(n) if n < 8: digui2(n+1) print(n) digui2(3) #3,4,5,6,7,8,8,7,6,5,4,3 # 这种情况, digui2(n+1)下面的代码块会先阻塞,等digui2(n+1)上面的代码块执行完后,再依次执行下面的代码 # 执行下面代码的过程中也是在释放栈帧内存空间 # 用递归写阶乘 def digui3(n): if n < 2: return 1 return n*digui3(n-1) res = digui3(5) print(res) # 120 # 用递归写斐波那契数列 1,1,2,3,5,8,13,21 def shulie(n): # n代表想要打印的第几个斐波那契数 if n == 1 or n== 2: return 1 return shulie(n-1) + shulie(n-2) res = shulie(5) print(res) # 用递归写1到100求和 def qiuhe(n): if n == 1: return 1 return n + qiuhe(n-1) res = qiuhe(100) print(res) # 用递归写n到m求和 def qiuhe2(n,m): if m == n: return n return m + qiuhe2(n,m-1) res = qiuhe2(-1,2) print(res) # 2
3.2 尾递归: 自己调用自己,并且非表达式,将值放在参数中运行
特点: 无论调用多少层,都只占用一层空间,不会有内存溢出的问题,只需要考虑最后一层的结果,但是对解释器是有要求的,目前Cpython解释器并不支持尾递归
3.2.1 尾递归小案例:
# 用尾递归写阶乘 # 方式一: def jiecheng(n,endval = 1): if n <= 1: return endval return jiecheng(n-1,endval*n) res = jiecheng(5) print(res) # 方式二: 防止用户乱传参数 def outter(n): def jiecheng(n,endval): if n <= 1: return endval return jiecheng(n - 1, endval * n) return jiecheng(n,1) res = outter(5) print(res)