> 文档中心 > 【python核心】生成器(面试题常考)

【python核心】生成器(面试题常考)

文章目录

  • 生成器generator
    • 定义
  • 生成器函数
    • 定义
    • 练习
    • 内置生成器
    • 练习
  • 生成器表达式
    • 定义
    • 练习
  • 总结

生成器generator

定义

能够动态(循环一次计算一次返回一次)提供数据的可迭代对象

作用:在循环过程中,按照某种算法推算数据,不必创建容器存储完整的结果,从而节省内存空间。数据量越大,优势越明显。

以上作用也称之为延迟操作或惰性操作,通俗的讲就是在需要的时候才计算结果,从而不是一次构建出所有结果。

"""    yield --> 生成器    生成器 = 可迭代对象 + 迭代器    简述生成器与迭代器的区别(面试题常考)"""#生成器的原理class MyGenerator:    """ 生成器 = 可迭代对象 + 迭代器    """    def __init__(self,stop_value): self.begin = 0 self.stop_value = stop_value    def __iter__(self): return self    def __next__(self): if self.begin >= self.stop_value:     raise StopIteration temp = self.begin self.begin += 1 return tempdef my_range(stop_value):    number = 0    while number < stop_value: yield number number += 1my01 = my_range(5)print(type(my01),dir(my01))print(id(my01.__iter__()),id(my01))for item in my01:    print(item)

生成器函数

定义

含有yield语句的函数,返回值为生成器对象。

练习

从列表[4,5,566,7,8,10]中选出所有偶数。
方法1:结果存入另外一个列表中
方法2:使用生成器实现

方法一:list01 = [4,5,566,7,8,10]result = []for item in list01:    if item % 2 == 0: result.append(item)print(result)方法二:list01 = [4,5,566,7,8,10]def get_even():    for item in list01: if item %2 ==0:     yield itemmy01 = get_even()for item in my01:    print(item)

内置生成器

  1. 枚举函数enumerate
    作用:遍历可迭代对象时,可以将索引与元素组合为一个元组。
  2. zip
    作用:将多个可迭代对象中对应的元素组合成一个个元组。

练习

练习1:定义生成器函数my_enumerate,实现下列现象,将元素与索引合成一个元组。

"""    练习"""# #原理# list01 = [ 3,4,55,6,7]# for item in enumerate(list01):#     #(索引,元素)#     print(item)## #实际开发写的# for index,element in enumerate(list01):#     print(index, element)def my_enumerate(iterable_target):    #方法1:    index = 0    for item in iterable_target: yield (index,item) index += 1    # 方法2# for index in range(len(iterable_target)):    #     yield (index,iterable_target[index])list01 = [3,4,55,6,7]for index,element in my_enumerate(list01):    print(index, element)

练习2:定义生成器函数my_zip,实现下列现象。将多个列表的每个元素合成一个元组。【暂不考虑长度不相等的情况。】

# list02 =["孙悟空","猪八戒","唐僧","沙僧"]# list03 =[ 101,102,103,104]# for item in zip(list02,list03):#     print(item)# def my_zip(iterable_target01,iterable_target02):#     for i in range(len(iterable_target01)):#  yield (iterable_target01[i],iterable_target02[i])# # list02 =["孙悟空","猪八戒","唐僧","沙僧"]# list03 =[ 101,102,103,104]# for item in my_zip(list02,list03):#     print(item)def my_zip(*args):    #根据星号元组形参args第一个参数的长度生成索引(len(args[0])    for i in range(len(args[0])): list_result = [] for item in args:    list_result.append(item[i]) yield tuple(list_result)list02 =["孙悟空","猪八戒","唐僧","沙僧"]list03 =[ 101,102,103,104]for item in my_zip(list02,list03):    print(item)

生成器表达式

定义

用推导式形式创建生成器对象。

"""    生成器表达式"""list01 = [3, "54", True,6, "76",1.6,False,3.5]def find01():    for item in list01: if type(item) == int:     yield itemre = find01()for item in re:    print(item)#生成器表达式#此时没有计算,更没有结果re = (item for item in list01 if type(item) == int)#不做#一次循环,一次计算,一个结果for item in re:    print(item)#列表推导式#此时已经完成所有计算,得到所有结果。re = [item for item in list01 if type(item) == int]#一次性做完#只是获取所有结果for item in re:    print(item)#总结#变量= [itme for item in 可迭代对象 if 条件] 列表推导#变量= {k,v for k,v in可迭代对象 if 条件} 字典推导#变量= item for item in 可迭代对象 if 条件 } 集合推导#变量= (item for item in 可迭代对象if 条件) 生成器表达

