开发者学堂课程【Python入门 2020年版:迭代器的使用场景】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/639/detail/10422
迭代器的使用场景
内容介绍:
一、可迭代对象
二、练习使用迭代器产生斐波那契数列
三、生成器和列表区别
一、可迭代对象
还是使用上节课的代码,删除掉注释,删除掉d=Demo(10)
下的内容
刚才讲到的 for in 循环就是不断的调对象的 iter 后再 next。那是否可以手动的进行 for in 循环呢?
能否输入d._iter_()._next_()
,使用print(d._iter_()._next_())
来调用呢?
手动输入代码print(d._iter_()._next_())
十次,来运行一下结果
结果显示0 1 2 3 4 5 6 7 8 9 raise StopIteration StopIteration
for in 循环就是获取迭代器,然后调用迭代器的next方法依次往下运行,只不过 for in 循环能够在迭代完之后把 for 循环提取下来,以上内容就是所谓的可迭代对象
除此之外,与迭代器相关的还有如下:
之前讲解内置函数时提到过iter(),它是获取到可迭代对象的迭代器
一般来说demo方法不手动调用,在该代码中,第一个方法def _iter_(self):return self
通过 for in 循环来调用,除此之外,还可以这样做:输入i = iter(d) //
内置函数 iter 可以获取到一个可迭代对象的迭代器
拿到迭代器后使用 next 将迭代器传入,输入print(next(i))
,手动输入四次print(next(i))
,运行一下,结果显示
0 1 2 3
iter的本质就是调d._iter_()
,然后拿到它的迭代器,两种写法类似,还有写法:
i=d._iter_()
i.
_next_()
也相同
二、练习使用迭代器产生斐波那契数列
使用迭代器实现一个斐波拉契数列,数列中第一个数为0,第二个数为1,其后的每一个数都可由前两个数相加得到:
0,1,1,2,3,5,8,13,21,34…
创建新文件,输入代码:
class Fibonacci(object):
def _init_(self,n):
self.n=n
//要求第n个
思考比如现在要求第12个数,Fibonacci(12)如何求?
12个数:1,1,2,3,5,8,13,21,34,55,89,144
输入:f=Fibonacci(12)
for i in f:
print(i)
但是现在运行会报错,因为不是可迭代对象,拿不到可迭代数据,运行结果显示TypeError:’Fibonacci’object is not iterable
那么现在需要把它变成可迭代对象,需要重写iter方法,在self.n=n
下继续输入代码def _iter_(self):
return self //return self
就会找自己,所以还需要再添加next方法
输入def _next_(self):
pass
那么next方法如何返回呢?def_init_(self,n)
中还需要有两个初始的数字:self.num1=self.num2=1
两个数都等于1,因为最开始的两个数都是1开始的
还需要添加self.count=1
,代表轮到第几个。
目前要到12个,那么将代码 pass 修改为self.num1,self.num2=self.num2,self.num1+self.num2 //该结果就是1=2 2=1+2
return self.num1
运行起来太快,再来加入time.sleep(1)
间隔一秒,再来运行,结果显示1 2 3 5 8 13 21 34 55 89 144依次往后显示
但是存在一个问题:当第一次进入时num1=1,num2=2
,return后返回值就是num1=1;第二次时num1=2,num2=3 返回值为num2=2。所以返回值就从1开始,1 2 3 5,此时少了最前面的一个1:1,1,2,3,5
那么如何解决呢?
现在返回值不规定为self.num1
,即将代码return self.num1
改为return x
,而x=self.num1
。然后先来用一个数保存x变之前的值,把num1变之前的值保存下来:x=1,num1=1,num2=2==>x
返回的是x,x等于1,这就是第一次进入。那么第二次进入时,x=self.num1=1,num1=2,num2=3
这时再返回x,x仍然等于1
即用一个变量存储更改之前的num1,不返回改变后的值,返回更改之前的值
现在回到原代码进行修改:将代码
def_next_(self):
self.num1,self.num2=self.num2,self.num1+self.num2
time.sleep(1)
return self.num1
修改为:
def_next_(self):
x=self.num1
self.num1,self.num2=self.num2,self.num1+self.num2
time.sleep(1)
return x
运行一下,结果就显示为1,1,2,3,5,8,13,21,34,55,89,144
(此外,对于0,1,1,2,3,5…不做讲解,因为第一位是0的话,存在第0位的问题)
再修改代码
def_next_(self):
self.count +=1
if self.count < self.n:
x=self.num1
self.num1,self.num2=self.num2,self.num1+self.num2
time.sleep(1)
return x
else:
raise StopIteration
现在来运行,结果显示只有十次
观察代码,修改self.count=1
为等于0,if self.count < self.n
为<=
再来运行,结果显示1 1 2 3 5 8 13 21 34 55 89 144
那么再求f = Fibonacci(30)
,运行结果就显示前三十个数
三、生成器和列表区别
迭代器和列表区别,既然有列表,为什么还要有生成器?
现有nums=[1,2,3,4,5,6,7,8,9]
和x=range(1,10)
这两个有什么区别:比如先换成nums=[1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765]
f = Fibonacci(30)
如果使用列表那么是一个个生成,如果数值多,将需要占用大量内存,一个个显示出。若使用计算,每次使用则计算出一个数显示,不占用空间,没有任何空间保存数据。
斐波那契数列的特点就是占时间,不占用空间。调用出的数也不占用空间,比如for i in f:print(i)
打印之后没有任何地方保存i,不占用内存,每次调用函数。而列表则占空间,不占时间。以空间换时间
但是时间空间也不是绝对的,列表占空间,不占时间,效率相对高一些。但其实也不一定,如果列表中的数据量特别大,这时也是需要一定时间的。
此外要想只打印第n个数,可以输入
for i in f:
print(i)
print(‘--------------’)
print(i)
例如打印第3000个数,结果就会显示第3000个数
f=Fibonacci(3000)
for i in f:
print(i)
print(‘--------------’)
print(i)
没有办法直接求,只能一个一个进行计算,再显示出来。
for in 循环遍历之后就会显示,for in循环中也可以不写内容,写 pass,再运行,for in 循环就会直接遍历它,直接打印出最后一个数