可迭代的对象

如果对象实现了能返回迭代器的 __iter__ 方法,那么对象就是可迭代的。
序列都可以迭代;实现了 __getitem__ 方法,而且其参数是从零开始的索引,这种对象也可以迭代。
>>> s = 'ABC'
>>> it = iter(s) # ➊
>>> while True:
... try:
... print(next(it)) # ➋
... except StopIteration: # ➌
... del it # ➍
... break # ➎
...
A
B
C

❶ 使用可迭代的对象构建迭代器 it。
❷ 不断在迭代器上调用 next 函数,获取下一个字符。
❸ 如果没有字符了,迭代器会抛出 StopIteration 异常。
❹ 释放对 it 的引用,即废弃迭代器对象。
❺ 退出循环。

StopIteration 异常表明迭代器到头了。Python 语言内部会处理 for循环和其他迭代上下文(如列表推导、元组拆包,等等)中的StopIteration 异常

标准的迭代器接口有两个方法

__next__
  返回下一个可用的元素,如果没有元素了,抛出 StopIteration异常。

__iter__
  返回 self,以便在应该使用可迭代对象的地方使用迭代器,例如在 for 循环中。

这个接口在 collections.abc.Iterator 抽象基类中制定。这个类定义了 __next__ 抽象方法,而且继承自 Iterable 类;__iter__ 抽象方法则在 Iterable 类中定义。

图 14-1:Iterable 和 Iterator 抽象基类。以斜体显示的是抽象方法。具体的 Iterable.__iter__ 方法应该返回一个 Iterator 实例。

具体的 Iterator 类必须实现 __next__ 方法。Iterator.__iter__ 方法直接返回实例本身

示例 14-1 sentence.py:把句子划分为单词序列

import re
import reprlib RE_WORD = re.compile('\w+') class Sentence: def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text) ➊
def __getitem__(self, index):
return self.words[index] ➋
def __len__(self): ➌
return len(self.words) def __repr__(self):
return 'Sentence(%s)' % reprlib.repr(self.text) ➍

❶ re.findall 函数返回一个字符串列表,里面的元素是正则表达式的全部非重叠匹配。
❷ self.words 中保存的是 .findall 函数返回的结果,因此直接返回指定索引位上的单词。
❸ 为了完善序列协议,我们实现了 __len__ 方法;不过,为了让对象可以迭代,没必要实现这个方法。

❹ reprlib.repr 这个实用函数用于生成大型数据结构的简略字符串表示形式。

再看示例 14-1 中定义的 Sentence 类,在 Python 控制台中能清楚地看出如何使用 iter(...) 函数构建迭代器,以及如何使用 next(...) 函数使用迭代器:

>>> s3 = Sentence('Pig and Pepper')  # ➊
>>> it = iter(s3) # ➋
>>> it # doctest: +ELLIPSIS
<iterator object at 0x...>
>>> next(it) # ➌
'Pig'
>>> next(it)
'and'
>>> next(it)
'Pepper'
>>> next(it) # ➍
Traceback (most recent call last):
...
StopIteration
>>> list(it) # ➎
[]
>>> list(iter(s3)) # ➏
['Pig', 'and', 'Pepper']

❶ 创建一个 Sentence 实例 s3,包含 3 个单词。
❷ 从 s3 中获取迭代器。
❸ 调用 next(it),获取下一个单词。
❹ 没有单词了,因此迭代器抛出 StopIteration 异常。
❺ 到头后,迭代器没用了。
❻ 如果想再次迭代,要重新构建迭代器。

因为迭代器只需 __next__ 和 __iter__ 两个方法,所以除了调用next() 方法,以及捕获 StopIteration 异常之外,没有办法检查是否还有遗留的元素。
此外,也没有办法“还原”迭代器。如果想再次迭代,那就要调用 iter(...),传入之前构建迭代器的可迭代对象。
传入迭代器本身没用,因为前面说过 Iterator.__iter__ 方法的实现方式是返回实例本身,所以传入迭代器无法还原已经耗尽的迭代器。

迭代器

迭代器是这样的对象:实现了无参数的 __next__ 方法,返回序列中的下一个元素;如果没有元素了,那么抛出 StopIteration 异常。
Python 中的迭代器还实现了 __iter__ 方法,因此迭代器也可以迭代。因为内置的 iter(...) 函数会对序列做特殊处理,所以第 1 版Sentence 类可以迭代。