练习

练习1:获取列表中所有字符串。
要求:使用生成器函数/生成器表达式/列表推导式完成。

list01 = [3, "54", True,6, "76",1.6,False,3.5]def find02():    for item in list01: if type(item) == str:     yield itemre = find02()for item in re:    print(item)re = (item for item in list01 if type(item) == str)for item in re:    print(item)re = [item for item in list01 if type(item) == str]for item in re:    print(item)

练习2:获取列表中所有小数。
要求:使用生成器函数/生成器表达式/列表推导式完成。

list01 = [3, "54", True,6, "76",1.6,False,3.5]def find03():    for item in list01: if type(item) == float:     yield itemfor item in find03():    print(item)for item in (item for item in list01 if type(item) == float):    print(item)for item in [item for item in list01 if type(item) == float]:    print(item)

练习3:

class SkillData:    def __init__(self,id,name,atk_ratio,duration): """     技能信息 :param id:技能编号 :param name:技能名称 :param atk_ratio: 攻击比例 :param duration: 持续时间 """ self.id = id self.name = name self.atk_ratio = atk_ratio self.duraftion = durationlist_skill = [    SkillData(101, "乾坤大挪移",5, 10),    SkillData(102, "降龙十八掌", 8, 5),    SkillData(103, "葵花宝典",10,2),]

要求如下:
(1) 获取攻击比例大于6的所有技能。
(2)获取持续时间在4–11之间的所有技能。
(3)获取技能编号是102的技能。
(4)获取技能名称大于4个字并且持续时间小于6的所有技能。
要求:使用生成器函数/生成器表达式完成。

class SkillData:    def __init__(self,id,name,atk_ratio,duration): """     技能信息 :param id:技能编号 :param name:技能名称 :param atk_ratio: 攻击比例 :param duration: 持续时间 """ self.id = id self.name = name self.atk_ratio = atk_ratio self.duraftion = duration    def __str__(self): return "技能数据是:%d,%s,%d,%d"%(self.id,self.name,self.atk_ratio,self.duraftion)list_skill = [    SkillData(101, "乾坤大挪移",5, 10),    SkillData(102, "降龙十八掌", 8, 5),    SkillData(103, "葵花宝典",10,2),]print("----------------1-------------------")def find01():    for item  in list_skill: if item.atk_ratio > 6 :     yield itemfor item in find01():    print(item)print("----------------1-------------------")for item in  (item for item  in list_skill  if item.atk_ratio > 6 ):    print(item)print("----------------2-------------------")def find02():    for item in list_skill: if   4 < item.duraftion < 11:     yield itemfor item in find02():    print(item)print("----------------2-------------------")for item in  (item for item  in list_skill   if   4 < item.duraftion < 11 ):    print(item)print("----------------3-------------------")def find03():    for item in list_skill: if  item.id == 102:     return item    #编号唯一,返回一个用returnre = find03()print(re)print("----------------4-------------------")def find04():    for item in list_skill: if  len(item.name)> 4 and item.duraftion <6 :     yield itemfor item in find04():    print(item)print("----------------4-------------------")#不建议使用生成器表达式# for item in  (item for item  in list_skill   if  len(item.name)> 4 and item.duraftion <6  ):#     print(item)

总结

迭代可迭代对象:具有__iter__迭代器生成器class 可迭代对象:def __iter__()创建迭代器对象class 迭代器:def __next__()返回一个元素如果没有元素,则抛出一个StopIteration异常。for 变量 in 可迭代对象:变量得到的就是__next__方法返回值原理:iterator = 可迭代器对象.__iter__()while True:try:变量 = iterator.__next__()except:break启发:调用next,执行一次,计算一次,返回一次。生成器函数:def 函数名():...yield 数据...#调用方法不执行生成器 = 函数名()#for 生成器 才执行函数体for item in 生成器:...优势:延迟/惰性操作生成器源码:class 生成器:def __iter__():return selfdef __next__():定义着yield以前的代码返回yield后面的数据生成器与迭代器渊源:生成器通过yield标记变成迭代代码,for循环调用__next__,而__next__内部定义着yield以前的代码,返回yield后面的数据,__next__就是做迭代器工作。...

Python学习手册