• 迭代器,生成器函数和各种推导式


    一.迭代器

    • 一个数据类型中包含了__iter__函数表示这个数据是可迭代的
    • 特征:

        1. 省内存
        2. 惰性机制
        3. 只能向前. 不能后退

    • 作用:统一了各种数据类型的遍历
    • dir(数据类型): 

        dir() 可以帮我们查看xxx数据能够执行的操作

    例如

    print(dir(str)) # 有__iter__,是可迭代对象
    
    print(dir(int)) # 没有__iter__,不是可迭代对象
    
    print(dir(list)) # 有__iter__,是可迭代对象
    
    print(dir(dict)) # 有__iter__,是可迭代对象
    
    print(dir(bool)) # 没有__iter__,不是可迭代对象
    # 共性:所有带有__iter__的东西都可以进行for循环, 带有__iter__的东西就是可迭代对象

      

    • 判断迭代器和可迭代对象的方案(野路子)

        __iter__ 可迭代的

        __iter__     __next__ 迭代器

    • 判断迭代器和可迭代对象的方案(官方)

        from collections import Iterable, Iterator

        isinstance(对象, Iterable) 是否是可迭代的

        isinstance(对象, Iterator) 是否是迭代器

    #借助于两个模块 Iterator迭代器, Iterable可迭代的
    from collections import Iterable, Iterator
    lst = [1,2,3]
    print(lst.__next__())
    print(isinstance(lst, Iterable)) # xxx是否是xxx类型的. True
    print(isinstance(lst, Iterator)) # xxx是否是xxx迭代器. False
    
    
    it = lst.__iter__()  # 迭代器一定可迭代,  可迭代的东西不一定是迭代器
    print(isinstance(it, Iterable)) # xxx是否是xxx类型的. True
    print(isinstance(it, Iterator)) #  xxx是否是xxx迭代器. True
    
    • 迭代器一定可迭代,  可迭代的东西不一定是迭代器
    • 模拟for循环
    # 模拟for循环 for el in lst:
    lst=[1,2,3] it = lst.__iter__() # 获取到迭代器 while 1: # 循环 try: # 尝试 el = it.__next__() # 那数据 print(el) except StopIteration: # 出了错误, 意味着数据拿完了 break # 结束循环

      

    二.生成器定义与获取

    •   定义:生成器实质就是迭代器.
    • 在python中有三种方式来获取生成器:
      1.  通过生成器函数
      2. 通过各种推导式来实现生成器
      3. 通过数据的转换也可以获取生成器
    def func():
        print("我叫周润发")
        yield "林志玲"   # yield表示返回. 不会终止函数的执行
    ret = func() # 执行函数, 此时没有运行函数. 此时我们拿到的是生成器
     print("返回值是", ret) # <generator生成器 object func at 0x0000000009E573B8>
    # 执行到下一个yield
    print(ret.__next__()) # 第一次执行__next__此时函数才开始执行
    print(ret.__next__()) # 执行到下一个yield
    print(ret.__next__()) # StopIteration
    
    • 我们可以看到, yield和return的效果是一样的. 有什么区别呢? 

            yield是分段来执行一个函数. return是直接停止执行函数.

    • 生成器函数在执行的时候返回生成器. 而不是直接执行此函数
    • 能向下执行的两个条件:

          __next__(), 执行到下一个yield      
       send(), 执行到下一个yield, 给上一个yield位置传值
    def func():
        print("韭菜盒子")
        a = yield "韭菜鸡蛋"
        print("a", a)
        b = yield "韭菜西红柿"
        print("b", b)
        c = yield "火烧"
        print("c", c)
    gen = func()#获取生成器
    print(gen.__next__()) # 执行到第一个yield
    print(gen.send("篮球")) # 给上一个yield位置传值,即给a一个值'篮球'
    print(gen.send("足球")) # 给上一个yield位置传值,即给b一个值'足球'
    • 所有的生成器都是迭代器都可以直接使用for循环
    • 都可以使用list()函数来获取到生成器内所有的数据
    • 生成器中记录的是代码而不是函数的运行

      def func():
          print("值 1")
          yield "值2"
      gen= func()#获取生成器
    • gen = func() # 创建生成器. 此时运行会把生成器函数中的代码记录在内存
    • 当执行到__next__(), 运行此空间中的代码, 运行到yield结束.
    • 优点: 节省内存, 生成器本身就是代码. 几乎不占用内存
    • 特点: 惰性机制, 只能向前. 不能反复

    三.生成器表达式

      (结果 for循环 if...)

    g =(i for i in range(10))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
    print(iter(g))

    四.各种推导式 

    • 列表推导式 [结果 for循环 if...]
    lst = [i for i in range(1, 19)]
    print(lst)
    • 字典推导式 {结果(k:v) for循环 if...}
    • 集合推导式 {结果(k) for循环 if...}

      元组没有推导式,小括号括起来的是生成器表达式

    补充:yield from

    def func():
    lst = ["衣服%s" % i for i in range(500)] yield from lst # 可以把一个可迭代对象分别进行yield返回
    lst1 = ["python%s" % i for i in range(18)] yield from lst1 gen = func() print(gen.__next__()) print(gen.__next__())
    lst全部返回完后才会返回lst1,不会交叉返回
    lst = ["衣服%s" % i for i in range(500)]
       yield from lst
    这个就相当于
    for i in range(500):
        yield "衣服%s" % i
    

     

      

  • 相关阅读:
    find 以及linux 和windows 文件互传
    27 关于Object类 -- equals()
    26 super关键字
    25 访问修饰符限定词
    24 继承 子类中方法重写
    23 static 关键字
    22 包(package)来解决不同包下同名文件的冲突问题
    21 封装(get,set方法)
    20 带参构造方法(this关键字)
    19 无参构造方法
  • 原文地址:https://www.cnblogs.com/l1222514/p/10103539.html
Copyright © 2020-2023  润新知