分享

Python中生成器的原理及用法

 禁忌石 2022-04-15

生成器使用总结: 
1.生成器的好处是可以一边循环一边进行计算,不用一下子就生成一个很大的集合,占用内存空间。生成器的使用节省内存空间。 
2.生成器保存的是算法,而列表保存的计算后的内容,所以同样内容的话生成器占用内存小,而列表占用内存大。每次调用 next(G) ,就计算出 G 的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出 StopIteration 的异常。 
3.使用for 循环来遍历生成器内容,因为生成器也是可迭代对象。通过 for 循环来迭代它,不需要关心 StopIteration 异常。但是用for循环调用generator时,得不到generator的return语句的返回值。如果想要拿到返回值,必须用next()方法,且捕获StopIteration错误,返回值包含在StopIteration的value中。 
4.在 Python 中,使用了 yield 的函数都可被称为生成器(generator)。生成器是一个返回迭代器的函数,只能用于迭代操作。更简单点理解生成器就是一个迭代器。 
5.一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,保存当前所有的运行信息,并返回一个迭代值,下次执行next() 方法时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造中的位置。

当然其实平常很少用到next(),我们直接用for循环就可以遍历一个generator,其实for循环的内部实现就是不停调用next()。

可迭代对象(Iterable)和迭代器(Iterator)的概念:

可迭代对象(Iterable)

可以直接作用于for循环的对象统称为可迭代对象:Iterable。包括集合数据类型(list、tuple、dict、set、str等)和生成器(generator)。

迭代器:Iterator

它表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。 
把list、dict、str等Iterable变成Iterator可以使用iter()函数:

生成器(generator)本身就是一个迭代器;

list、dict、str等可迭代对象(Iterable) 要使用iter()函数才能变成迭代器(Iterator)

生成器有两种:       

生成器函数        

生成器表达式 


生成器函数的定义:  
      含有yield语句的函数是生成器函数,此函数被调用将会返回一个生成器对象

简单来说:只要在def中有yield关键字的 就称为 生成器

      yield翻译为产生(或生成)

说明:
            yield 用于def函数中,目的是将此函数用生成器函数使用
            yield 用来生成数据,供迭代器和next(it)函数使用

  1. def myyield():
  2. print('即将生成2')
  3. yield 2
  4. print('即将生成3')
  5. # return '在生成3之前用return返回' 将会发生异常
  6. yield 3
  7. print('即将生成4')
  8. yield 4
  9. print('即将生成5')
  10. yield 5
  11. print('生成器生成结束')
  12. yield
  13. #for x in myyield():
  14. # print(x)
  15. # 调用生成器函数来创建一个生成器,此生成器能生成 2,3,4,5
  16. gen = myyield()
  17. it = iter(gen) #用生成器拿到对应的迭代器
  18. print(next(it)) #此时生成器函数才开始执行,并遇到yield停止 2
  19. print(next(it)) #访问迭代器 3
  20. print(next(it)) #4
  21. print(next(it)) #5
  22. print(next(it)) #生成器生成结束

生成器表达式:

语法:

把一个列表生成式的[ ]改成 (),就创建了一个generator:

(表达式 for 变量 in 可迭代对下哪个 [if 真值表达式])
        作用:
            用推导式形式创建一个新的生成器
        说明:
            if子句可以省略

  1. gen = (x**2 for x in range(1,5))
  2. it = iter(gen)
  3. print(next(it)) #1
  4. print(next(it))
  5. print(next(it)) #9
  6. print(next(it)) #16
  7. print(next(it)) #StopInteration

生成器表达式和列表推导式的区别: 生成器表达式是现用现生成,列表推导式是一次生成静态数据

  1. #列表推导式
  2. l = [2,3,5,7]
  3. l2 = [x ** 2 + 1 for x in l]
  4. it = iter(l2)
  5. print(next(it)) # 5
  6. l[1] = 30
  7. print(next(it)) # 10
  8. #生成器表达式
  9. l = [2,3,5,7]
  10. gen = (x ** 2 + 1 for x in l)
  11. it = iter(gen)
  12. print(next(it)) #5
  13. l[1] = 30
  14. print(next(it)) #901

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多