python 迭代器(二):迭代器基础(二)可迭代的对象与迭代器的对比的更多相关文章

  1. 『流畅的Python』第14章:可迭代的对象、迭代器和生成器

  2. 流畅的python第十四章可迭代的对象,迭代器和生成器学习记录

    在python中,所有集合都可以迭代,在python语言内部,迭代器用于支持 for循环 构建和扩展集合类型 逐行遍历文本文件 列表推导,字典推导和集合推导 元组拆包 调用函数时,使用*拆包实参 本章 ...

  3. 流畅的python 14章可迭代的对象、迭代器 和生成器

    可迭代的对象.迭代器和生成器 迭代是数据处理的基石.扫描内存中放不下的数据集时,我们要找到一种惰性获取数据项的方式,即按需一次获取一个数据项.这就是迭代器模式(Iterator pattern). 迭 ...

  4. Python(四)基础篇之「文件对象&错误处理」

    [笔记]Python(四)基础篇之「文件对象&错误处理」 2016-12-08 ZOE    编程之魅  Python Notes: ★ 如果你是第一次阅读,推荐先浏览:[重要公告]文章更新. ...

  5. python学习笔记之基础二(第二天)

    1.编码转换介绍        unicode是最底层.最纯的,会根据终端的编码进行转化展示 一般硬盘存储或传输为utf-8(因为省空间.省带宽),读入内存中为unicode,二者如何转换 a = ' ...

  6. Python 可迭代的对象、迭代器和生成器

    迭代是数据处理的基石.扫描内存中放不下的数据集时,我们要找到一种惰性获取数据项的方式,即按需一次获取一个数据项.这就是迭代器模式(Iterator pattern). p.p1 { margin: 0 ...

  7. Python天天学_02_基础二

    Python_day_02 金角大王:http://www.cnblogs.com/alex3714/articles/5717620.html ------Python是一个优雅的大姐姐 学习方式: ...

  8. Python的高级特性(切片,迭代,生成器,迭代器)

    掌握了python的数据类型,语句和函数,基本上就可以编出很多有用的程序了. 但是在python中,并不是代码越多越好,代码不是越复杂越好,而是越简单越好. 基于这个思想,就引申出python的一些高 ...

  9. python学习笔记(基础二:注释、用户输入、格式化输出)

    注释 单行:# 多行:上下各用3个连续单引号或双引号 3个引号除了多行注释,还可以打印多行 举例: msg = ''' name = "Alex Li" name2 = name ...

随机推荐

  1. 用python复制文件夹

    用python复制文件 1. 根据文件夹的名称复制 需要复制的文件夹编号文件中,每一行表示一个编号,如下所示: > cat id.txt 1 2 3 ... > 目标文件的目录结构树如下所 ...

  2. Redis学习笔记(二十一) 事务

    文章开始啰嗦两句,写到这里共21篇关于redis的琐碎知识,没有过多的写编程过程中redis的应用,着重写的是redis命令.客户端.服务器以及生产环境搭建用到的主从.哨兵.集群实现原理,如果你真的能 ...

  3. matplotlib作图一例

    知识点都在这个例子里面: plt.figure(figsize=(10,10)) for i in range(25): plt.subplot(5,5,i+1) plt.xticks([]) plt ...

  4. Android学习笔记样式资源文件

    样式资源和主题资源都是写在styles.xml文件里面的 <style name="title"> <item name="android:textSi ...

  5. Flutter学习笔记(35)--通知Notification

    如需转载,请注明出处:Flutter学习笔记(35)--通知Notification 通知的NotificationListener和我们之前写的事件的Listener一样,都是功能性的组件,而且也都 ...

  6. Matlab 常用语法速记 1

    ===快捷帮助=== 查找帮助:doc 函数名 强制终止: ctrl + c 注释: % 清屏 clc,清临时变量窗口 clear NaN: not a number inf: infinite == ...

  7. TensorFlow中读取图像数据的三种方式

    本文面对三种常常遇到的情况,总结三种读取数据的方式,分别用于处理单张图片.大量图片,和TFRecorder读取方式.并且还补充了功能相近的tf函数. 1.处理单张图片 我们训练完模型之后,常常要用图片 ...

  8. Shiro简单加密服务

    编码/加密 在涉及到密码存储问题上,应该加密 / 生成密码摘要存储,而不是存储明文密码.比如之前的 600w csdn 账号泄露对用户可能造成很大损失,因此应加密 / 生成不可逆的摘要方式存储. Sh ...

  9. C#数据结构与算法系列(十二):递归(Recursion)

    1.介绍 简单的说:递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂的问题,同时也让代码变得整洁 2.规则 执行一个方法时,就创建一个新的受保护的独立空间(栈空间) 方法的 ...

  10. MongoDB快速入门教程 (4.3)

    4.3.Mongoose模块化 4.3.1.为什么要进行模块化拆分? 模块化拆分的目的是为了代码的复用,让整个项目的结构更加清晰,举个例子:当数据库中的集合变多的时候,例如有课程.订单.分类.教师等多 ...