当前位置:   article > 正文

Python中的iterator——yield和__iter___yield __iter

yield __iter

本文代码较多,建议阅读时间5分钟,并且注重理论与实践相结合

原文选自菜鸟教程可以点击阅读原文


举个栗子:斐波那契数列

斐波那契数列是一个简单的递归数列,除了第一个第二个外,其他都可由任意两个数组成。

Eg1.简单输出前N个数:

  1. def fab(max):
  2. n,a,b = 0,0,1
  3. while n < max:
  4. print(b)
  5. a ,b = b ,a+b
  6. n = n+1
  7. fab(5)

Eg2.使用列表(提高函数的复用性):

  1. def fab(max):
  2. n , a , b = 0,0,1
  3. L = []
  4. while n<max:
  5. L.append(b)
  6. a,b = b,a+b
  7. n = n+1
  8. return L
  9. for n in fab(5):
  10. print(n)

Eg3.支持iterator的class类:

  1. class Fab(object):
  2. def __init__(self,max):
  3. self.max = max
  4. self.n,self.a,self.b = 0,0,1
  5. def __iter__(self):
  6. return self
  7. def __next__(self):
  8. if self.n<self.max:
  9. r = self.b
  10. self.a ,self.b = self.b ,self.a+self.b
  11. self.n = self.n+1
  12. return r
  13. raise StopIteration
  14. for i in Fab(5):
  15. print(i)

Eg4.主角yield:

  1. def fab(max):
  2. n,a,b = 0,0,1
  3. while n<max:
  4. yield b
  5. a,b = b,a+b
  6. n = n+1
  7. for i in fab(5): print(i)

打印输出:

11235

简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。


fab的工作流程:

  1. >>> f = fab(5)
  2. >>> f.next()#Python2的写法
  3. Traceback (most recent call last):
  4. File "<pyshell#101>", line 1, in <module>
  5. f.next()
  6. AttributeError: 'generator' object has no attribute 'next'
  7. >>> f.__next__()#Python3的写法
  8. 1
  9. >>> f.__next__()
  10. 1
  11. >>> f.__next__()
  12. 2
  13. >>> f.__next__()
  14. 3
  15. >>> f.__next__()
  16. 5
  17. >>> f.__next__()
  18. Traceback (most recent call last):
  19. File "<pyshell#107>", line 1, in <module>
  20. f.__next__()
  21. StopIteration

Eg5.判断fab是否是一个特殊的generator函数?

  1. >>> from inspect import isgeneratorfunction as isg
  2. >>> isg(fab)
  3. True

Eg6.类的定义与实例

  1. >>> import types
  2. >>> isinstance(fab,types.GeneratorType)
  3. False
  4. >>> isinstance(fab(5),types.GeneratorType)
  5. True

证明了fab是无法迭代的,fab(5)可以

>>> from collections import Iterable>>> isinstance(fab,Iterable)False>>> isinstance(fab(5),Iterable)True

Eg7.每次调用fab函数都会生成一个新的generator,各实例互不影响:

  1. >>> f1 = fab(3)>>> f2 = fab(5)
  2. >>> print('f1:',f1.__next__())
  3. f1: 1
  4. >>> print('f2:',f2.__next__())
  5. f2: 1
  6. >>> print('f1:',f1.__next__())
  7. f1: 1
  8. >>> print('f2:',f2.__next__())
  9. f2: 1
  10. >>> print('f1:',f1.__next__())
  11. f1: 2
  12. >>> print('f2:',f2.__next__())
  13. f2: 2
  14. >>> print('f2:',f2.__next__())
  15. f2: 3
  16. >>> print('f2:',f2.__next__())
  17. f2: 5

http://www.runoob.com/w3cnote/python-yield-used-analysis.html


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/145408
推荐阅读
相关标签
  

闽ICP备14008679号