《Python Cookbook 3rd》笔记(4.4):实现迭代器协议
实现迭代器协议
问题
你想构建一个能支持迭代操作的自定义对象,并希望找到一个能实现迭代协议的简单方法。
解法
目前为止,在一个对象上实现迭代最简单的方式是使用一个生成器函数。在 4.2 小节中,使用 Node 类来表示树形数据结构。你可能想实现一个以深度优先方式遍历树形节点的生成器。下面是代码示例:
class Node:def __init__(self, value):self._value = valueself._children = []def __repr__(self):return 'Node({!r})'.format(self._value)def add_child(self, node):self._children.append(node)def __iter__(self):return iter(self._children)def depth_first(self):yield selffor c in self:yield from c.depth_first()# Example
if __name__ == '__main__':root = Node(0)child1 = Node(1)child2 = Node(2)root.add_child(child1)root.add_child(child2)child1.add_child(Node(3))child1.add_child(Node(4))child2.add_child(Node(5))for ch in root.depth_first():print(ch)# Outputs Node(0), Node(1), Node(3), Node(4), Node(2), Node(5)
在这段代码中, depth_first() 方法简单直观。它首先返回自己本身并迭代每一个子节点并通过调用子节点的 depth_first() 方法 (使用 yield from 语句) 返回对应元素。
讨论
Python 的迭代协议要求一个__iter__() 方法返回一个特殊的迭代器对象,这个迭代器对象实现了__next__() 方法并通过 StopIteration 异常标识迭代的完成。但是,实现这些通常会比较繁琐。下面我们演示下这种方式,如何使用一个关联迭代器类重新实现 depth_first() 方法:
class Node2:def __init__(self, value):self._value = valueself._children = []def __repr__(self):return 'Node({!r})'.format(self._value)def add_child(self, node):self._children.append(node)def __iter__(self):return iter(self._children)def depth_first(self):return DepthFirstIterator(self)class DepthFirstIterator(object):'''Depth-first traversal'''def __init__(self, start_node):self._node = start_nodeself._children_iter = Noneself._child_iter = Nonedef __iter__(self):return selfdef __next__(self):# Return myself if just started; create an iterator for childrenif self._children_iter is None:self._children_iter = iter(self._node)return self._node# If processing a child, return its next itemelif self._child_iter:try:nextchild = next(self._child_iter)return nextchildexcept StopIteration:self._child_iter = Nonereturn next(self)# Advance to the next child and start its iterationelse:self._child_iter = next(self._children_iter).depth_first()return next(self)
DepthFirstIterator 类和上面使用生成器的版本工作原理类似,但是它写起来很繁琐,因为迭代器必须在迭代处理过程中维护大量的状态信息。坦白来讲,没人愿意写这么晦涩的代码。将你的迭代器定义为一个生成器后一切迎刃而解。
《Python Cookbook 3rd》笔记(4.4):实现迭代器协议相关推荐
- 《Python Cookbook 3rd》笔记(1.4):查找最大或最小的N个元素
<Python Cookbook 3rd>1.4:查找最大或最小的N个元素 问题 怎样从一个集合中获得最大或者最小的N个元素列表? 解法 heapq 模块有两个函数:nlargest()和 ...
- Python Cookbook 3rd Edition Documentation
Python Cookbook 3rd Edition Documentation 文章目录 第一章:数据结构和算法 1.1 解压序列赋值给多个变量 问题 解决方案 讨论 1.2 解压可迭代对象赋值给 ...
- 《Python cookbook》笔记二
<Python cookbook>笔记二 第二章 字符串和文本 -使用多个界定符分割字符串- 你需要将一个字符串分割为多个字段,但是分隔符 (还有周围的空格) 并不是固定 的. # str ...
- Machine Learning with Python Cookbook 学习笔记 第8章
Chapter 8. Handling Images 前言 本笔记是针对人工智能典型算法的课程中Machine Learning with Python Cookbook的学习笔记 学习的实战代码都放 ...
- Machine Learning with Python Cookbook 学习笔记 第9章
Chapter 9. Dimensionality Reduction Using Feature Extraction 前言 本笔记是针对人工智能典型算法的课程中Machine Learning w ...
- Machine Learning with Python Cookbook 学习笔记 第6章
Chapter 6. Handling Text 本笔记是针对人工智能典型算法的课程中Machine Learning with Python Cookbook的学习笔记 学习的实战代码都放在代码压缩 ...
- 《Python Cookbook 3rd》笔记(4.2):代理迭代
代理迭代 问题 你构建了一个自定义容器对象,里面包含有列表.元组或其他可迭代对象.你想直接在你的这个新容器对象上执行迭代操作. 解法 实际上你只需要定义一个 iter () 方法,将迭代操作代理到容器 ...
- 《Python Cookbook 3rd》笔记汇总
文章目录 一.数据结构 二.字符串和文本 三.数字.日期和时间 四.迭代器与生成器 五.文件与IO 一.数据结构 标题 关键词 1.1:拆分序列后赋值给多个变量 可迭代对象.拆分赋值 1.2:拆分任意 ...
- 《Python cookbook》笔记一
<Python cookbook> 第一章 数据结构和算法 - *号解压多个变量 - 如果一个可迭代对象的元素个数超过变量个数时,会抛出一个 ValueError .那么 怎样才能从这个可 ...
最新文章
- python中ret是什么意思_数据结构图在python中的应用
- 无源定位之时差估计的精确时差估计算法(ETDE)及MATLAB实现程序
- 力扣(leetcode)-1. 两数之和
- 直接管理内存——new和delete
- JavaScript函数节流和函数防抖
- 阿里内推题——物流派送员送快递最短路径问题
- 可能是全网最通俗易懂的微服务架构改造解读
- 侏儒排序算法原理与Python实现
- vue将每个路由打包成html,Ant Design Vue pro 动态路由的实现和打包
- 如何将 Mac 置入睡眠状态或唤醒 Mac?
- Golang 入门 : Go语言介绍
- logo字体在线设计工具
- EF Core注意事项
- linux的htb队列,Linux流量控制中的HTB队列创建与过滤(2)
- [渝粤教育] 西南科技大学 计算机文化基础复习资料
- 基于安卓的校园跳蚤市场app
- LeetCode(跳跃游戏)
- 简易的MySQL主从复制
- 为什么说学计算机更有远见,“孩子,我为什么逼你读书”:有远见的父母,都有点心狠...
- sql --Acess
热门文章
- 串口通讯编程一日通3(COMMTIMEOUTS DCB整理)
- Maven笔记——依赖管理
- java二级缓存技术_Java二级缓存
- Web服务器控件和HTML控件的区别与联系
- C#多线程编程系列(一)- 简介
- 35解释器模式(Interpreter Pattern)
- 使用 Syslog 连接 Sentinel
- ROS有三个层级的概念,分别是:文件系统级、计算图级和开源社区级
- python用什么系统好_10分钟用python搭建一个超好用的CMDB系统
- 【Python CheckiO 题解】Sort Array by Element Frequency