好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Python函数之生成器及生成器函数

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函数之生成器及生成器函数的详细内容...

  阅读:21次