真正的开发中,迭代器使用不多,生成器更常用。生成器是特殊的迭代器,为了掌握生成器的工作原理,必须先了解迭代器原理。本文章案例使用的是python语言
知识点
for循环原理
可迭代对象
迭代器原理
生成器的定义、原理和优点
生成器函数(主要了解yield的作用)
定义:每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。(循环地使用自己定义自己)
这有两道相关的经典面试题:
可以被for的条件?------ 对象具有__iter__方法,即能返回迭代器对象
不使用for循环,获取字典所有记录.
for循环语句的原理:可分为以下三个步骤
步骤1:获取迭代器对象(具有__iter__方法的对象) iterator = (1,2,3,4).__iter__() while True: try: # 步骤2:循环获取下一个元素,既是使用迭代器对象的__next__方法 item = iterator.__next__() print(item) #步骤3:处理异常 except StopIteration: break可迭代对象iterable
定义:具有__iter__函数的对象,可以返回迭代器对象。
语法
1. 创建: class 可迭代对象名称: def __iter__(self): return 迭代器 2. 使用: for 变量名 in 可迭代对象: 语句原理:
迭代器 = 可迭代对象.__iter__() while True: try: print(迭代器.__next__()) except StopIteration: break迭代器对象iterator
定义:可以被__next__函数调用并返回下一个值的对象。
语法
class 迭代器类名: def __init__(self, 聚合对象): self.聚合对象= 聚合对象 def __next__(self): if 没有元素: raise StopIteration return 聚合对象元素说明:聚合对象通常是容器对象。
作用:使用者只需通过一种方式,便可简洁明了的获取聚合对象中各个元素,而又无需了解其内部结构。
练习:将自定义类对象迭代(for 自定义类的对象)
目的:更深入地了解迭代器工作原理 """ 练习:参照下列代码,定义类MyRange实现函数range一样的功能 for i in MyRange(5): print(i) """ class RangeIteration: def __init__(self, target): self.end = target self.start = 0 def __next__(self): if self.start > self.end-1: raise StopIteration result = self.start self.start += 1 return result class MyRange: def __init__(self, end): self.end = end def __iter__(self): return RangeIteration(self.end) for i in MyRange(5): print(i)定义:能够动态(循环一次,计算一次,返回一次)提供数据的可迭代对象。
将可迭代对象一个个地提供出去作用:
优点:在循环过程中,按照某种算法推算数据,不必创建容器存储完整的结果,从而节省内存空间。数据量越大,优势越明显。
以上作用也称之为延迟操作或惰性操作,通俗的讲就是在需要的时候才计算结果,而不是一次构建出所有结果。
缺点:不能通过索引/切片操作生成器对象
第一次遍历生成器对象时,返回可迭代对象,再次执行时不会返回可迭代对象
# 延迟/惰性操作 # 优点:不会将所有结果计算出来,存储在内存中. # 缺点:通过索引/切片灵活的访问结果. # 解决:将延迟操作 转为 立即操作 result = list(result) print(result[0].name) for item in result: print(item.name) # 调用生成器函数,创建一个生成器对象 result = find03(list01) # 使用一次 for item in result: print(item.name) # 再使用一次(没有执行find03函数.) for item in result: print(item.name)生成器内置类
return 和 yield的区别:return返回一个数据,并退出方法;yield返回数据,暂时离开方法(不会退出方法)。
生成器=迭代器对象+可迭代对象(同时具有iter和next方法)
class MyGenerator: """ 等同与整数生成器range 备注:本类是生成器的"源码",只需要看,不需要写. 生成器:可迭代对象 + 迭代器对象 """ def __init__(self, stop_value): self.__stop_value = stop_value self.__start_value = 0 def __iter__(self): return self def __next__(self): if self.__start_value >= self.__stop_value: raise StopIteration() result = self.__start_value self.__start_value += 1 return result生成器函数
定义:含有yield语句的函数,返回值为生成器对象。
语法
1. 创建: def 函数名(): yield 数据 2. 调用:生成器调用须使用for语句,因为for会调用__next__ for 变量名 in 函数名(): 语句说明:
调用生成器函数将返回一个生成器对象,不执行函数体。
yield翻译为”产生”或”生成”
执行过程:
调用生成器函数会自动创建迭代器对象。
调用迭代器对象的_next_()方法时才执行生成器函数。
每次执行到yield语句时返回数据,暂时离开。
待下次调用_next_()方法时继续从离开处继续执行。
原理:生成迭代器对象的大致规则如下
将yield关键字以前的代码放在__next__方法中。
将yield关键字后面的数据作为__next__方法的返回值。
内置生成器
枚举函数enumerate
语法:for 变量 in enumerate(可迭代对象): 语句
作用:遍历可迭代对象时,可以将索引与元素组合为一个元组。
zip
语法: for item in zip(可迭代对象1, 可迭代对象2….): 语句作用:将多个可迭代对象中对应的元素组合成一个个元组,生成的元组个数由最小的可迭代对象决定。生成器表达式
定义:用推导式形式创建生成器对象。
语法:变量 = ( 表达式 for 变量 in 可迭代对象 [if 真值表达式] )
