|
|
51CTO旗下网站
|
|
移动端

3.2.1 迭代器(1)

《自学Python:编程基础、科学计算及数据分析》第3章Python 进阶,在本章中,我们将学习 Python的一些进阶用法,包括函数的进阶,迭代器、生成器、装饰器、上下文管理器的使用,以及 Python中的变量作用域。本节为大家介绍迭代器。

作者:李金来源:机械工业出版社|2018-05-04 13:29

3.2 迭代器与生成器

3.2.1 迭代器(1)

1.迭代器的规则Python中的容器类型通常包含一个迭代器(Iterator)帮助它们支持 for循环的操作。这些容器类型需要实现一个.__iter__()方法返回相应的迭代器:

  1. <container>.__iter__() 

常见的容器类型,如列表、集合、字典、元组等,都有一个对应的迭代器:

  1. In [1]: [1, 2, 3].__iter__()   
  2. Out[1]: <listiterator at 0x47c2898>   
  3. In [2]: {1, 2, 3}.__iter__()   
  4. Out[2]: <setiterator at 0x47c3318>   
  5. In [3]: {1:1, 2:2}.__iter__()   
  6. Out[3]: <dictionary-keyiterator at 0x47b89f8>   
  7. In [4]: (1, 2, 3).__iter__()   
  8. Out[4]: <tupleiterator at 0x47ea588> 

迭代器对象支持.next()方法,该方法返回容器中被迭代到的下一个元素。例如,对于列表的迭代器。

  1. In [5]: x = [2, 4, 6]   
  2. In [6]: i = x.__iter__() 

第一次调用.next()方法,返回第一个元素2:

  1. In [7]: i.next()   
  2. Out[7]: 2 

再次调用.next()方法时,返回可迭代对象的下一个元素:

  1. In [8]: i.next()   
  2. Out[8]: 4   
  3. In [9]: i.next()   
  4. Out[9]: 6 

迭代器是一种“一次性消费品”,迭代完最后一个元素后,调用.next()方法不会回到开头,而是抛出一个StopIteration异常:

  1. In [10]: i.next()  
  2. -----------------------------------------------------------------------  
  3. StopIteration Traceback (most recent call last)  
  4. <ipython-input-10-e590fe0d22f8> in <module>()  
  5. ----> 1 i.next()  
  6. StopIteration: 

for循环正好可以利用迭代器的这种性质。

当我们对一个容器类型进行循环时,Python首先使用它的.__iter__()方法得到它的迭代器,然后不断调用迭代器的.next()方法,在抛出StopIteration异常后停止循环。

迭代器对象本身也有一个.__iter__()方法,这个方法必须返回迭代器本身:

  1. In [11]: i.__iter__() is i   
  2. Out[11]: True 

有一些函数返回的结果是迭代器对象,例如:

  1. In [12]: reversed(x)   
  2. Out[12]: <listreverseiterator at 0x49327f0>  

2.自定义迭代器

对于一个迭代器来说,它需要实现两个方法:

z.__iter__()方法,返回迭代器自身;

.next()方法,对内容进行迭代,当内容被迭代完时,抛出一个StopIteration异常。实现了这两个方法的自定义类型都可以称为一个迭代器。

我们仿照函数reversed()的功能,来定义一个将列表反序的自定义迭代器。自定义类型使用关键字class定义。按照迭代器的定义要求,需要实现的基本结构如下:

  1. class Reverse(object):  
  2. def __init__(self, ...):  
  3. ...  
  4. def __iter__(self):  
  5. return self  
  6. def next(self):  
  7. ...  
  8. raise StopIteration 

其中,self表示自定义对象本身,.__init__()是自定义类型中一个特殊的方法,用来初始化定义的类型。

我们的迭代器需要接受一个列表进行初始化,因此.__init__()方法接受一个列表 x作为参数,并让对象的.seq属性存储列表x,.idx属性存储列表 x的长度:

  1. def __init__(self, x):  
  2. self.seq = x 
  3. self.idx = len(x) 

对于.__iter__()方法,只需要返回这个对象本身即self:

  1. def __iter__(self):  
  2. return self 

对于.next()方法,我们利用.idx属性来判断当前迭代到哪个元素:

初始情况下,.idx属性等于列表的长度,表示列表中剩下的元素;

每次调用.next()方法时,idx属性减1;

根据.idx属性的大小返回相应位置的元素;

当idx属性<0时,说明列表已被迭代完毕,抛出一个StopIteration异常。

  1. def next(self):  
  2. self.idx -1 
  3. if self.idx >= 0:  
  4. return self.seq[self.idx]  
  5. else:  
  6. raise StopIteration 

完整的定义如下:

  1. In [13]: class Reverse(object):  
  2.     ...:  def __init__(self, x):  
  3.     ...:      self.seq = x 
  4.     ...:      self.idx = len(x)  
  5.     ...:  
  6.     ...:  def __iter__(self):  
  7.     ...:      return self  
  8.     ...:  
  9.     ...:  def next(self):  
  10.     ...:      self.idx -1 
  11.     ...:      if self.idx >= 0:  
  12.     ...:     return self.seq[self.idx]  
  13.     ...:      else:  
  14.     ...:     raise StopIteration  
  15.     ...: 


喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

网络管理员考试考前冲刺预测卷及考点解析

本书依据最新版《网络管理员考试大纲》的考核要求,深入研究了历年网络管理员考试试题的命题风格和试题结构,对考查的知识点进行了提炼,并...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