zoukankan      html  css  js  c++  java
  • python--生成器,生成器推导式, yield from

    一.生成器

      生成器的本质就是迭代器,它一个一个的创建对象.

      在python中有三种方式获取生成器:
    
        1.通过生成器函数
    
        2.通过各种推导式来实现生成器
    
        3.通过数据的类型转换也可以获取生成器

    二.生成器函数

      生成器函数中包含yield,返回数据和return差不多, return会立即结束这个函数的执行, yield 可以分段的执行一个函数

      生成器函数在执行的时候返回生成器,而不是直接执行此函数

      能向下执行的两个条件:  

        1.  __next__(),执行到下一个yield

        2.  send(),执行到下一个yield,给上一个yield位置传值

      注意:

        所有的生成器都是迭代器都可以使用for循环

        都可以使用list()函数来获取到生成器内所有的数据

        生成器中记录的代码而不是函数的运行

      优点: 节省内存, 生成器本身就是代码. 几乎不占用内存

      特点: 惰性机制, 只能向前. 不能反复

    def func():
        print('111')
        yield 222
    
    gen = func()  # 创建生成器.此时运行会把生成器函数中的代码记录在内存当中
    ret = gen.__next__()  # 当执行到__next__(),运行此空间中的代码,运行到yield结束
    print(ret)
    
    #结果:
    111
    222

      由于函数中存在了yield,那么这个函数就是一个生成器函数.这个时候,再执行这个函数的时候,就不再是函数的执行了,而是获取这个生成器,直接使用__next__()来执行

      从这里可以看到,yield和return的效果是一样的,区别是yield是分段来执行一个函数,而return是直接停止函数

    def func():
        print('111')
        yield 222
        print('333')
        yield 444
    gen = func()
    ret = gen.__next__()
    print(ret)
    
    ret2 = gen.__next__()
    print(ret2)
    
    ret3 = gen.__next__()  # 最后一个yield执行完毕.再次__next__()程序报错,也就是说,和return无关了
    print(ret3)
    
    #结果:
    111
    Traceback (most recent call last):
      File "D:/pyworkspace/练习.py", line 94, in <module>
    222
        ret3 = gen.__next__()
    333
    StopIteration
    444

      程序运行完最后一个yield,后面继续进行__next__() 程序会报错

      接下来我们来看send方法, send和__next__()一样都可以让生成器执行到下一个yield.

    def eat():
      print("我吃什什么啊")
      a = yield "馒头"
      print("a=",a)
      b = yield "大饼"
      print("b=",b)
      c = yield "韭菜盒子"
      print("c=",c)
      yield "GAME OVER"
    
    
    gen = eat() # 获取生成器
    ret1 = gen.__next__()
    print(ret1)
    ret2 = gen.send("胡辣汤")
    print(ret2)
    ret3 = gen.send("狗粮")
    print(ret3)
    ret4 = gen.send("猫粮")
    print(ret4)

      send和__next__()区别:
        1. send和next()都是让生成器向下走一次
        2. send可以给上一个yield的位置传递值, 不能给最后一个yield发送值. 在第一次执行生
     成器代码的时候不能使用send()

    生成器可以使用for循环来循环获取内部的元素

    def func():
        print('111')
        yield 222
        print('333')
        yield 444
        print('555')
        yield 666
    
    gen = func()
    for i in gen:
        print(i)
    
    #结果:
    111
    222
    333
    444
    555
    666

    三.列表推导式,生成器表达式以及其他推导式

    列表推导式:

      1.   列表推导式是通过一行来构建你要的列列表, 列表推导式看起来代码简单. 但是出现错误之后很难排查.

        列表推导式的常用写法:

          [ 结果 for 变量 in 可迭代对象]

    #给出一个列表,循环添加1到14
    lst = []
    for i in range(1, 15):
      lst.append(i)
    print(lst)
    
    替换成列表推导式:
    lst = [i for i in range(1, 15)]
    print(lst)

      2.  我们还可以对列表中的数据进行筛选
        筛选模式:
           [ 结果 for 变量 in 可迭代对象 if 条件 ]

    # 获取1-100内所有的偶数
    lst = [i for i in range(1, 100) if i % 2 == 0]
    print(lst)

    生成器表达式:

      生成器表达式和列表推导式的语法基本上是⼀样的. 只是把[]替换成()

    gen = (i for i in range(10))
    print(gen)
    结果:<generator object <genexpr> at 0x106768f10>

      打印的结果就是⼀一个生成器. 我们可以使用for循环来循环这个⽣成器:

    gen = ("麻花藤我第%s次爱你" % i for i in range(10))
    for i in gen:
      print(i)

    四. yield from

      yield from 是在Python3.3才出现的语法。所以这个特性在Python2中是没有的。

      yield from 后面需要加的是可迭代对象,它可以是普通的可迭代对象,也可以是迭代器,甚至是生成器。

    def func():
        lst = ["衣服%s" % i for i in range(500)]
        yield from lst # 可以把一个可迭代对象分别进行yield返回
    
        lst1 = ["%s" % i for i in range(18)]
        yield from lst1
    
    
    gen = func()
    print(gen.__next__())
    print(gen.__next__())
  • 相关阅读:
    Window 下配置ChromeDriver(简单4步完成)[转]
    selenium之 chromedriver与chrome版本映射表(更新至v2.46)[转]
    学习网站
    如何理解python中的类和方法(转)
    面试题整理20191127
    mysql 慢查询
    python学习--代码组织实例
    ubuntu下安装Matlab
    SkinPP for VC
    C++中的4个类型转换关键字
  • 原文地址:https://www.cnblogs.com/robertx/p/10102299.html
Copyright © 2011-2022 走看看