美文网首页
python的迭代器、生成器和yield用法

python的迭代器、生成器和yield用法

作者: owolf | 来源:发表于2020-01-03 16:57 被阅读0次

    一、迭代器iterables

    image.png

    任何可以用 for in 来迭代读取的都是迭代容器,例如lists,strings,files.这些迭代器非常的便利,因为你可以想取多少便取多少,但是你得存储所有的值,其中很多值都完全没有必要每次都保持在内存中。range(1000)就默认生成一个含有1000个数的list了,所以很占内存。

    二、生成器Generators

    image.png
    小结:迭代器需要全部存储,比较占内存;生成器用一个生成一个,用完以后再删除。

    三、yield的用法

    带yield的函数是一个生成器,而不是一个函数了,当你调用这个函数的时候,你写在这个函数中的代码并没有真正的运行。这个函数仅仅只是返回一个生成器对象

    先把yield看做“return”,普通的return是什么意思,就是在程序中返回某个值,返回之后程序就不再往下运行了;接下来把再把它看做是生成器的一部分(带yield的函数才是真正的迭代器)

    def foo():
       print("starting...")
       while True:
          res = yield 4
          print("res:",res)
    g = foo()
    print(next(g))
    print("*"*20)
    print(next(g))
    

    输出结果:

    starting...
    4
    ********************
    res: None
    4
    

    我直接解释代码运行顺序,相当于代码单步调试:

    1.程序开始执行以后,因为foo函数中有yield关键字,所以foo函数并不会真的执行,而是先得到一个生成器g(相当于一个对象)

    2.直到调用next方法,foo函数正式开始执行,先执行foo函数中的print方法,然后进入while循环

    3.程序遇到yield关键字,然后把yield想想成return,return了一个4之后,程序停止,并没有执行赋值给res操作,此时next(g)语句执行完成,所以输出的前两行(第一个是while上面的print的结果,第二个是return出的结果)是执行print(next(g))的结果,

    4.程序执行print(""20),输出20个*

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

    6.程序会继续在while里执行,又一次碰到yield,这个时候同样return 出4,然后程序停止,print函数输出的4就是这次return出的4.

    再把结论说一遍:带yield的函数是一个生成器,而不是一个函数了,当你调用这个函数的时候,你写在这个函数中的代码并没有真正的运行。这个函数仅仅只是返回一个生成器对象,你可以用for循环来迭代这个对象。

    参考文献:https://blog.csdn.net/mieleizhi0522/article/details/82142856

    相关文章

      网友评论

          本文标题:python的迭代器、生成器和yield用法

          本文链接:https://www.haomeiwen.com/subject/tdazoctx.html