如何定义一个类对象并用next()的方法使用_python零基础必读--可迭代对象、迭代器与生成器...
本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理
迭代器是 Python 最强大的功能之一,可以想像如果有个几十 GB 的大文件,你需要编写程序处理其中的文本信息,如果一次性全部读入内存,估计机器会直接罢工了,但是借住可迭代对象,可以一次从硬盘读取一小块内容到内存,处理完后写回硬盘,不断迭代,从而节省内存,加快处理速度。
首先来解释这3个概念。
(1)可迭代对象:如果一个对象定拥有 iter 方法,那么这个对象就是一个可迭代对象。这里顺便说下
for 循环的处理过程:在 Python 中我们经常使用 for 循环来对某个对象进行遍历,此时被遍历的这个对象就是可迭代对象,常见的有列表,元组,字典。for 循环开始时自动调用可迭代对象的 iter 方法获取一个迭代器,for 循环时自动调用迭代器的 next 方法获取下一个元素,当调用可迭代器对象的 next 方法引发 StopIteration 异常时,结束 for 循环。
(2)迭代器:如果一个对象定拥有 iter 方法和 next 方法,那么这个对象就是一个迭代器。
(3)生成器:生成器是一类特殊的迭代器,就是在需要的时候才产生结果,不是立即产生结果。这样可以同时节省 CPU 和内存。有两类方法实现生成器:
- 生成器函数。使用 def 定义函数,使用 yield 而不是 return 语句返回结果。yield 语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。
- 生成器表达式。类似于列表推导,只不过是把一对大括号 [] 变换为一对小括号() 。但是,生成器表达式是按需产生一个生成器结果对象,要想拿到每一个元素,就需要循环遍历。
三者之间的关系如下图所示。
三者之间的关系
可迭代对象包含迭代器、序列、字典;生成器是一种特殊的迭代器。下面分别举例说明。
### 创建一个迭代器
1 class MyListIterator(object): # 定义迭代器类,其是MyList可迭代对象的迭代器类
2
3 def __init__(self, data):
4 self.data = data # 上边界
5 self.now = 0 # 当前迭代值,初始为0
6
7 def __iter__(self):
8 return self # 返回该对象的迭代器类的实例;因为自己就是迭代器,所以返回self
9
10 def __next__(self): # 迭代器类必须实现的方法
11 while self.now < self.data:
12 self.now += 1
13 return self.now - 1 # 返回当前迭代值
14 raise StopIteration # 超出上边界,抛出异常
类 MyListIterator 实现了 iter 方法和 next 方法,因此它是一个迭代器对象,由于 iter 方法本返的是迭代器(本身),因此它也是可迭代对象。迭代器必然是一个可迭代对象。
下面使用3种方法遍历迭代器 MyListIterator。
1 my_list = MyListIterator(5) # 得到一个迭代器
2 print("使用for循环来遍历迭代器")
3 for i in my_list:
4 print(i)
5 my_list = MyListIterator(5) # 重新得到一个可迭代对象
6 print("使用next来遍历迭代器")
7 print(next(my_list))
8 print(next(my_list))
9 print(next(my_list))
10 print(next(my_list))
11 print(next(my_list))
12 my_list = MyListIterator(5) # 重新得到一个可迭代对象
13 print("同时使用next和for来遍历迭代器")
14 print("先使用两次next")
15 print(next(my_list))
16 print(next(my_list))
17 print("再使用for,会从第三个元素2开始输出")
18 for i in my_list:
19 print(i)
输出结果如下:
使用for循环来遍历迭代器
0
1
2
3
4
使用next来遍历迭代器
0
1
2
3
4
同时使用next和for来遍历迭代器
先使用两次next
0
1
再使用for,会从第三个元素2开始输出
2
3
4
从结果可以看出,for 循环实际上就是调用了迭代器的 __next__方法,当捕捉到 MyListIterator 异常时自动结束 for 循环
创建一个可迭代对象
1 class MyList(object): # 定义可迭代对象类
2 def __init__(self, num):
3 self.data = num # 上边界
4 def __iter__(self):
5 return MyListIterator(self.data) # 返回该可迭代对象的迭代器类的实例
上例中对象 MyList 实现了 iter 方法返回了迭代器类的实例,因此它是一个可迭代对象。遍历操作可使用 for 循环,无法使用 next()。for 循环实质上还是调用 MyListIterator 的 next 方法。
1 my_list = MyList(5) # 得到一个可迭代对象
2 print("使用for循环来遍历可迭代对象my_list")
3 for i in my_list:
4 print(i)
5 my_list = MyList(5) # 得到一个可迭代对象
6 print("使用next来遍历可迭代对象my_list")
7 print(next(my_list))
8 print(next(my_list))
9 print(next(my_list))
10 print(next(my_list))
11 print(next(my_list))
输出结果如下:
使用for循环来遍历可迭代对象my_list
0
1
2
3
4
使用next来遍历可迭代对象my_listprint(next(my_list))
TypeError: 'MyList' object is not an iterator
从运行结果知道可迭代对象如果没有 __next__方法,则无法通过next()进行遍历。
创建一个生成器
像定义一般函数一样,只不过使用 yield 返回中间结果。生成器是一种特殊的迭代器,生成器自动实现了迭代器协议,即 iter 和 next 方法,不需要再手动实现两方法。创建生成器实例如下:
1 def myList(num): # 定义生成器
2 now = 0 # 当前迭代值,初始为0
3 while now < num:
4 val = (yield now) # 返回当前迭代值,
5 now = now + 1 if val is None else val # val为None,迭代值自增1,否则重新设定当前迭代值为val
遍历生成器:
1 my_list = myList(5) # 得到一个生成器对象
2 print("for 循环遍历生成器myList")
3 for i in my_list:
4 print(i)
5
6 my_list = myList(5) # 得到一个生成器对象
7 print("next遍历生成器myList")
8 print(next(my_list)) # 返回当前迭代值值
9 print(next(my_list)) # 返回当前迭代值值
10 print(next(my_list)) # 返回当前迭代值值
11 print(next(my_list)) # 返回当前迭代值值
12 print(next(my_list)) # 返回当前迭代值值
运行结果如下:
for 循环遍历生成器myList
0
1
2
3
4
next遍历生成器myList
0
1
2
3
4
具有 yield 关键字的函数都是生成器,yield 可以理解为 return,返回后面的值给调用者。不同的是 return 返回后,函数会释放,而生成器则不会。在直接调用 next 方法或用 for 语句进行下一次迭代时,生成器会从 yield 下一句开始执行,直至遇到下一个 yield。
如何定义一个类对象并用next()的方法使用_python零基础必读--可迭代对象、迭代器与生成器...相关推荐
- java定义一个类计算圆的半径,C++编程:定义一个圆类要求属性为半径,操作为计算圆的周长和面积...,java编程:定义一个圆类,属性为半径,方法为对输入的半径计...
导航:网站首页 > C++编程:定义一个圆类要求属性为半径,操作为计算圆的周长和面积...,java编程:定义一个圆类,属性为半径,方法为对输入的半径计 C++编程:定义一个圆类要求属性为半径, ...
- Java创建一个文件变量_java如何定义一个类,创建它的成员变量和方法?
展开全部 类即对象的思想,一个对象包含e68a843231313335323631343130323136353331333337623439了属于自己的成员变量和操作方法. 如何定义一个类,得看你对 ...
- java定义一个类_java如何定义一个类,创建它的成员变量和方法?
展开全部 类即对象的思想,一个对象包含e69da5e887aa3231313335323631343130323136353331333337623439了属于自己的成员变量和操作方法. 如何定义一个 ...
- python中定义类的关键字_在Python中,定义一个类使用什么关键字?
[多选题]技术应用的限制包括 [多选题]关于类和对象,下面说法正确的有? [判断题]温度越高,料液的粘度越小,扩散系数越大,可提高膜通量. [单选题]某企业有10台运货车,已知每台车每运行100小时平 ...
- 按要求编写一个Java应用程序:(1)定义一个类,描述一个矩形,包含有长、宽两种属性,和计算面积方法。(2)编写一个类,继承自矩形类,同时该类描述长方体,具有长、宽、高属性
(1)定义一个类,描述一个矩形,包含有长.宽两种属性,和计算面积方法. public class Jvcs {private int Long; //长private int wide; //宽pub ...
- java设计一个bank类实现银行_java定义一个类实现银行账户的概念。
2016-11-17 13:40黄瞩信 客户经理 比如,只定义了一个抽象方法run(),而要通过系统用极短的时间.这5s内,此后这个线程就不能进入其它状态,进入消亡状态;+i++). 2,另一方面;, ...
- 根据公式计算y的值。其中∑表示求各项的和,∏表示求各项的积。定义一个类F,实现上述功能。具体要求如下:
根据公式计算y的值.其中∑表示求各项的和,∏表示求各项的积.定义一个类F,实现上述功能.具体要求如下: (1)私有数据成员 double x[5]:存放xi(i=1,2,3,4,5)的值,xi不能为0 ...
- java设计一个bank类实现银行_用java定义一个类实现银行帐户的概念
满意答案 ZHIu6Az0v 推荐于 2017.11.26 采纳率:56% 等级:11 已帮助:8247人 /* * 2. 定义一个类实现银行帐户的概念,包括的变量有"帐号" ...
- php面向对象 - 定义一个类
1.定义类 在 PHP 中,可以使用 class 关键字加类名的方式定义一个类,然后用大括号{ }将在类体中定义类的属性和方法包裹起来,类的语法格式如下: [修饰类的关键字] class 类名{类的属 ...
- java定义一个类_Java类的定义格式:Java如何定义一个类
在面向对象的思想中,最核心的就是对象.为了在程序中创建对象,首先需要定义一个类.类是对象的抽象,它用于描述一组对象的共同特征和行为,例如人都有姓名.年龄.性别等特征,还有学习.工作.购物等行为.以面向 ...
最新文章
- 服务没有报告任何错误。 请键入 NET HELPMSG 3534 以获得更多的帮助。
- 空间谱专题09:阵列信号建模方法
- 微信在公众号增开了新广告位 这次是在图文消息头部
- 一个 http 请求的曲折经历
- android app无感知自动升级,Android中实现用户无感知处理后台崩溃
- 多重背包的二进制优化(ybtoj-宝物筛选)
- 汇编语言(七)之字符串转大写
- 工业交换机和工业级光纤收发器的区别
- 快速入门Pytorch(1)--安装、张量以及梯度
- CSS基础必备知识点01
- JBox2D For Android - hello box2d
- FPGA设计经验总结
- Java父类与子类中静态代码块 实例代码块 静态变量 实例变量 构造函数执行顺序...
- MySQL两阶段加锁
- 2023最新可用QQ机器人框架整理
- 工程师的基本功是什么?该如何练习?听听美团技术大咖怎么说
- Hibernate架包的下载
- Arcmap没有Spatial Analyst模块
- [Python] 一行代码让你明白什么叫艺术
- 图论欧拉回路初步 BZOJ2095 POI2010 Bridges