python基础(part15)--迭代
鄙人学习笔记
开发工具:Spyder
文章目录
- 迭代
- 举个例子1
- 举个例子2
- for循环原理
- 可迭代对象iterable
- 举个例子1
- 举个例子2
- 举个例子3
- 迭代器对象iterator
- yield关键字迭代原理
- 举个例子(我们将之前的MyRange类进行改写)
迭代
每一次对过程的重复为一次”迭代”,而每一次迭代得到的结果,会作为下一次迭代的初始值。例如:循环获取容器中的元素。
举个例子1
创建一个列表:
再输入以下代码:
结果:
可以看出,我们得到的结果和for循环遍历这个列表,得到的结果相同。
如果我们多写一个iterator.__next__()
,会怎样呢?
结果:
会报错 python警告我们,要 Stop Iteration, 停止迭代!
举个例子2
还是创建原来的列表:
我们再利用以下方法迭代:
第39行代码这样写,其实相当于在except之后写了个异常基类:
结果:
我们发现,我们没有用for循环,也拿到了可迭代对象(列表)内元素。以上两个例子演示了for循环原理。
for循环原理
现在,我们对上面例子中的代码进行解释,进而阐述一下for循环原理
①获取迭代器对象
我们说,可迭代对象,是具有__iter__()
方法,可以返回迭代器的对象。所以以后我们评判一个对象是不是可迭代对象时,就可以看一看,这个对象有没有__iter__()
方法,如果有这个方法,则说明,这个对象是可以被迭代的。
②获取下一个元素(迭代)
有迭代器之后,我们就可以迭代了,__next__()
的过程就是在迭代的过程,有__next__()
我们就可以拿到下一个元素。
③停止迭代(StopIteration错误)
最后,我们总结一下for循环原理:
①获取迭代器对象
②循环迭代(调用迭代器的__next__()
方法)
③捕获StopIteration异常
- 小问题
问:能够被for循环的条件是什么?
答:具有__iter__()
方法的对象。
- 例子1
使用while + 迭代器,获取元祖(“小白”, “小黄”, “大白”)中所有元素。
代码:
t01 = ("小白", "小黄", "大白")
iterator = t01.__iter__()while True:try:item = iterator.__next__()print(item)except:break
结果:
- 例子2
不使用for循环,获取字典{“小白”:0, “小黄”:6, “大白”:7}中的key和value.
代码:
d01 = {"小白":0, "小黄":6, "大白":7}iterator = d01.__iter__()while True:try:key = iterator.__next__()print(key, d01[key])except:break
结果:
备注:使用迭代器迭代字典,拿到的是字典的key
可迭代对象iterable
- 定义
具有__iter__()
函数的对象,可以返回迭代器对象.
- 语法
创建可迭代对象:
class 可迭代对象名称:def __iter__(self):return 迭代器
使用可迭代对象:
for 变量名 in 可迭代对象:语句
- 原理
迭代器 = 可迭代对象.__iter__()while True:try:print(迭代器.__next__())except StopIteration:break
举个例子1
首先创建两个类:
再创建SkillManager对象,并试着迭代此对象的成员变量skills:
得到结果:
结果得到了列表内的各个Skill对象。
但是,如果我们只迭代SkillManager对象会怎样呢?我们看看下面这个例子。
举个例子2
利用例子1,创建的两个类:
再创建SkillManager对象,并试着迭代此对象:
运行:
报错!且python提示我们SkillManager对象是个不可迭代的对象。
接下来,我们就要让SkillManager可迭代!
我们先要在SkillManager类里增加一个__iter__()
方法,使他变为可迭代对象。 这个__iter__()
被调用后,应该返回一个迭代器类对象SkillIterator。这个迭代器类对象里应该有一个__next__()
方法,用于返回下一个元素。在__next__()
方法里应该抛出一个索引越界异常,当被迭代对象全部迭代完后,再获取下一个元素,则会抛出异常。具体情况,我们看看下面的代码。
现在我们看一下SkillManager类:
再看一下SkillIterator类:
创建对象,并开始利用for循环原理,进行迭代:
我们再运行一下,看一下运行结果:
不错!可迭代对象内元素全部拿到了。
备注1:由上面的过程我们也可以看出,可迭代对象不会直接return它的元素,而是由迭代器return了可迭代对象内的元素。
备注2:若我们用for循环,则它也会先获取迭代器对象,获取完迭代器对象后,再用迭代器对象不断的调用__next__()
方法,直到迭代器对象抛出异常,for再进行异常处理。
举个例子3
参照下例代码,定义MyRange类,实现相同效果:
代码:
class MyRangeIterator:def __init__(self, stop):self.stop = stopself.start = 0def __next__(self):if self.start + 1 > self.stop:raise StopIteration()temp = self.startself.start += 1return tempclass MyRange:def __init__(self, stop):self.stop = stopdef __iter__(self):# 创建迭代器对象return MyRangeIterator(self.stop)iterator = MyRange(5)
for item in iterator:print(item)
结果:
备注:谁要被for,谁要就有__iter__()
方法,这个方法可以获取迭代器,迭代器内部具体怎么写?看需求!迭代器中有__next__()
,可以返回下一个元素。
迭代器对象iterator
- 定义
可以调用__next__()
函数,并返回下一个值得对象。
- 语法
class 迭代器类名::def __init__(self, 聚合对象):self.聚合对象 = 聚合对象def __next__(self):if 没有元素:raise StopIterationreturn 聚合对象内元素
- 说明
聚合对象通常是容器对象。
- 作用
使用者只通过一种方式(for循环),便可以简洁明了获取聚合对象中的各个元素,而又无需了解可迭代对象的内部存储结构。
==备注!==若我们在__iter__()
方法内不返回自己创建的迭代器对象,而用yield关键字自动生成迭代器对象,会怎样呢?
请看以下案例
代码:
结果:
执行过程:
①客户端调用__iter__()
方法,__iter__()
方法不执行, 进入while循环.
②客户端调用__next__()
方法,__iter__()
方法执行,先执行print("准备返回第一个元素")
, 执行到yield语句, 将yield后的数据作为__next__()
方法的返回值return给item, 并且暂时离开__iter__()
方法, 继续执行while循环中的print(item)
.
③当再次调用__next__()
方法时,从上次离开的代码开始执行,再运行到下一个yield语句,return数据之后,并再次暂时离开.
④待执行完__iter__()
方法体,若再次调用__next__()
方法,会自动抛出StopIteration异常.
yield关键字迭代原理
- 原理
如果方法体中包含yield关键字,那么会自动生成迭代器对象.
生成迭代器代码的大致规则:
①将yield关键字前的代码,放到__next__()
方法中.
②将yield关键字后的数据,作为__next__()
方法的返回值.
举个例子(我们将之前的MyRange类进行改写)
代码:
结果:
若我们不定义类,而只定义包含yield的方法,来满足我们迭代的需求,该怎么做呢?
代码:
结果:
我们说这项技术,就叫做生成器generator函数.
python基础(part15)--迭代相关推荐
- Python基础(八)--迭代,生成器,装饰器与元类
目录 Python基础(八)--迭代,生成器,装饰器与元类 1 迭代 1.1 可迭代对象与迭代器 1.2 自定义迭代类型 1.3 迭代合体 2 生成器 2.1 什么是生成器 2.2 生成器表达式 2. ...
- python基础——迭代
python基础--迭代 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). 在Python中,迭代是通过for .. ...
- 第4章 基础知识进阶 第4.1节 Python基础概念之迭代、可迭代对象、迭代器
第四章 基础知识进阶 第十七节 迭代.可迭代对象.迭代器 一. 引言 本来计划讲完元组和字典后就讲列表解析和字典解析,但要理解列表解析和字典解析,就需要掌握Python的高级的类型迭代器,因此本 ...
- Python基础教程:迭代和解析
Python中的迭代是指按照元素的顺序逐个调用的过程,迭代概念包括:迭代协议.可迭代对象和迭代器三个概念. 迭代协议是指有__next__()函数的对象会前进到下一个结果,而到达系列的末尾时,则会引发 ...
- Python入门基础之迭代和列表生成式
什么是迭代 在Python中,如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们成为迭代(Iteration). 在Python中,迭代是通过 for ...
- python基础04
python基础04 python2在编译安装时,可以通过参数 -----enable----unicode=ucs2 或 -----enable--unicode=ucs4 分别用于指定使用2个字节 ...
- 刻意练习:Python基础 -- Task11. 魔法方法
背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...
- 刻意练习:Python基础 -- Task09. else 与 with 语句
背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...
- 刻意练习:Python基础 -- Task06. 字典与集合
背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...
最新文章
- spring 基于XML的申明式AspectJ通知的执行顺序
- 上帝和面向对象的七天
- 【FPGA】Spartan-6的时钟管理器(CMT)
- 【通知】2020年有三AI-CV夏季划升级倒计时,最后两天
- electron 入坑记
- java 水印 位置_Java实现图片加水印且控制位置和透明度
- C++基础与深度解析第一章:C++初探笔记
- log4j指定日志文件目录
- VS2015 自动代码补全
- 胡昊—第6次作业—static关键字、对象
- 火狐浏览器修改默认搜索引擎和添加搜索引擎
- 什么是电口模块?它和光模块有什么区别?
- Altium Designer 10 PCB简要设计及其例程
- c语言窄字符转换为宽字符,将窄字符串转换为宽字符串
- 操作Excel之“=VLOOKUP(V2,Sheet2!J:K,2)”公式解读
- “有效沟通”-你的团队做到了吗?
- Atlas (一) --------- Atlas 入门
- 【数字电子技术 Digital Electronic Technology 5】—— 组合逻辑电路设计题解题技巧归纳
- 用inkspace创建一个简单的LOGO
- 英雄联盟显示计算机内存不足怎么办,为什么我的电脑玩多玩几把LOL就显示内存不足...