迭代器, 高阶函数(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)

 

posted on 2020-05-14 19:21  fdsimin  阅读(235)  评论(0编辑  收藏  举报