• Python——迭代器和生成器


    1. 迭代器

    (1)迭代器——iterator

      [].__iter__(),通过__next__方法就可以从迭代器中一个一个取值

    (2)可迭代的——iterable

      只要含有__iter__方法的都是可迭代的

    (3)相关协议

      可迭代协议 —— 只要含有__iter__方法的都是可迭代的,可以被for循环的都是可迭代的

      迭代器协议 —— 内部含有__next__和__iter__方法的就是迭代器

    (4)是否是迭代器的判断

      以下几种情况可能是迭代:

      <1>.iterator——print([].__iter__()) #<list_iterator object at 0x00000277E7E0CE10>

      <2>.可迭代对象——print(range(10))

      <3>.直接给内存地址

      只有 是可迭代对象的时候,才能有for循环——for循环其实就是在使用迭代器

      遇到新变量,不确定能不能for循环的时候,可以判断其是否可迭代

    (5)迭代器和可迭代的对比

      迭代器一定可迭代,可迭代的不一定是迭代器

      可迭代的.__iter__()方法就可以得到一个迭代器

      迭代器中的__next__方法可以一个一个的获取值

    (6)迭代器的好处

      <1>从容器类型中一个一个的取值,会把所有值都取到

      <2>节省内存空间

        迭代器并不会在内存中占用一大块内存,而是随着循环每次生成一个,或者每次next每次生成一个

    2. 生成器

    (1)本质

      生成器的本质就是迭代器

    (2)生成器函数

      含有关键字yield的函数就是生成器函数,关键字yield只能写在函数内部,不会结束函数,且不能与return共用

    def generator():
        print(1)
        yield 'a'
        print(2)
        yield 'b'
    # 生成器函数:执行之后会得到一个生成器作为函数的返回值
    ret = generator()
    print(ret)
    print(ret.__next__())
    print(ret.__next__())

    运行结果:

     

    特点:

      调用函数的时候函数不执行,返回一个生成器
      每次调用next方法的时候会取到一个值
      直到取完最后一个,在执行就会报错

    (3)各种推导式

    表达式格式:

      遍历操作:[每一个元素/和元素相关的操作 for 元素 in 可迭代数据类型]

      筛选功能:[满足条件的元素相关的操作 for 元素 in 可迭代数据类型]

      <1> 生成器表达式

    老母鸡 = ('鸡蛋%s'%i for i in range(10))    #生成器表达式
    print(老母鸡)
    forin 老母鸡:
        print(蛋)
    # 面试——取一个next,for循环执行一次
    g = (i*i for i in range(10))
    print(g.__next__())    # 1:取一个next,for循环执行一次
    print(g.__next__())    # 4:取一个next,for循环执行一次
    print(g.__next__())    # 9:取一个next,for循环执行一次
    print(g.__next__())    # 16:取一个next,for循环执行一次

      <2> 列表推导式

    # 30以内所有能被3整除的数
    ret = [i for i in range(30) if i%3 == 0]
    print(ret)  #[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
    
    # 30以内所有能被3整除的数的平方
    ret = [i*i for i in range(30) if i%3 == 0]
    print(ret)  #[0, 9, 36, 81, 144, 225, 324, 441, 576, 729]
    
    #找嵌套列表中名字含有两个e的名字
    names = [['tom','billy','jefference','aneedhg'],
             ['alice','jill','ehdjbse']]
    ret = [name for lst in names for name in lst if name.count('e') == 2]
    print(ret)  #['aneedhg', 'ehdjbse']

      <3> 字典推导式

    # 将一个字典的key和value对调
    mcase = {'a':10,'b':34}
    mcase_frequency = {mcase[k]:k for k in mcase}
    print(mcase_frequency)  #{10: 'a', 34: 'b'}
    
    # 合并大小写对应的value的值,将k统一写成小写
    mcase = {'a':10,'b':34,'A':7,'Z':3}
    mcase_frequency = {k.lower():mcase.get(k.lower(),0 )+mcase.get(k.upper(),0)for k in mcase}
    print(mcase_frequency)  #{'a': 17, 'b': 34, 'z': 3}

      <4> 集合推导式

    # 计算列表中每个值的平方(集合推导式自带结果去重功能)
    squared = {x**2 for x in [1,-1,2]}
    print(squared)  #{1, 4}

    生成器表达式和其他各种表达式的区别:

      括号不一样

      返回值不一样(生成器表达式几乎不占用内存)

    (4)生成器的优点

      延迟计算,一次返回一个结果

     

    长得丑就应该多读书。我爱学习,只爱学习,最爱学习!
  • 相关阅读:
    程序员都遇到过哪些误解?
    云原生系列5 容器化日志之EFK
    云原生系列4 批量定时更新本地代码库
    云原生系列3 pod核心字段
    云原生系列2 部署你的第一个k8s应用
    云原生系列1 pod基础
    项目总结二:使用分布式存储读写分离功能应要注意的问题
    项目总结一:HttpClient DelegatingHandler管道扩展 生命周期问题
    Java 反编译工具的使用与对比分析
    如何使用 Github Actions 自动抓取每日必应壁纸?
  • 原文地址:https://www.cnblogs.com/xc-718/p/9700616.html
Copyright © 2020-2023  润新知