当前位置 : 主页 > 编程语言 > python >

python基础(part15)--迭代

来源:互联网 收集:自由互联 发布时间:2022-06-15
鄙人学习笔记 开发工具:Spyder 文章目录 ​​迭代​​ ​​举个例子1​​ ​​举个例子2​​ ​​for循环原理​​ ​​可迭代对象iterable​​ ​​举个例子1​​ ​​举个例子2​​

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



文章目录

  • ​​迭代​​
  • ​​举个例子1​​
  • ​​举个例子2​​
  • ​​for循环原理​​
  • ​​可迭代对象iterable​​
  • ​​举个例子1​​
  • ​​举个例子2​​
  • ​​举个例子3​​
  • ​​迭代器对象iterator​​
  • ​​yield关键字迭代原理​​
  • ​​举个例子(我们将之前的MyRange类进行改写)​​



迭代

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

举个例子1

创建一个列表:
python基础(part15)--迭代_for循环
再输入以下代码:

python基础(part15)--迭代_生成器_02
结果:
python基础(part15)--迭代_生成器_03

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

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

python基础(part15)--迭代_python_04
结果:

python基础(part15)--迭代_python_05

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

举个例子2

还是创建原来的列表:
python基础(part15)--迭代_python_06

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

python基础(part15)--迭代_for循环_07
第39行代码这样写,其实相当于在except之后写了个异常基类:
python基础(part15)--迭代_生成器_08

结果:
python基础(part15)--迭代_迭代器_09

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

for循环原理

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

①获取迭代器对象

python基础(part15)--迭代_python_10
我们说,可迭代对象,是具有​​​__iter__()​​​方法,可以返回迭代器的对象。所以以后我们评判一个对象是不是可迭代对象时,就可以看一看,这个对象有没有​​__iter__()​​方法,如果有这个方法,则说明,这个对象是可以被迭代的。

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

python基础(part15)--迭代_python_11
有迭代器之后,我们就可以迭代了,​​​__next__()​​​的过程就是在迭代的过程,有​​__next__()​​我们就可以拿到下一个元素。

③停止迭代(StopIteration错误)
python基础(part15)--迭代_迭代_12

最后,我们总结一下for循环原理:

①获取迭代器对象
②循环迭代(调用迭代器的​​​__next__()​​​方法)
③捕获StopIteration异常

  • 小问题

问:能够被for循环的条件是什么?
答:具有​​​__iter__()​​方法的对象。

  • 例子1

使用while + 迭代器,获取元祖(“小白”, “小黄”, “大白”)中所有元素。

代码:

t01 = ("小白", "小黄", "大白")
iterator = t01.__iter__()

while True:
try:
item = iterator.__next__()
print(item)

except:
break

结果:
python基础(part15)--迭代_python_13

  • 例子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

结果:

python基础(part15)--迭代_for循环_14

备注:使用迭代器迭代字典,拿到的是字典的key

可迭代对象iterable

  • 定义

具有​​__iter__()​​函数的对象,可以返回迭代器对象.

  • 语法

创建可迭代对象:

class 可迭代对象名称:
def __iter__(self):
return 迭代器

使用可迭代对象:

for 变量名 in 可迭代对象:
语句
  • 原理
迭代器 = 可迭代对象.__iter__()

while True:
try:
print(迭代器.__next__())

except StopIteration:
break

举个例子1

首先创建两个类:
python基础(part15)--迭代_for循环_15
再创建SkillManager对象,并试着迭代此对象的成员变量skills:
python基础(part15)--迭代_迭代_16
得到结果:
python基础(part15)--迭代_生成器_17
结果得到了列表内的各个Skill对象。

但是,如果我们只迭代SkillManager对象会怎样呢?我们看看下面这个例子。

举个例子2

利用例子1,创建的两个类:
python基础(part15)--迭代_python_18
再创建SkillManager对象,并试着迭代此对象:
python基础(part15)--迭代_迭代_19
运行:
python基础(part15)--迭代_python_20
报错!且python提示我们SkillManager对象是个不可迭代的对象。

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

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

现在我们看一下SkillManager类:
python基础(part15)--迭代_python_21
再看一下SkillIterator类:
python基础(part15)--迭代_迭代_22
创建对象,并开始利用for循环原理,进行迭代:

python基础(part15)--迭代_迭代器_23
我们再运行一下,看一下运行结果:

python基础(part15)--迭代_生成器_24

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

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

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

举个例子3

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

python基础(part15)--迭代_迭代器_25
代码:

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 temp


class MyRange:
def __init__(self, stop):
self.stop = stop

def __iter__(self):
# 创建迭代器对象
return MyRangeIterator(self.stop)

iterator = MyRange(5)
for item in iterator:
print(item)

结果:
python基础(part15)--迭代_迭代_26

备注:谁要被for,谁要就有​​__iter__()​​​方法,这个方法可以获取迭代器,迭代器内部具体怎么写?看需求!迭代器中有​​__next__()​​,可以返回下一个元素。

迭代器对象iterator

  • 定义

可以调用​​__next__()​​函数,并返回下一个值得对象。

  • 语法
class 迭代器类名::
def __init__(self, 聚合对象):
self.聚合对象 = 聚合对象

def __next__(self):
if 没有元素:
raise StopIteration

return 聚合对象内元素
  • 说明

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

  • 作用

使用者只通过一种方式(for循环),便可以简洁明了获取聚合对象中的各个元素,而又无需了解可迭代对象的内部存储结构。

==备注!==若我们在​​__iter__()​​方法内不返回自己创建的迭代器对象,而用yield关键字自动生成迭代器对象,会怎样呢?

请看以下案例

代码:
python基础(part15)--迭代_迭代_27

python基础(part15)--迭代_python_28
结果:
python基础(part15)--迭代_for循环_29
执行过程:

①客户端调用​​__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类进行改写)

代码:

python基础(part15)--迭代_python_30

python基础(part15)--迭代_for循环_31

结果:

python基础(part15)--迭代_for循环_32

若我们不定义类,而只定义包含yield的方法,来满足我们迭代的需求,该怎么做呢?

代码:
python基础(part15)--迭代_生成器_33

结果:
python基础(part15)--迭代_for循环_34
我们说这项技术,就叫做生成器generator函数.

【文章原创作者:高防ip http://www.558idc.com/gfip.html欢迎留下您的宝贵建议】
上一篇:python基础(part14)--异常处理
下一篇:没有了
网友评论