python基础(part15)--迭代(python 列表迭代)

网友投稿 464 2022-08-31


python基础(part15)--迭代(python 列表迭代)

鄙人学习笔记 开发工具:Spyder

文章目录

​​迭代​​

​​举个例子1​​​​举个例子2​​​​for循环原理​​

​​可迭代对象iterable​​

​​举个例子1​​​​举个例子2​​​​举个例子3​​

​​迭代器对象iterator​​

​​yield关键字迭代原理​​​​举个例子(我们将之前的MyRange类进行改写)​​

迭代

每一次对过程的重复为一次”迭代”,而每一次迭代得到的结果,会作为下一次迭代的初始值。例如:循环获取容器中的元素。

举个例子1

可以看出,我们得到的结果和for循环遍历这个列表,得到的结果相同。

如果我们多写一个​​iterator.__next__()​​,会怎样呢?

会报错 python警告我们,要 Stop Iteration, 停止迭代!

举个例子2

我们再利用以下方法迭代:

我们发现,我们没有用for循环,也拿到了可迭代对象(列表)内元素。以上两个例子演示了for循环原理。

for循环原理

现在,我们对上面例子中的代码进行解释,进而阐述一下for循环原理

①获取迭代器对象

②获取下一个元素(迭代)

最后,我们总结一下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对象会怎样呢?我们看看下面这个例子。

举个例子2

接下来,我们就要让SkillManager可迭代!

我们先要在SkillManager类里增加一个​​__iter__()​​​方法,使他变为可迭代对象。 这个​​__iter__()​​​被调用后,应该返回一个迭代器类对象SkillIterator。这个迭代器类对象里应该有一个​​__next__()​​​方法,用于返回下一个元素。在​​__next__()​​方法里应该抛出一个索引越界异常,当被迭代对象全部迭代完后,再获取下一个元素,则会抛出异常。具体情况,我们看看下面的代码。

不错!可迭代对象内元素全部拿到了。

备注1:由上面的过程我们也可以看出,可迭代对象不会直接return它的元素,而是由迭代器return了可迭代对象内的元素。

备注2:若我们用for循环,则它也会先获取迭代器对象,获取完迭代器对象后,再用迭代器对象不断的调用​​__next__()​​方法,直到迭代器对象抛出异常,for再进行异常处理。

举个例子3

参照下例代码,定义MyRange类,实现相同效果:

class MyRangeIterator: def __init__(self, stop): self.stop = stop self.start = 0 def __next__(self): if self.start + 1 > self.stop: raise StopIteration() temp = self.start self.start += 1 return tempclass MyRange: def __init__(self, stop): self.stop = stop def __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 StopIteration return 聚合对象内元素

说明

聚合对象通常是容器对象。

作用

使用者只通过一种方式(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的方法,来满足我们迭代的需求,该怎么做呢?


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:python基础(part14)--异常处理(关于python的异常及处理,描述错误的是)
下一篇:python基础(part12)--模块(python里模块)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~