『无为则无心』Python基础 — 62、Python中自定义迭代器
1、迭代器对象的创建
迭代器是一种可以被遍历的对象,并且能够作用于next()函数,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器只能往后遍历,不能回溯。不像列表,你随时可以取后面的数据,也可以返回头取前面的数据,迭代器通常要实现两个基本方法next()和iter()。
概括的说,一个对象实现了__iter__()和__next__()方法,那么它就是一个迭代器对象。
但是只实现了__iter__()方法没有实现__next__()方法,就只是一个可迭代对象。
例如:
# 3.6之前的版本是不需要带.abc的,3.7就会提示需要加.abc
from collections.abc import Iterable, Iterator
class IterA:
def __iter__(self):
# 我们这里返回一个列表
return [1, 2, 3]
class IterB:
pass
iterA = IterA()
iterB = IterB()
# 可以看到iterA 是一个可迭代对象
# iterB 是一个不可迭代对象
print(isinstance(iterA, Iterable)) # True
print(isinstance(iterB, Iterable)) # False
# iterA是一个可迭代对象,但并不是一个迭代器对象
# 因为IterA类中并没有实现next方法
print(isinstance(iterA, Iterator)) # False
我们在IterA类中实现__next__()方法,IterA类就变成了一个迭代器对象了。
# 3.6之前的版本是不需要带.abc的,3.7就会提示需要加.abc
from collections.abc import Iterable, Iterator
class IterA:
def __iter__(self):
# 我们这里返回一个列表
return [1, 2, 3]
def __next__(self):
pass
iterA = IterA()
# 可以看到iterA 是一个可迭代对象
# iterB 是一个不可迭代对象
print(isinstance(iterA, Iterable)) # True
# iterA对象也是要给迭代器对象
print(isinstance(iterA, Iterator)) # True
2、实际应用案例
"""
1.迭代器的应用场景
1).如果数列的数据规模巨大
2).数列有规律,但是依靠列表推导式描述不出来
2.数学中有个著名的斐波那契数列(Fibonacci),
数列中第⼀个数0,第⼆个数1,其后的每⼀个数都可由前两个数相加得到:
如下:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
现在我们想要通过for...in...循环来遍历迭代斐波那契数列中的前n个数。
那么这个斐波那契数列我们就可以⽤迭代器来实现,
每次迭代都通过数学计算来⽣成下⼀个数。
"""
from collections.abc import Iterable, Iterator
class FibIterator(object):
"""
fib数列迭代器
"""
# 初始化方法
def __init__(self, count):
# 斐波拉契数列中的前两个数
self.num1 = 0
self.num2 = 1
# 用来保存迭代的总次数
self.count = count
# 用来记录迭代次数(计数器)
self.i = 0
# 实现__iter__表示FibIterator是一个可迭代对象
# 返回对象自己。是一个可迭代对象
def __iter__(self):
return self
# 实现__next__方法,是FibIterator定义为迭代器对象的重要条件之一
def __next__(self):
# 判断是否迭代结束,如果没有到达迭代次数,则返回数据
# self.count 需要迭代的次数
# self.i已迭代次数
if self.i < self.count:
item = self.num1
# 计算num1, num2的值,方便下次迭代返回
# 这里运用的是序列的封包与解包,不会的可以看我以前的文章(元组)
self.num1, self.num2 = self.num2, self.num1 + self.num2
# 执行一次next方法,计数器+1
self.i += 1
# 返回新获得的数,
# 也就是前两个数求和的第三个数
return item
else:
# 到达了迭代次数,抛出异常
raise StopIteration
# 创建一个fib数列迭代器对象
fibIter = FibIterator(15)
# fibIter对象是一个迭代器
print(isinstance(fibIter, Iterable)) # True
print(isinstance(fibIter, Iterator)) # True
# 转换为列表查看fib对象内容
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]
print(list(fibIter))
# 遍历,可执行
for li in fibIter:
print(li)
3、总结:
(1)整理总结
- 对象是否实现了
__iter__方法,如果实现了,该对象就是一个可迭代对象。 - 一个对象实现了
__iter__()和__next__()方法,那么它就是一个迭代器对象。 - 可以使用
iter()函数把可迭代对象(Iterable)变成迭代器对象(Iterator)。 - 通过
isinstance()函数,可以判断一个对象是否是Iterable对象或者是Iterator对象。print(isinstance(fibIter, Iterable))
print(isinstance(fibIter, Iterator))
(2)迭代协议
当任何可迭代对象传入到for循环或其他迭代工具中进行遍历时,迭代工具都是先通过iter()函数获得与可迭代对象对应的迭代器,然后再对迭代器调用next()函数,不断的依次获取元素,并在捕捉到StopIteration异常时,确定完成迭代,这就是完整的迭代过程,这也称之为“迭代协议”。
(3)为什么任何Python序列都可迭代?
- 都实现了
__getitem__方法 - 标准序列也都实现了
__iter__方法 - 实现了
__getitem__方法,而且其参数是从0开始的索引,这种对象也可迭代,但它不是一个可迭代对象。
原因是:如果没有实现__iter__方法,但实现了__getitem__方法,__getitem__()方法可以通过iter()函数转成Iterator,即可以在for循环中使用,按顺序(从0开始)获取元素。from collections.abc import Iterable, Iterator class IterObj: def __init__(self):
self.a = [3, 5, 7, 11, 13, 17, 19] def __getitem__(self, i):
return self.a[i] # 从创建对象
it = IterObj()
print(isinstance(it, Iterable)) # false
print(isinstance(it, Iterator)) # false
# <__main__.IterObj object at 0x0000000002573AC8>
print(it)
# # <iterator object at 0x10b231278>
print(iter(it)) # 遍历
for i in it:
print(i)
归纳:
- 如果这个可迭代对象要在
for循环中被使用,那么它就应该能够被内置的iter()函数调用并转化成Iterator对象。- Python的for语法功能非常强大,可以遍历任何可迭代的对象。
参考:
『无为则无心』Python基础 — 62、Python中自定义迭代器的更多相关文章
- 『无为则无心』Python基础 — 3、搭建Python开发环境
目录 1.Python开发环境介绍 2.Python解释器的分类 3.下载Python解释器 4.安装Python解释器 5.Python解释器验证 1.Python开发环境介绍 所谓"工欲 ...
- 『无为则无心』Python基础 — 4、Python代码常用调试工具
目录 1.Python的交互模式 2.IDLE工具使用说明 3.Sublime3工具的安装与配置 (1)Sublime3的安装 (2)Sublime3的配置 4.使用Sublime编写并调试Pytho ...
- 『无为则无心』Python基础 — 6、Python的注释
目录 1.注释的作用 2.注释的分类 单行注释 多行注释 3.注释的注意事项 4.什么时候需要使用注释 5.总结 提示:完成了前面的准备工作,之后的文章开始介绍Python的基本语法了. Python ...
- 『无为则无心』Python基础 — 7、Python的变量
目录 1.变量的定义 2.Python变量说明 3.Python中定义变量 (1)定义语法 (2)标识符定义规则 (3)内置关键字 (4)标识符命名习惯 4.使用变量 1.变量的定义 程序中,数据都是 ...
- 『无为则无心』Python基础 — 10、Python字符串的格式化输出
目录 1.什么是格式化输出 2.Python格式化输出的五种方式 方式一:字符串之间用+号拼接 方式二:print()函数可同时输出多个字符串 方式三:占位符方式 方式四:f格式化方式(推荐) 方式五 ...
- 『无为则无心』Python基础 — 12、Python运算符详细介绍
目录 1.表达式介绍 2.运算符 (1)运算符的分类 (2)算数运算符 (3)赋值运算符 (4)复合赋值运算符 (5)比较运算符 3.逻辑运算符 拓展1:数字之间的逻辑运算 拓展2:Python中逻辑 ...
- 『无为则无心』Python基础 — 44、对文件和文件夹的操作
目录 1.os模块介绍 2.查看os模块相关文档 3.os模块常用方法 (1)文件重命名 (2)删除文件 (3)创建文件夹 (4)删除文件夹 (5)获取当前目录 (6)改变默认目录 (7)获取目录列表 ...
- 『无为则无心』Python基础 — 61、Python中的迭代器
目录 1.迭代的概念 2.迭代器的概念 3.可迭代的对象(Iterable) 4.迭代器对象(Iterator) 5.迭代器的使用体验 (1)基本用法 (2)实际应用 1.迭代的概念 (1)什么是迭代 ...
- 『无为则无心』Python序列 — 24、Python序列的推导式
目录 1.列表推导式 (1)快速体验 (2)带if的列表推导式 (3)多个for循环实现列表推导式 2.字典推导式 (1)创建一个字典 (2)将两个列表合并为一个字典 (3)提取字典中目标数据 3.集 ...
- 『无为则无心』Python函数 — 29、Python变量和参数传递
目录 1.Python的变量 (1)Python变量不能独立存在 (2)变量是内存中数据的引用 (3)注意点 2.了解变量的引用 3.Python的参数传递(重点) (1)示例 (2)结论 (3)总结 ...
随机推荐
- 【发布开源代码】铁威马NAS存储上实现的视频文件浏览
具体介绍请看:https://github.com/ahfuzhang/tnas_video_web x86机器的windows/linux/mac机器应该都能使用 效果如下: 按月浏览视频 视频太多 ...
- DDD从入门到精通:基础篇
这篇文章主要还是表述清楚DDD相关的基础概念,因为DDD入门有一定的专业名词,还是得有个基本的了解. 先讲解下领域模型作用: 对软件需求进行设计,维持其内在逻辑的一致性 1)划分边界.也是一种高内聚. ...
- golang中数组指针和指针数组当做函数参数如何修改数组中的值
先理解:数组指针它的类型时指针,指针数组它的类型时数组 1. 数组指针当做函数的参数 package main import "fmt" func changeData(dataA ...
- linux下查看开放的端口
Nmap是一款针对大型网络的端口扫描工具,它也适用于单机扫描,它支持很多扫描,也同时支持性能和可靠性统计. [root@localhost ~]# yum install namp [root@loc ...
- 什么是协程(第三方模块gevent--内置模块asyncio)
目录 一:协程 1.什么是协程? 2.携程的作用? 3.安装第三方模块:在命令行下 二:greenlet模块(初级模块,实现了保存状态加切换) 三: gevent模块(协程模块) 1.time 模式协 ...
- 基于Redis&MySQL接口幂等性设计
基于Redis&MySQL接口幂等性设计 欲把相思说似谁,浅情人不知. 1.幂等 幂等性即多次调用接口或方法不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致. 2.幂等使用场景 前 ...
- Ventoy的UEFI模式安全启动操作说明
Ventoy 1.0.07 版本开始支持 Secure Boot (安全启动),但是这个方案不是非常的完美,会导致在一些机器上不管BIOS里安全启动是否关闭都不能正常工作.因此从 1.0.09 版本开 ...
- 在EntityFrameworkCore中记录EF修改日志,保存,修改字段的原始值,当前值,表名等信息
突发奇想,想把业务修改的所有字段原始值和修改后的值,做一个记录,然后发现使用EF可以非常简单的实现这个功能 覆盖父类中的 SaveShanges() 方法 public new int SaveCha ...
- vue常用组件
滚动组件:better-scroll 官网地址:https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/installation.html ...
- ApacheCN 计算机视觉译文集 20211110 更新
OpenCV3 和 Qt5 计算机视觉 零.前言 一.OpenCV 和 Qt 简介 二.创建我们的第一个 Qt 和 OpenCV 项目 三.创建一个全面的 Qt + OpenCV 项目 四.Mat和Q ...