迭代
对计算机特定程序中需要反复执行的子程序*(一组指令),进行一次重复,即重复执行程序中的循环,直到满足某条件为止,亦称为迭代。
迭代对象
满足迭代条件的叫做可迭代对象,比如for循环
lst = [11,22,33,44]
for i in lst:
print(i)
#从lst中循环遍历输出值,这个过程是重复执行,叫做迭代,这个lst是可迭代对象
同理:python中的数据容器比如:list、dic、tuple、set、 string 等都是可迭代对象。
如何判断一个对象是否是可迭代对象。
1、粗暴版:就是数据对象能否用for遍历出来
2、精准判断:数据对象是否实现了__getitem__()方法(list、dic、tuple、set、 string内部都是实现了此函数方法)
3、标准程序实现 _ iter_() 方法,则是可迭代的
迭代器
迭代器跟可迭代对象去的区别在于迭代器同时实现了__iter__()和__next__()方法,迭代器对象可以通过next()函数访问
from collections.abc import Iterable#Iterable可迭代对象
from collections.abc import Iterator#迭代器
lst = []#如果一个一个对象可以用for遍历,这个对象就是可以迭代的,比如list、dic、tuple、set、string,容器对象都是可迭代对象
class ClassMates2(object):
def __init__(self):
self.names = list()
def add(self,name):
self.names.append(name)
def __iter__(self):
#如果想要一个对象称为一个可以迭代的对象,那么必须实现__iter__方法(或者__getitem__()方法)
return iter(self.names)#返回该可迭代对象的迭代器类的实例
class ClassMates3(object):
def __init__(self):
self.i = 0
self.names = list()
def add(self,name):
self.names.append(name)
def __iter__(self):
return self
def __next__(self):
if self.i<len(self.names):
self.i+=1
return self.names[self.i-1]
else:
raise StopIteration()
#如果一个恶对象称为迭代器,那么必须实现__next__方法
'''
__next__(self):相当于一个while True,每次一循环结束返回一个'return 结果',直到条件不满足结束循环
def __next__(self):
return self.names#如果这样写,将会返回无限个names,相当于while True永远不结束
'''
classmate = lst
classmate.append('老王')
classmate.append('小李')
classmate.append('张三')
#classmate.__getitem__(),list dic tuple都实现了__getitem__()方法,是可迭代对象
print(isinstance(classmate,Iterable))
for i in classmate:
print(i)
classmate = ClassMates2()
classmate.add('老王')
classmate.add('小李')
classmate.add('张三')
print(isinstance(classmate,Iterable))
print(isinstance(classmate,Iterator))#没有实现__next__(),是可迭代对象,但不是迭代器
for i in classmate:
print(i)
classmate = ClassMates3()
classmate.add('老王')
classmate.add('小李')
classmate.add('张三')
print("是否是迭代器:",isinstance(classmate,Iterator))
print(next(classmate))
print(next(classmate))
print(next(classmate))
生成器
生成器是特殊的迭代器,生成器主要用于生成数据,集成了iter()和next()函数,迭代器主要用于数据的迭代输出。
常用python生成器函数有yield()
def create_num(all_num):
a, b = 0, 1
current_num = 0
while current_num < all_num:
a, b = b, a+b
current_num+=1
yield a
def create_num1(all_num):#这是非常规写法,主要用来提现yield和return的区别
a, b = 0, 1
current_num = 0
while current_num < all_num:
yield b#区分一下 yield和return的区别
a, b = b, a+b
current_num+=1
return 'over'#这句一般不要,没有用
'''
如果一个函数中有yield关键字,则这个函数不再是一个函数,就是一个生成器模版
如果在调用create_num的时候,发现这个函数中有yield对象,那么此时,不是调用函数,而是创建一个生成器对象
'''
a = create_num(10)#创建一个生成器对象
for i in a:
print('a:',i)
b = create_num1(10)#创建一个生成器对象
print('b:',next(b))
print('b:',next(b))
print('b:',next(b))
print('b:',next(b))
while True:
try:
print(next(b))
except Exception as error:
print(error.value)#可以获取return的值
break
总结
为什么有一系列容器还需要迭代器和生成器,因为如list等容器对象存储的是生成的大量数据,如果数量巨大的话会占用很多内存空间,而迭代器存储的是生成数据的方式,要的时候再生成,节约内存空间,但是同样的会消耗时间
就跟做馒头一样,如果开始说需要100个馒头,但是不知道什么时候吃,如果提前做好了需要空间存储,所以只要直到馒头怎么做就行了,主要知道了做馒头的方法,需要的时候边做边吃,这样节约了空间,但是响应的浪费了事件,迭代器也是这样,用迭代器生成数据,只有在用next()的时候才会计算生成,