迭代的概念
上一次输出的结果为下一次输入的初始值,重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值
很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!??¤
QQ群:961562169
什么是迭代
- 访问集合元素的一种方式
- 可通过 for 循环遍历的对象 叫可迭代对象
- 数字类型 不可迭代
判断对象是否可迭代: isinstance( ) 判断是否为 Iterable(可迭代对象)
from collections.abc import Iterable
#print(isinstance(要判断的对象,数据类型))
print(isinstance([1,2,3,4],Iterable))
是可迭代对象 返回 True
不是可迭代对象 返回 False
可迭代的对象
内置iter方法的,都是可迭代的对象。 list是可迭代对象,dict是可迭代对象,set也是可迭代对象。
迭代器 Iterator
1.为什么要有迭代器?
对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式。
2.迭代器定义:
迭代器:可迭代对象执行iter方法,得到的结果就是迭代器,迭代器对象有next方法
它是一个带状态的对象,他能在你调用next()方法的时候返回容器中的下一个值,任何实现了iter和next()方法的对象都是迭代器,iter返回迭代器自身,next返回容器中的下一个值, 如果容器中没有更多元素了,则抛出StopIteration异常
迭代器的遍历循环:
class MyIterator(object):
def __init__(self,list):
self.list=list
self.xiabiao=0
def __iter__(self): #获取迭代器,自身就为迭代器,所以返回自身
return self
def __next__(self): #获取迭代器中的下一个数据
if self.xiabiao < len(slef.list):
item=self.list[self.xiabiao]
self.xiabiao += 1
return item
else:
raise StopIteration #抛出 停止迭代异常
a=[11,22,33,44,55]
my=MyIterator(a)
for i in my:
print(i)
for…in… 循环的本质:
先通过iter( )获取可迭代对象的迭代器,然后对获取到的迭代器 不断使用next( )方法来获取下一个值,并赋值给一个变量,当遇到 StopIteration 循环结束
while True:
try:
print(next( ))
except StopIteration:
break
迭代器的应用场景: 斐波那契数列
class Fei(object):
def __init__(self,n):
self.n=n
self.weizhi=0 记录位置
self.num1=0 定义初始变量
self.num2=1
def __iter__(self): 获取迭代器,此类本身就是迭代器,返回自身
return self
def __next__(self): 获取迭代器中的下一个数据
if self.weizhi < self.n:
num=self.num1
self.num1,self.num2=self.num2,self.num1+self.num2
self.weizhi += 1
return num
else:
raise StopIteration
fei=Fei(10)
for i in fei:
print(i)
查看迭代器数据的三种方法: for 、list、tuple
#for
for i in fei:
print(fei)
#list
print(list(fei))
#tuple
print(tuple(fei))
生成器 generator
1.定义
- 生成器(generator)是一个特殊的迭代器,它的实现更简单优雅,yield是生成器实现next()方法的关键。它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回。
- 也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态。
- 生成器可以理解为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己的内置iter方法)
- 在Python中,一边循环,一边计算的机制,称为生成器。
yield的功能:
- 相当于为函数封装好iter和next
- return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行
- 保存当前运行状态,暂停执行
- 将 yield 关键字 后面表达式的值,作为返回值返回,可理解为起到了return的作用
生成器的作用
- 通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的。
- 而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
- 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?
- 这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
生成器工作原理
-
生成器是这样一个函数,它记住上一次返回时在函数体中的位置。
-
对生成器函数的第二次(或第 n 次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。
-
生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造中的位置。
-
生成器是一个函数,而且函数的参数都会保留。
-
迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的
yield生成器运行机制
在Python中,yield就是这样的一个生成器。
- 当你问生成器要一个数时,生成器会执行,直至出现 yield 语句,生成器把yield 的参数给你,之后生成器就不会往下继续运行。
- 当你问他要下一个数时,他会从上次的状态开始运行,直至出现yield语句,把参数给你,之后停下。如此反复
- 在python中,当你定义一个函数,使用了yield关键字时,这个函数就是一个生成器
- 它的执行会和其他普通的函数有很多不同,函数返回的是一个对象,而不是你平常所用return语句那样,能得到结果值。如果想取得值,那得调用next()函数
- 每当调用一次迭代器的next函数,生成器函数运行到yield之处,返回yield后面的值且在这个地方暂停,所有的状态都会被保持住,直到下次next函数被调用,或者碰到异常循环退出。
为什么说生成器是一种迭代器?
Python 判断一个对象是否是迭代器的标准是看这个对象是否遵守迭代器协议 ,判断一个对象是否遵守迭代器协议主要看两个方面:
- 对象首先得实现 iter 和 next 方法
- 其次iter 方法必须返回它自己
而生成器恰好满足了这两个条件(可以自己写个生成器,然后调用生成器的这两个方法试试)。我们平常还会经常碰到另外一个概念:可迭代对象。可迭代对象就是可迭代的对象,可迭代的对象就是说我们可以从这个对象拿到一个迭代器。在 Python 中,iter 方法可以帮我们完成这个事情,也就是说,可迭代对象和迭代器满足这样一个关系:iter(iterable) -> iterator。
在 Python 中,list 是个可迭代对象,所以我们经常会写这样的代码:
l = [1, 2, 3]
for element in l:
print(element)
但你想过为什么我们可以这么写吗?为啥在 c 语言里面,我们访问数组元素的时候,必须要通过 index?
因为:list 是个可迭代对象,我们在 Python 中使用 for … in 时,Python 会给我们生成一个迭代器对象,而如上所说:迭代器是个数据流,它可以产生数据,我们一直从里面取数据就好了,而不需要我们在代码中维护 index,Python 已经通过迭代器给我们完成了这个事情。
构建生成器:
将列表推导式的方括号 改为 小括号
g=(i for i in range(1,11))
print(g)
使用 yield
构建斐波那契数列
def fei(n):
num1,num2=0,1
weizhi=0
while weizhi < n :
num=num1
num1,num2=num2,num1+num2
weizhi += 1
yield num
print(list(fei(10)))
唤醒生成器:send( )、next( )、 __next__( )
send( )
ret=fei(10)
a=ret.send(None)
print(a)
next( )
ret=fei(10)
while True:
try:
print(next(ret))
except StopIteration:
break
生成器和迭代器之间的区别
在使用生成器时,我们创建一个函数;在使用迭代器时,我们使用内置函数iter()和next()。 在生成器中,我们使用关键字‘yield’来每次生成/返回一个对象。 生成器中有多少‘yield’语句,你可以自定义。 每次‘yield’暂停循环时,生成器会保存本地变量的状态。而迭代器并不会使用局部变量,它只需要一个可迭代对象进行迭代。 使用类可以实现你自己的迭代器,但无法实现生成器。 生成器运行速度快,语法简洁,更简单。 迭代器更能节约内存。
1257

被折叠的 条评论
为什么被折叠?



