当前位置:Gxlcms > Python > python生成器与迭代器的区别

python生成器与迭代器的区别

时间:2021-07-01 10:21:17 帮助过:62人阅读

对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()函数。iter()是python内置函数。 iter()函数会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内的元素。next()也是python内置函数。在没有后续元素时,next()会抛出一个StopIteration异常,通知for语句循环结束。

迭代器

迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。实际上,在使用next()函数的时候,调用的就是迭代器对象的_next_方法(Python3中是对象的_next_方法,Python2中是对象的next()方法)。所以,我们要想构造一个迭代器,就要实现它的_next_方法。但这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现_iter_方法,而_iter_方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的_iter_方法返回自身self即可。

一些术语的解释:

1,迭代器协议:对象需要提供next()方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代。
2,可迭代对象:实现了迭代器协议对象。list、tuple、dict都是Iterable(可迭代对象),但不是Iterator(迭代器对象)。但可以使用内建函数iter() ,把这些都变成Iterable(可迭代器对象)。
3,for item in Iterable 循环的本质就是先通过iter()函数获取可迭代对象Iterable的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束。

相关推荐:《Python视频教程》

Python自带容器对象案例:

  1. # 随便定义一个list
  2. listArray=[1,2,3]
  3. # 使用iter()函数
  4. iterName=iter(listArray)
  5. print(iterName)
  6. # 结果如下:是一个列表list的迭代器
  7. # <list_iterator object at 0x0000017B0D984278>
  8. print(next(iterName))
  9. print(next(iterName))
  10. print(next(iterName))
  11. print(next(iterName))#没有迭代到下一个元素,直接抛出异常
  12. # 1
  13. # 2
  14. # 3
  15. # Traceback (most recent call last):
  16. # File "Test07.py", line 32, in <module>
  17. # StopIteration

Python中一个实现了_iter_方法和_next_方法的类对象,就是迭代器,如下案例是计算菲波那切数列的案例

  1. class Fib(object):
  2. def __init__(self, max):
  3. super(Fib, self).__init__()
  4. self.max = max
  5. def __iter__(self):
  6. self.a = 0
  7. self.b = 1
  8. return self
  9. def __next__(self):
  10. fib = self.a
  11. if fib > self.max:
  12. raise StopIteration
  13. self.a, self.b = self.b, self.a + self.b
  14. return fib
  15. # 定义一个main函数,循环遍历每一个菲波那切数
  16. def main():
  17. # 20以内的数
  18. fib = Fib(20)
  19. for i in fib:
  20. print(i)
  21. # 测试
  22. if __name__ == '__main__':
  23. main()

解释说明:

在本类的实现中,定义了一个_iter_(self)方法,这个方法是在for循环遍历时被iter()调用,返回一个迭代器。因为在遍历的时候,是直接调用的python内置函数iter() ,由iter()通过调用_iter_(self)获得对象的迭代器。有了迭代器,就可以逐个遍历元素了。而逐个遍历的时候,也是使用内置的next()函数通过调用对象的_next_(self)方法对迭代器对象进行遍历。所以要实现_iter_(self)和_next_(self)这两个方法。

而且因为实现了_next_(self)方法,所以在实现_iter_(self)的时候,直接返回self就可以。

总结一句话就是:

在循环遍历自定义容器对象时,会使用python内置函数iter()调用遍历对象的_iter_(self)获得一个迭代器,之后再循环对这个迭代器使用next()调用迭代器对象的_next_(self) 。

注意点: _iter_(self)只会被调用一次,而_next_(self)会被调用 n 次,直到出现StopIteration异常。

生成器

作用:

延迟操作。也就是在需要的时候才产生结果,不是立即产生结果。

注意事项:

生成器是只能遍历一次的。
生成器是一类特殊的迭代器。

分类:

第一类:生成器函数:还是使用 def 定义函数,但是,使用yield而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。

  1. # 菲波那切数列
  2. def Fib(max):
  3. n, a, b = 0, 0, 1
  4. while n < max:
  5. yield b
  6. a, b = b, a + b
  7. n = n + 1
  8. return '亲!没有数据了...'
  9. # 调用方法,生成出10个数来
  10. f=Fib(10)
  11. # 使用一个循环捕获最后return 返回的值,保存在异常StopIteration的value中
  12. while True:
  13. try:
  14. x=next(f)
  15. print("f:",x)
  16. except StopIteration as e:
  17. print("生成器最后的返回值是:",e.value)
  18. break

第二类:生成器表达式:类似于列表推导,只不过是把一对大括号[]变换为一对小括号()。但是,生成器表达式是按需产生一个生成器结果对象,要想拿到每一个元素,就需要循环遍历。

如下案例加以说明:

  1. # 一个列表
  2. xiaoke=[2,3,4,5]
  3. # 生成器generator,类似于list,但是是把[]改为()
  4. gen=(a for a in xiaoke)
  5. for i in gen:
  6. print(i)
  7. #结果是:
  8. 2
  9. 3
  10. 4
  11. 5
  12. # 为什么要使用生成器?因为效率。
  13. # 使用生成器表达式取代列表推导式可以同时节省 cpu 和 内存(RAM)。
  14. # 如果你构造一个列表(list)的目的仅仅是传递给别的函数,
  15. # 比如 传递给tuple()或者set(), 那就用生成器表达式替代吧!
  16. #本案例是直接把列表转化为元组
  17. kk=tuple(a for a in xiaoke)
  18. print(kk)
  19. #结果是:
  20. (2, 3, 4, 5)
  21. # python内置的一些函数,可以识别这是生成器表达式,外面有一对小括号,就是生成器
  22. result1=sum(a for a in range(3))
  23. print(result1)
  24. # 列表推导式
  25. result2=sum([a for a in range(3)])
  26. print(result2)

区别:

生成器能做到迭代器能做的所有事,而且因为自动创建了 iter()和 next()方法,生成器显得特别简洁,而且生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出 StopIteration 异常。

以上就是python生成器与迭代器的区别的详细内容,更多请关注Gxlcms其它相关文章!

人气教程排行