python——iterator迭代器|iterator详解——20140918|

本文深入探讨了Python中的迭代器与for循环机制,详细解释了如何在各种容器上遍历元素,以及如何实现自定义迭代器。通过实例演示,帮助读者理解Python的迭代协议及其应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

-----------------------------------------------------------------------------前言----------------------------------------------------------------------------------

  • python中的for循环可以在各种容器container上遍历所有可用元素。
  • 一个类里面,如果实现了  __iter__ 这个函数, 那这个类就是 “iterable”。
  • 如果它还实现了 next ( self ) ,那它就称为 iterator。

------------------------------------------------------------------------------正文-------------------------------------------------------------------------------------

我们都知道,Python有for循环。我们可以用for循环在各种容器container上遍历其所有可用的元素。
比如:
在列表(list)上遍历:

  1. >>> for i in [1, 2, 3]:
  2. ... print i
  3. ...
  4. 1
  5. 2
  6. 3

在字符串(string)上遍历:

  1. >>> for i in 'iter':
  2. ... print i
  3. ...
  4. i
  5. t
  6. e
  7. r

除此之外,还可以在元组(tuple),字典(dictionary)和文件(file)上遍历。这些遍历操作涉及到
同一个概念,那就是Python的迭代器(iterator)。维基百科中是这样定义迭代器的: 在面向对象的
程序设计语言
中,迭代器(iterator)是一个对象,这个对象可以让程序员在容器(container)上遍历。
Python中的迭代器(iterator)则是实现了迭代协议的对象。迭代协议由下面的两种方法组成,实现了
这两种方法就是实现了迭代协议。


1、__iter__(): 返回iterator对象本身。
2、next(): 每当next()方法被调用时,返回下一个值直到StopIteration的异常被抛出【1】

在Python里,iterator主要用于for循环。首先,我们来看一段代码:

  1. >>> lst = ['a', 'b', 'c', 'd', 'e']
  2. >>> for i in lst:
  3. ... print i
  4. ...
  5. a
  6. b
  7. c
  8. d
  9. e
  10. >>> lst_iter = iter(lst)
  11. >>> for i in lst_iter:
  12. ... print i
  13. ...
  14. a
  15. b
  16. c
  17. d
  18. e
  19. >>> type(lst_iter)
  20. <type 'listiterator'>

对于container类型【2】(列表是典型的container),可以直接用于for循环进行遍历。而将列表转化成
迭代器(iterator)进行遍历,效果似乎一样。
为什么两种方法都可以呢?Python到底是怎样遍历一个container的呢?前面提到Python中的迭代器
(iterator)实现两种方法分别是__iter__()和next(),Python正是通过调用这两种方法来实现遍历的。
首先,当Python在执行for循环时,会先调用container的__iter__()方法【3】 来获得container的迭代器
(iterator),其实就是将container转化成迭代器(iterator)。然后它会重复调用迭代器(iterator)的
next()方法,直到迭代器(iterator)抛出StopIteration的异常。一旦这个异常抛出,for循环就结束了。
看下面的代码,和上面的两种方法同样的结果。

  1. >>> _lst_iter = lst.__iter__() # 返回lst的iterator
  2. >>> for i in _lst_iter:
  3. ... print i
  4. ...
  5. a
  6. b
  7. c
  8. d
  9. e
  10. >>> type(_lst_iter)
    <type 'listiterator'>

在Python的内置数据类型中,list,tuple,dictionary,set都是container且都可以直接用于for循环。

  1. >>> s = {'a', 'b', 'c'}   # set
  2. >>> s
  3. set(['a', 'c', 'b'])
  4. >>> s.__iter__()
  5. <setiterator object at 0x7fac6c6f3280>
  6. >>> t = ('a', 'b', 'c')   # tuple
  7. >>> t
  8. ('a', 'b', 'c')
  9. >>> t.__iter__()
  10. <tupleiterator object at 0x7fac6c6fb490>
  11. >>> d = {1: 'a', 2: 'b', 3: 'c'}   # dict
  12. >>> d
  13. {1: 'a', 2: 'b', 3: 'c'}
  14. >>> d.__iter__()
  15. <dictionary-keyiterator object at 0x7fac6c6def70>
  16. >>>

上面的代码可以看出,这四种container都有__iter__(),一般把这种拥有__iter__()方法的container
叫做iterable。但是要注意,container和iterator的__iter__()方法虽然同名,但是返回的对象是不一样
的。container的__iter__()返回的是一个iterator对象,而iterator的__iter__()返回的是它自己,即
iterator对象本身。以一个list为例:

  1. >>> a = [1, 2, 3]     # list container
  2. >>> b = a.__iter__()  # listiterator
  3. >>> a is a.__iter__()
  4. False
  5. >>> b is b.__iter__()
  6. True
  7. >>>

除了Python内置的iterator,用户也可以通过实现迭代协议定义自己的iterator。自定义iterator,很显然是要实现
__iter__()和next()方法。例如我们定义一个偶数迭代器。

  1. class EvenIterators(object):
  2.     
  3.     def __init__(self, n):
  4.         self.stop = n
  5.         self.value = -2
  6.     
  7.     def __iter__(self):
  8.         return self
  9.     
  10.     def next(self):
  11.         if self.value + 2 > self.stop:
  12.             raise StopIteration
  13.         self.value += 2
  14.         return self.value

  15. >>> from iterator import EvenIterators
  16. >>> even_iter = EvenIterators(5)
  17. >>> even_iter.next()
  18. 0
  19. >>> even_iter.next()
  20. 2
  21. >>> even_iter.next()
  22. 4
  23. >>> even_iter.next()
  24. Traceback (most recent call last):
  25.   File "<stdin>", line 1, in <module>
  26.   File "iterator.py", line 18, in next
  27.     raise StopIteration
  28. StopIteration
  29. >>> for e in EvenIterators(5):
  30. ... print e
  31. ...
  32. 0
  33. 2
  34. 4
  35. >>> list(EvenIterators(9))
  36. [0, 2, 4, 6, 8]
  37. >>>

上面的EvenIterators类实现了一个偶数迭代器。从这个例子我们可以看出,只要我们实现了迭代协议,即
方法__iter__()和next(),我们就实现了iterator。

注:

【1】当所有可用的值都被遍历后,StopIteration才会被抛出。
【2】In computer science, a container is a class, a data structure, or an abstract data type (ADT) whose instances are
        collections of other objects. In other words; they are used for storing objects in an organized way following specific
        access rules. The size of the container depends on the number of the objects (elements) it contains. (Wikipedia)
【3】如果一个container是iterable,那么这个container拥有__iter__()方法,此方法将转化container成iterator。

 

-------------------------------------------------------------------------------------------后记---------------------------------------------------------------------------

 

转载于:https://www.cnblogs.com/Simon-xm/p/3898755.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值