Python函数之生成器及生成器函数
收录于话题
#Python入门
27个
概要:
1.生成器和生成器函数;2.yield;3.取值gen.__next__() ,gen.send()4.转换list(gen)
知识点:
生成器:本质是迭代器,写法和迭代器不一样,但是用法和迭代器一样
生成器函数:函数中带有yield,执行生成器函数的时候返回生成器,而不是执行这个函数.
在python中有三种方式来获取生成器:
1. 通过生成器函数
2. 通过各种推导式来实现生成器
3. 通过数据的转换也可以获取生成器(range())
一.认识生成器及生成器函数
先看一个普通的函数,如下
1.def fun():
print("我叫赛利亚")
return "西岚的武士刀" #返回值
ret=fun() #走到这时, 打印我叫赛利亚,并把西岚的武士刀返给ret,但此时并没有打印
print(ret) #此时打印西岚的武士刀
再看生成器函数,此时只需要将return,换成yield,但运行结果完全不一样了.
2.def fun():
print("我叫赛利亚")
yield "西岚的武士刀" #yield一样和return也是返回值的意思,看见yield 就肯定是生成器函数
ret=fun() #走到这时,上面的函数不执行,不会打印出我叫赛利亚. 而是获取生成器,ret 为生成器
print(ret) #此时打印的为<generator object fun at 0x0000000002146830>
ret.__next__() #此时为执行生成器函数,输出 我叫赛利亚,并没有西岚的武士刀,因为没有值接收它
如果将ret.__next__()改为s =ret.__next__() print(s),此时结果为我叫赛利亚 西岚的武士刀
或者直接写成print(ret.__next__()) ,结果一样.此时的s =ret.__next__()即接收
二.生成器及生成器函数用法及作用
1.yield是分段来执行一个函数. return呢? 直接停止执行函数.
def fun():
print("打开手机")
print("打开陌陌")
yield "手机"
print("约妹子")
print("出来喝喝茶")
yield "电脑"
gen = fun() #得到一个生成器
print(gen.__next__()) #第一次执行打印 打开陌陌 手机
print(gen.__next__())#第二次执行打印 约妹子 出来喝喝茶 电脑
print(gen.__next__())#当程序运行完最后一个yield. 那么后面继续进行__next__()程序会报错.StopIteration
2.订购衣服:,节省内存
def fun():
for i in range(1,100):
yield "衣服%s" %i
gen =fun() #得到一个生成器,此时函数不执行
print(gen.__next__())#执行生成器函数, 衣服1
print(gen.__next__())#再次执行生成器函数 衣服2
50件50件的拿衣服
def fun ():
lst =[]
for i in range(1,1000):
lst.append("衣服%s" %i)
if len(lst) % 50 ==0:
yield lst
lst =[] #如果没有此步骤,第二次拿的时候,还会有前50件衣服
gen =fun() #创建一个生成器,函数此时不执行
print(gen.__next__()) #先拿50件
print(gen.__next__()) #在从51件后拿到100件
假如为如下的写法
def fun():
lst = []
for i in range(1,1000):
lst.append("衣服%s" %i)
return lst
c =fun()
print(c)
此时将1000件衣服全部都拿来,会非常占用内存,而生成器函数用多少那多少,非常节省内存.
3.取值:gen.__next__() 下一个,gen.send()也可以是下一个的效果,同时可以给上一个yield传值,(不给下面的传值 第一次执行不能用send())
def func():
print("韭菜盒子")
a = yield "哇哈哈"
print("肉包子",a)
b = yield "脉动"
print("锅包肉",b)
yield "冰红茶"
gen = func() #创建一个生成器,函数不执行
print(gen.__next__()) # 第一次执行 韭菜盒子 哇哈哈
print(gen.__next__()) #第二次执行 ,肉包子 None 脉动 a没有被传值.
假如此时给a传值,此时用到send
def func():
print("韭菜盒子")
a = yield "哇哈哈"
print("肉包子",a)
b = yield "脉动"
print("锅包肉",b)
yield "冰红茶"
gen = func() #创建一个生成器,函数不执行
print(gen.__next__()) # 韭菜盒子 哇哈哈
print(gen.send("刘伟")) #肉包子 刘伟 脉动
print(gen.send("刘德华"))#锅包肉 刘德华 冰红茶
print(gen.send("刘伟")) #此时没有了会报错StopIteration
4.可迭代的
def fun():
yield "麻花藤"
yield "马云"
yield "刘强东"
yield "李彦宏"
gen = fun() #拿到生成器,不执行函数
print(gen.__next__()) #麻花藤
print(gen.__next__()) #马云
print(gen.__next__()) #刘强东
print(gen.__next__()) #李彦宏
print("__iter__" in dir(gen)) #查看其是否可迭代. True
迭代,因此可以执行for循环,即
def fun():
yield "麻花藤"
yield "马云"
yield "刘强东"
yield "李彦宏"
gen = fun() #拿到生成器,不执行函数
for el in gen:
print(el) #结果和上面的一致
或者进行数据的转换,转换成列表
lst =list(gen)
print(lst) # ['麻花藤', '马云', '刘强东', '李彦宏']
目前学到的从生成器拿数的方法有:1,__next__ 2.send()3.for循环 4,数据转化list,不要以为gen=fun是拿数,他其实是创建一个生成器
5 补充一个知识点:
def func():
lst=["三国演义","水浒传","西游记","红楼梦"]
def func():
# for el in lst:
# yield el
yield from lst #等价于上面,知道即可
print(list(func())) #['三国演义', '水浒传', '西游记', '红楼梦']
查看更多关于Python函数之生成器及生成器函数的详细内容...