zoukankan      html  css  js  c++  java
  • 生成器

    生成器

    生成器

    生成器仅仅保存了一套生成数值或者对象的算法,并且没有让这个算法现在就开始执行,而是我什么时候调它,它什么时候开始计算一个新的值,并给你返回。

    为何要用生成器

    存储海量的数据会占用内存资源,如果我们可以根据算法推算后面的数据,什么时候需要的时候就去生成,这样将极大地减少内存占用。

    创建生成器

    1. 列表生成式的[]改成()

    L = [x * x for x in range(10)]
    print(L)
    
    G = (x * x for x in range(10))
    print(G)
    print(next(G)
    

    执行结果

    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    <generator object <genexpr> at 0x02739DB0>
    0
    

    next是生成器能迭代的关键,next(G)等价于G.__next__(),调用他就生成一个新的对象并返回。

    2. yield

    在函数里面有yield关键字,函数就变成了一个生成器。当调用next()函数时,就相当于生成下一个对象(统称),这一次next开始的地方是接着上一次next停止的地方执行的,即yield之后继续执行,到yield处返回生成的对象。

    例子

    def fun():
        print('run fun')
        while True:
            rtn = yield 6
            print('rtn:',rtn)
    g = fun()
    print(g)
    print(next(g))
    print('-------')
    print(next(g))
    print('------------')
    print(next(g))
    

    执行结果

    <generator object fun at 0x0278CDB0>
    run fun
    6
    -------
    rtn: None
    6
    ------------
    rtn: None
    6
    

    分析

    1. 程序开始执行以后,因为fun函数中有yield关键字,所以先得到一个生成器对象g,由print(g)可以看出他是一个生成器对象

    2. 直到调用next方法,fun函数正式开始执行,先执行fun函数中的print方法,然后进入while循环(++生成器都有一个while True循环以此不断生成对象并返回++)

    3. 程序遇到yield关键字,把yield想象成return,return了一个6之后,程序停止,并没有执行赋值操作,此时next(g)语句执行完成,返回6,是执行print(next(g))的结果,

    4. 程序执行print,,输出---

    5. 又开始执行下面的print(next(g)),这个时候是从刚才那个next程序停止的地方开始执行,也就是要执行rtn的赋值操作,这时候要注意,这个时候赋值操作的右边是没有值的(因为刚才那个是return出去了,并没有给赋值操作的左边传参数),所以这个时候rtn赋值是None,所以接着下面的输出就是rtn:None,继续走while循环

    6. 又一次碰到yield,这个时候同样return 出6,然后程序停止,print函数输出的6就是这次return的返回值.

    7. 继续5-6

    再看

    def fun():
        print('run fun')
        while True:
            rtn = yield 6
            print('rtn:',rtn)
    g = fun()
    print(g)
    print(next(g))
    print('-------')
    print(g.send(True))
    print('------------')
    print(g.send('赋值操作'))
    

    执行结果

    <generator object fun at 0x029AEAB0>
    run fun
    6
    -------
    rtn: True
    6
    ------------
    rtn: 赋值操作
    6
    
    

    这次的rtn为什么有值了呢?

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

    send()干了两件事情:

    1. 发送一个参数做赋值操作
    2. 函数内部包含执行next(),yield 6 返回
  • 相关阅读:
    vscode task 与 linux shell编程小记
    Python并行计算专题
    分类任务评价指标(Accuracy / Precision / Recall / F1 / ROC / AUC)
    JAVA笔记 10.04
    MySQL5.7忘记密码 Linux
    MYSQL 获取最近多少天时间列表
    Volatile 关键字的原理和实现
    安装正常APP时被小米提醒是诈骗APP不允许安装的问题
    【瞎口胡】网络流基础
    题解 Luogu P4774 [NOI2018]屠龙勇士
  • 原文地址:https://www.cnblogs.com/yuliangkaiyue/p/12147617.html
Copyright © 2011-2022 走看看