• day13. 迭代器与高阶函数


    一、迭代器

    """
    能被next调用,并不断返回下一个值的对象,叫做迭代器(对象)
    概念:
        迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果而继续的,
        单纯的重复并不是迭代  
    特征:
        并不依赖索引,而通过next指针迭代所有数据,一次只取一个值,大大节省空间
    """

    1、可迭代对象

    setvar = {"a","b","c","d"}
    for i in setvar:
        print(i)
    
    # dir 获取当前类型对象中的所有成员
    """__iter__ 方法用来判断是否是可迭代性数据"""
    lst = dir(setvar)
    print(dir("123"))
    
    res = "__iter__" in dir(setvar)
    print(res)

    2、迭代器

    """
    for 循环能够遍历一切可迭代性数据的原因在于,底层调用了迭代器,通过next方法中的指针实现数据的获取
    可迭代对象  ->  迭代器  不能够被next直接调用 -> 可以被next直接调用的过程
    
    如果是一个可迭代对象不一定是迭代器
    但如果是一个迭代器就一定是一个可迭代对象
    """

    2.1、如何来定义一个迭代器

    setvar = {"a","b","c","d"}
    it = iter(setvar)
    print(it)

    2.2、如何来判断一个迭代器

    print(dir(it))
    res = "__iter__" in dir(it) and "__next__" in dir(it)
    print(res)

    2.3、如何来调用一个迭代器

    """next在调用迭代器中的数据时,是单向不可逆,一条路走到黑的过程"""
    res = next(it)
    print(res)
    res = next(it)
    print(res)
    res = next(it)
    print(res)
    res = next(it)
    print(res)
    """
    # StopIteration 报错 停止迭代
    res = next(it)
    print(res)
    """

    3、重置迭代器

    it = iter(setvar)
    res = next(it)
    print(res)

    4、使用其他方式判断迭代器或者可迭代对象

    """Iterator 迭代器 Iterable 可迭代对象"""
    # from ... 从哪里  import 引入 ...
    from collections import Iterator,Iterable
    # from collections.abc import Iterator,Iterable python3.7 
    res = isinstance(it,Iterator)
    print(res)
    res = isinstance(it,Iterable)
    print(res)

    5、使用其他方式调用迭代器中的数据

    # 1. for 循环
    print("<=>")
    for i in it:
        print(i)
    
    # 2. for + next
    print("<=>")
    lst = [1,2,3,4,5,6,7,7,8,9,10]
    it = iter(lst)
    for i in range(10):
        res = next(it)
        print(res)
    
    print(next(it))
    print(next(it))

    6、总结

    '''
    迭代器:
    
    迭代器(Iterator)可以看做是一个特殊的对象,每次调用该对象是会返回自身的下一个元素,一个迭代器对象必须是定义了__iter__()方法和next()方法的对象
    
    为什么要有迭代器:
    序列类型字符串、列表、元组都有下标,用下标访问没问题。但是非序列类型像字典、集合、文件对象就不能用下标,for循环就是基于迭代器协议
    提供了一个统一的可以遍历所有对象的方法。即在遍历前,先调用对象的__iter__方法将其转换成一个迭代器,然后使用迭代器协议去实现循环访问
    这样所有的对象都可以通过for循环访问了。循环结束,捕捉异常,循环结束。这种方式不依赖与索引
    
    
    可迭代对象:
    
    可迭代对象是指内置有__iter__ 方法的对象,即 obj.__iter__
    
    字符串、元组、列表、字典都可以进行迭代
    
    'kxq'.__iter__
    
    open('kxq.txt'.__iter__)
    
    
    
    迭代器对象
    
    可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
    
    迭代器对象指内置有 __iter__ 、 __next__ 方法的对象
    
    迭代器对象一定是可迭代对象,可迭代对象不一定是迭代器对象
    '''
    i = [1, 2, 3]
    iter_l = i.__iter__() # 得到迭代器对象,
    print(iter_l.__next__()) # 与 next(iter_l)相同
    print(iter_l.__next__())
    print(iter_l.__next__())
    print(iter_l.__next__())# 抛出异常 StopIteration
    
    # iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误;

    6.1、for 循环原理

    i = [1, 2, 3]
    
    for x in i:
         print(x)
    
    # 原理
    # 1.执行i.__iter__() 方法,得到一个迭代器对象 iter_i
    # 2.执行 iter_i.__next__()方法,将得到的值赋值给x,进入循环体
    # 重复2,捕捉StopIteration异常,循环结束

    6.2、优缺点

    1 # 缺点: 它的特性决定了它只能往前,不能后退
    2 
    3 # 有点:节省内存,惰性计算,不依赖与索引

    二、map函数

    """
    map(func,Iterable)
        功能:处理数据
            把Iterable中的数据一个一个拿出来,扔到func函数中做处理
            把处理之后的结果放到迭代器当中,最后返回迭代器
        参数:
            func : 自定义函数 或 内置函数
            Iterable : 可迭代性数据(容器类型数据 range对象 迭代器)
        返回值:
            迭代器
    """

    1、lst = ["1","2","3","4"]  转换为  [1,2,3,4]

    lst = ["1","2","3","4"]
    # 常规写法
    lst_new = []
    for i in lst:
        lst_new.append(int(i))
    print(lst_new)
    
    # map改造
    it = map(int,lst)
    
    """
    # 代码解析:
    先把"1" 扔到int当中做处理,将强转后的结果扔到迭代器中
    然后把"2" 扔到int当中做处理,将强转后的结果扔到迭代器中
    然后把"3" 扔到int当中做处理,将强转后的结果扔到迭代器中
    然后把"4" 扔到int当中做处理,将强转后的结果扔到迭代器中
    最终返回迭代器
    """

    1.1、获取迭代器中的数据

    # 1.next
    res = next(it)
    print(res)
    res = next(it)
    print(res)
    res = next(it)
    print(res)
    res = next(it)
    print(res)
    # 2.for 
    for i in it:
        print(i)
    
    # 3.for + next
    for i in range(4):
        res = next(it)
        print(res)
    
    # 4.list强转
    print(list(it))

    2、[1,2,3,4] 转换为 [2,8,24,64]

    lst = [1,2,3,4]
    '''
    1 * 2^1 = 2
    2 * 2^2 =8
    3 * 2^3 =24
    4 * 2^4 =64
    '''
    lst_new = []
    for i in lst:
        res = i << i
        lst_new.append(res)
    print(lst_new)
    # map改造
    '''参数和返回值return一定要写'''
    def func(n):
        return n << n 
        
    lst = [1,2,3,4]    
    it = map(func,lst)
    print(list(it))
    # lambda + map 
    it = map(lambda n : n << n , lst)
    print(list(it))

    3、{"a":97,"b":98,"c":99} 转换为 [97,98,99]

    dic = {"a":97,"b":98,"c":99}
    def func(lst):
        lst_new = []
        # 遍历列表
        for i in lst:
            # 通过键取值
            res = dic[i]
            # 把值追加到新的列表中
            lst_new.append(res)
        # 返回新列表
        return lst_new # [97,98,99]
    res = func(lst = ["a","b","c"])
    print(res)
    # 将键值对反转
    dic = {97:"a",98:"b",99:"c"}
    dic_new = {}
    for k,v in dic.items():
        dic_new[v] = k
    print(dic_new)
    
    lst = ["a","b","c"]
    lst_new = []
    # 遍历列表
    for i in lst:
        # 通过键取值
        res = dic_new[i]
        # 把值追加到新的列表中
        lst_new.append(res)
    # 返回新列表
    print(lst_new)
    # map改造
    def func(n):
        # 原字典
        dic = {97:"a",98:"b",99:"c"}
        # 新字典
        dic_new = {}
        # 遍历原字典
        for k,v in dic.items():
            # 更换键值对
            dic_new[v] = k
        print(dic_new) # {'a': 97, 'b': 98, 'c': 99}
        # 通过键来获取值
        return dic_new[n]
        
    lst = ["a","b","c"]
    it = map(func,lst)
    print(list(it))

    三、filter函数

    """
    filter(func,iterable)
        功能: 过滤数据
              return True  当前这个数据保留
              return False 当前这个数据舍弃
        参数:
            func : 自定义函数
            iterable : 可迭代型数据(容器类型数据,range对象,迭代器)
        返回值:
            迭代器
    """
    lst = [1,2,3,4,5,6,7,8,9,10]
    # 常规写法
    lst_new = []
    for i in lst:
        if i % 2 == 0:
            lst_new.append(i)
            
    print(lst_new)
    # filter改写
    def func(i):
        if i % 2 == 0:
            return True
        else:
            return False
    
    it = filter(func,lst)
    # (1) next
    res = next(it)
    print(res)
    
    # (2) for 
    print("<====>")
    for i in it:
        print(i)
        
    # (3) for + next
    it = filter(func,lst)
    for i in range(3):
        res = next(it)
        print(res)
        
    # (4) list强转    
    res = list(it)
    print(res)
    # filter + lambda 改写
    it = filter(lambda i : True if i % 2 == 0 else False , lst )
    print(list(it))

     四、reduce函数

    """
    reduce(func,iterable)
        功能:计算数据
            先把iterable中的前两个值拿出来,扔到func当中做运算,
            把计算的结果和iterable中的第三个元素在扔到func当中做运算,
            再把结果算出来,和第四个元素做运算,以此类推
            直到所有结果运算完毕.返回该结果
        参数:
            func : 自定义函数
            iterable : 可迭代型数据(容器类型数据,range对象,迭代器)
        返回值:
            计算之后的结果
    """

    1、lst = [5,4,8,8]  转换 整型5488

    # 常规写法
    # 方法一
    strvar = ""
    for i in lst:
        strvar += str(i)
    print(strvar , type(strvar))
    res = int(strvar)
    print(res , type(res))
    from functools import reduce
    from collections import Iterator,Iterable
    lst = [5,4,8,8]
    it = iter(lst)
    print(isinstance(it , Iterator))
    print(isinstance(it , Iterable))
    
    num1 = next(it)
    num2 = next(it)
    print(num1,num2)
    num = num1 * 10 + num2
    print(num) # 54
    
    for i in it:
        num = num * 10 + i # 54 * 10 + 8 => 548
    print(num, type(num))
    # reduce 改造
    def func(x,y):
        return x*10 + y
    lst = [5,4,8,8]
    res = reduce(func,lst)
    print(res , type(res))
    """
    # 代码解析:
    先拿出5和4两个元素,扔到func当中做运算,结果是54
    在拿54和8两个元素,扔到func当中做运算,结果548
    在拿548和8两个元素,扔到func当中做运算,结果5488
    返回最终的结果: 5488 程序结束
    """
    # 使用reduce + lambda改造
    res = reduce(lambda x,y:x*10+y,lst)
    print(res)

    2、"789" => 789 禁止使用int强转

    # "789" -> 数字7 数字8 数字9
    def func1(x,y):
        return x*10 + y
    def func2(n):
        dic = {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9}
        return dic[n]
    it = map(func2,"789") # [7,8,9]
    res = reduce(func1,it)
    print(res,type(res))

    五、sorted函数

    """
    sorted(iterable,key=函数,reverse=False)
        功能:排序
        参数:
            iterable:可迭代型数据(容器类型数据,range对象,迭代器)
            key     :指定自定义函数或内置函数
            reverse :代表升序或者降序 , 默认是升序(从小到大排序) reverse=False
        返回值:
            排序后的结果
    """
    # 1.默认是从小到大排序
    lst = [1,2,3,4,5,-90,-4,-1,100]
    res = sorted(lst)
    print(res)
    
    # 2.reverse 从大到小排序
    res = sorted(lst,reverse=True)
    print(res)
    
    # 3.指定函数进行排序
    # 按照绝对值排序 abs
    lst = [-10,-1,3,5]
    res = sorted(lst,key=abs)
    """
    -1  => abs(-1)  => 1
    3  => abs(3)  => 3
    5  => abs(5)  => 5
    -10 => abs(-10) => 10
    [-1, 3, 5, -10]
    """
    print(res)

    1、使用自定义函数进行排序

    lst = [19,21,38,43,55]
    def func(n):
        return n % 10
    lst = sorted(lst,key=func)
    print(lst)
    """
    21 => n % 10 => 1
    43 => n % 10 => 3
    55 => n % 10 => 5
    38 => n % 10 => 8
    19 => n % 10 => 9
    
    21 43 55 38 19
    """

    2、可迭代类型数据排序

    # 字符串
    container = "eadc"
    # 列表
    container = [19,21,38,43,55]
    # 元组
    container = (19,21,38,43,55)
    # 集合
    container = {19,21,38,43,55}
    # 字典 (排序的是字典的键)
    container = {"c":3,"a":1,"b":2}
    container = {"aa":3,"bb":2}
    print("<===>")
    res = sorted(container)
    print(res)

    3、sorted 和 sort 之间的区别

    # (1) sorted可以排序一切容器类型数据, sort只能排列表
    # (2) sorted返回的是新列表,sort是基于原有的列表进行修改
    # (3) 推荐使用sorted

    六、练习

    """
    # 1.用map来处理字符串列表,把列表中所有人都变成 leader ,比方alex_leader
    name = ['oldboy', 'alex', 'wusir']
    
    # 2.用map来处理下述 listvar ,要求得到新列表,每个元素名字加后面加_leader
    listvar = [{'name':'alex'},{'name':'wusir'}]
    
    # 3.用filter来处理,得到股票价格大于20的股票名字
    shares={
           'IBM':36.6,
           'Lenovo':23.2,
          'oldboy':21.2,
            'ocean':10.2,
        }
    
    # 4.有下面字典:
    portfolio=[
        {'name':'IBM','shares':100,'price':91.1},
        {'name':'AAPL','shares':20,'price':54.0},
        {'name':'FB','shares':200,'price':21.09},
        {'name':'HPQ','shares':35,'price':31.75},
        {'name':'YHOO','shares':45,'price':16.35},
        {'name':'ACME','shares':75,'price':115.65}
    ]
    # a.获取购买每只股票的总价格(乘积),迭代器中[9110.0, 1080.0 ,......]
    # b.用filter过滤出price大于100的股票。
    
    # 5.将listvar 按照列表中的每个字典的values大小进行排序,形成一个新的列表。
    listvar = [
        {'sales_volumn': 0},
        {'sales_volumn': 108},
        {'sales_volumn': 337},
        {'sales_volumn': 475},
        {'sales_volumn': 396},
        {'sales_volumn': 172},
        {'sales_volumn': 9},
        {'sales_volumn': 58},
        {'sales_volumn': 272},
        {'sales_volumn': 456},
        {'sales_volumn': 440},
        {'sales_volumn': 239}
    ]
    """
    def func(n):
        return n+"_leader"
        
    name = ['oldboy', 'alex', 'wusir']
    it = map(func,name)
    print(list(it))
    
    # lambda
    it = map(lambda n : n+"_leader",name)
    print(list(it))
    1
    def func(n):
        print(n) # {'name': 'alex'}
        return n["name"] + "_leader"
    
    listvar = [{'name':'alex'},{'name':'wusir'}]
    it = map(func,listvar)
    print(list(it))
    
    # lambda
    it = map(lambda n : n["name"] + "_leader" , listvar)
    print(list(it))
    2
    shares={
           'IBM':36.6,
           'Lenovo':23.2,
          'oldboy':21.2,
            'ocean':10.2,
        }
    def func(n):
        return shares[n] > 20
    
    it = filter(func,shares)
    print(list(it))
        
    # lambda
    it = filter(lambda n : shares[n] > 20 , shares)
    print(list(it))
    3
    portfolio=[
        {'name':'IBM','shares':100,'price':91.1},
        {'name':'AAPL','shares':20,'price':54.0},
        {'name':'FB','shares':200,'price':21.09},
        {'name':'HPQ','shares':35,'price':31.75},
        {'name':'YHOO','shares':45,'price':16.35},
        {'name':'ACME','shares':75,'price':115.65}
    ]
    # a.获取购买每只股票的总价格(乘积),迭代器中[9110.0, 1080.0 ,......]
    def func(n):
        return n["shares"] * n["price"]
         
    
    it = map(func,portfolio)
    print("<====>")
    print(list(it))
    4 (a)
    portfolio=[
        {'name':'IBM','shares':100,'price':91.1},
        {'name':'AAPL','shares':20,'price':54.0},
        {'name':'FB','shares':200,'price':21.09},
        {'name':'HPQ','shares':35,'price':31.75},
        {'name':'YHOO','shares':45,'price':16.35},
        {'name':'ACME','shares':75,'price':115.65}
    ]
    
    # b.用filter过滤出price大于100的股票
    def func(n):
        return  n["price"] > 100
        
    it = filter(func,portfolio)
    print(list(it))
    4 (b)
    # 5.将listvar 按照列表中的每个字典的values大小进行排序,形成一个新的列表。
    listvar = [
        {'sales_volumn': 0},
        {'sales_volumn': 108},
        {'sales_volumn': 337},
        {'sales_volumn': 475},
        {'sales_volumn': 396},
        {'sales_volumn': 172},
        {'sales_volumn': 9},
        {'sales_volumn': 58},
        {'sales_volumn': 272},
        {'sales_volumn': 456},
        {'sales_volumn': 440},
        {'sales_volumn': 239}
    ]
    def func(n):
        return n["sales_volumn"]
    print("<===>")
    lst = sorted(listvar,key=func)
    print(lst)
    5
  • 相关阅读:
    bootstrap-图片样式记录
    关于json数据中的多反斜杆转译--StringEscapeUtils.unescapeJava(踩过的坑)
    Nginx与tomcat组合的简单使用
    多进程之间的互斥信号量的实现(Linux和windows跨平台)
    跨平台(win和unix)的线程封装类
    linux 静态库、共享库
    WinMain与wWinMain,win32的字符集问题
    linux下添加动态链接库路径、动态库加载等方法
    win系统动态载入DLL所需要的三个函数详解(LoadLibrary,GetProcAddress,FreeLibrary)
    dll程序开发总结
  • 原文地址:https://www.cnblogs.com/kongxiangqun/p/13356539.html
Copyright © 2020-2023  润新知