python3 迭代器,生成器
一、迭代器
1.
什么是迭代?
迭代就是通过for循环遍历对象的每一个元素的过程。
迭代器访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问结束。迭代器只能往前不会后退。
【可以用来减少内存空间,而且还可以怎么生成数据】
2.可迭代对象
使用for...in..的循环语法从其中依次拿到数据进行使用,把这样的过程称为遍历,也叫迭代。
我们把可以通过for...in...这类语句可迭代读取一台数据供我么使用的对象称之为可迭代对象(Iterable)
3.如何判断一个对象是否是可迭代?
可以使用ininstance()来判断一个对象是不是Iterable对象;
简单示例:
from collections import Iterable
print(isinstance([],Iterable))
#######################
True
4.迭代器
一个实现了__iter__方法和__next__方法的对象,就是迭代器;
"""如果想要一个对象称为一个可迭代的对象,即可以使用for,那么必须实现__iter__方法"""
# 如果类中有该方法,那么这个类就是可迭代的,但是如果这个方法返回了另外一个类的实例对象,
# 而且这个类中有__iter__和__next__方法,那么把返回的这个对象称之为迭代器
很多时候,为了让我们自己写的类成为一个迭代器,需要在类里实现__iter__()和__next__()方法。
__author__ = 'Administrator'
from collections import Iterable
class Classmates():
def __init__(self,name):
self.name=list()
def add(self,name):
self.name.append(name)
def __iter__(self):
"""如果想要一个对象称为一个可迭代的对象,即可以使用for,那么必须实现__iter__方法"""
# 如果类中有该方法,那么这个类就是可迭代的,但是如果这个方法返回了另外一个类的实例对象,
# 而且这个类中有__iter__和__next__方法,那么把返回的这个对象称之为迭代器
return ClassmateIterable(self)
class ClassmateIterable():
"""必须有以下两个方法"""
def __init__(self,obj):
self.obj=obj
self.current_num=0
def __iter__(self):
pass
def __next__(self):
if self.current_num<len(self.obj.name):
ret=self.obj.name[self.current_num]
self.current_num+=1
return ret
else:
raise StopIteration
classmate=Classmates("张三")
classmate.add("小猪猪0")
classmate.add("小猪猪11")
classmate.add("小猪猪22")
classmate.add("小猪猪33")
for name in classmate:
print(name)
###########################
小猪猪0
小猪猪11
小猪猪22
小猪猪33
升级版:
__author__ = 'Administrator'
from collections import Iterable
class Classmates():
def __init__(self):
self.name=list()
self.current_num=0
def add(self,name):
self.name.append(name)
def __iter__(self):
"""如果想要一个对象称为一个可迭代的对象,即可以使用for,那么必须实现__iter__方法"""
# 如果类中有该方法,那么这个类就是可迭代的,但是如果这个方法返回了另外一个类的实例对象,
# 而且这个类中有__iter__和__next__方法,那么把返回的这个对象称之为迭代器
return self
def __next__(self):
if self.current_num<len(self.name):
ret=self.name[self.current_num]
self.current_num+=1
return ret
else:
raise StopIteration
classmate=Classmates()
classmate.add("小猪猪0")
classmate.add("小猪猪11")
classmate.add("小猪猪22")
classmate.add("小猪猪33")
for name in classmate:
print(name)
##########################
小猪猪0
小猪猪11
小猪猪22
小猪猪33
5.for...in...循环的本质
for item in Iterable 循环的本质就是先通过iter()函数获取可迭代对象Iterable的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束。
6.迭代器的应用
我们发现迭代器最核心的功能就是可以通过next()函数的调用来返回下一个数据值。如果每次返回的数据值不是在一个已有的数据集合中读取的,而是通过程序按照一定的规律计算生成的,那么也就意味着可以不用再依赖一个已有的数据集合,也就是说不用再将所有要迭代的数据都一次性缓存下来供后续依次读取,这样可以节省大量的存储(内存)空间。
__author__ = 'Administrator' from collections import Iterable class Fibonaqi(): def __init__(self,all_num): self.all_num=all_num self.current_num=0 self.a=0 self.b=1 def __iter__(self): """如果想要一个对象称为一个可迭代的对象,即可以使用for,那么必须实现__iter__方法""" # 如果类中有该方法,那么这个类就是可迭代的,但是如果这个方法返回了另外一个类的实例对象, # 而且这个类中有__iter__和__next__方法,那么把返回的这个对象称之为迭代器 return self def __next__(self): if self.current_num<self.all_num: ret=self.a self.a,self.b=self.b,self.a+self.b self.current_num+=1 return ret else: raise StopIteration fo=Fibonaqi(10) for num in fo: print(num,end=" ") for num in fo: print(num) ########################### 0 1 1 2 3 5 8 13 21 34
7.除了for循环能接收可迭代对象,list、tuple等也能接收。
迭代器(Iterator)和可迭代(Iterable)的区别:
-
凡是可作用于for循环的对象都是可迭代类型;
-
凡是可作用于next()函数的对象都是迭代器类型;
-
list、dict、str等是可迭代的但不是迭代器,因为next()函数无法调用它们。可以通过iter()函数将它们转换成迭代器。
-
Python的for循环本质上就是通过不断调用next()函数实现的。
二、生成器
生成器是一次生成一个值的特殊类型函数。可以将其视为可恢复函数。调用该函数将返回一个可用于生成连续 x 值的生成【Generator】,简单的说就是在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。——百度百科
在 Python中,使用yield返回的函数会变成一个生成器(generator)。 在调用生成器的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行next()方法时从当前位置继续运行。
1、创建生成器方法
第一种:把一个列表生成式[]改成(),通过圆括号可以编写生成器推导式;
第二种:通过函数来生成
第三种:在函数中有yield关键字
__author__ = 'Administrator' def create_num(all_num): print("——-——1——————") a,b=0,1 current_num=0 while current_num<all_num: # 如果一个函数中有yield语句,那么这个就不再是函数,而是一个生成器的模板 print("——————2——————") yield a print("————3————") a,b=b,a+b current_num+=1 print("————4————") obj=create_num(5) # 如果在调用create_num的时候,发现这个函数中有yield,不是调用对象,而是一个生成器对象 while True: try: ret=next(obj) print(ret) except Exception as e: break # for num in obj: # print(num) ################# ——-——1—————— ——————2—————— 0 ————3———— ————4———— ——————2—————— 1 ————3———— ————4———— ——————2—————— 1 ————3———— ————4———— ——————2—————— 2 ————3———— ————4———— ——————2—————— 3 ————3———— ————4————
使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器);
yield关键字有两点作用:
保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起;
将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用;
可以使用next()函数让生成器从断点处继续执行,即唤醒生成器(函数);
Python3中的生成器可以使用return返回最终运行的返回值。
2.唤醒生成器
next()
send()
__author__ = 'Administrator' def create_num(all_num): a,b=0,1 current_num=0 while current_num<all_num: # 如果一个函数中有yield语句,那么这个就不再是函数,而是一个生成器的模板 ret=yield a print(ret) a,b=b,a+b current_num+=1 obj=create_num(100) ret=next(obj) print(ret) # send里面的数据会传递给第七行,当做yield的结果,然后ret保存这个结果 # send的结果是下一次调用yield时 yield后面的值 ret=obj.send("哈哈哈哈") print(ret) # for num in obj: # print(num) ################## 0 哈哈哈哈 1


浙公网安备 33010602011771号