python中的生成器

目录

一、生成器函数

练习1:创建一个生成器,并且调用

练习2:创建一个生成器,并且设置返回

练习3:创建生成器,定义多个yield 值

练习4:创建生成器,生成200万桶方便面。

二、send()

练习1:使用send()方法给yield传递参数

练习2:计算移动平均值

三、yield form

练习1:使用for循环取出g1生成器中所有的值。

练习2:使用 yield from 遍历出可变数据类型中的数据。

四、生成器表达式

练习1:使用生成器表达式,进行数数。

练习2:list()函数底层会默认调用g的__next__()方法

五、生成器作用


生成器的本质就是迭代器。

生成器包括两种:生成器函数和生成器表达式

一、生成器函数

 

一个包含yield关键字的函数就是一个生成器函数。并且yield不能和return共用,并且yield只能用在函数内。

 

(1).生成器函数执行之后会得到一个生成器作为返回值,并不会执行函数体。

(2).执行了__next__()方法之后才会执行函数体,并且获得返回值。

(3).next()内置方法,内部调用生成器函数的__next__()方法。

(3).yield和return相同的是可以返回值,但是不同的是yield 不会结束函数

练习1:创建一个生成器,并且调用

# 1、创建一个生成器,并且调用
def generator():
    print('lalala')
    yield
    print('hhh')
    yield

g = generator()
# 注意:调用生成器,函数体是不会执行的,会返回一个生成器对象
print(g)

输出为:

<generator object generator at 0x0000000002145830>

调用__next__()方法或者是next()函数可以执行函数体。遇到yield停止

 

g.__next__()  # 调用__next__()方法执行函数体。遇到yield停止
g.__next__()
# 或是
# next(g)
# next(g)

输出为:

lalala
hhh

练习2:创建一个生成器,并且设置返回

 

def generator():
    print('---->>>')
    yield '这是返回值'


g = generator()
ret = next(g)
print(ret)

ret变量接收返回值,然后打印

---->>>
这是返回值

练习3:创建生成器,定义多个yield 值

 

def generator():
    print('---->')
    yield 1
    print('---->>>')
    yield 2


g = generator()
ret = next(g)
print(ret)
ret2 = next(g)
print(ret2)

输出为:

---->
1
---->>>
2

练习4:创建生成器,生成200万桶方便面。

def ksf():
    for i in range(1, 2000000):
        yield '正在生产第%d桶方便面' % i


g = ksf()
print(next(g))
print(next(g))

输出为:

正在生产第1桶方便面
正在生产第2桶方便面

从上代码中我们可以发现,在yield的影响下,调动一次才运行一次。我们使用for循环试一下

for fbm in g :
    print(fbm)

它就一直在输出了,如

 

二、send()

send 获取下一个值的效果和next()基本一致,只是在获取下一个值的时候,给上一yield的位置传递一个数据。

使用send的注意事项:

(1).第一次使用生成器的时候 是用next获取下一个值

(2).最后一个yield不能接受外部的值

 

练习1:使用send()方法给yield传递参数

def generator():
    print('aa')
    content = yield 1
    print(content)
    print('---->')
    yield 2


g = generator()
ret=next(g)
print(ret)
g.send('hello')

输出为:

aa
1
hello
---->

1、如上代码所示,当程序运行到next(g)时,程序输出了'aa'

2、然后碰到了第一个yield,程序停止运行了,并返回了值'1',我们用ret接收了这个返回的值,然后我们print(ret),就输出了1

3、之后程序运行了g.send('hello'),把'hello'返回了第一个yidle,而我们用变量content接收了yield ‘hello',同时程序继续运行print(content),输出了'hello',然后继续下行,print('---->'),输出了---->

4、代码碰到了第二个yield,程序停止运行

 

练习2:计算移动平均值

def fun_avg():
    count = 1
    avg = 0
    total = 0
    while True:
        get_num = yield avg
        total += get_num
        avg = total / count
        count += 1


g=fun_avg()
next(g)
print(g.send(10))
print(g.send(20))
print(g.send(30))

输出为:

10.0
15.0
20.0

1、如上代码所示,当print(next(g))运行时,程序运行碰到了yield,返回了avg的值即'0',程序停止了,然后被print函数输出了

2、然后print(g.send(10))运行时,把'10'返回了yield,程序继续运行,所以get_num=10,total=10,avg=10,count=1+1=2,又因为在while循环里,所以程序继续从头开始走,然后碰到了yield,此时avg=10,yield返回了avg并停止了运行,被print函数输出了

3、print(g.send(20))运行时,把'20'返回了yield,程序继续运行,所以get_num=20,total=10+20=30,avg=30/2=15,count=2+1=3,然后又循环一次,碰到了yield,此时avg=15,所以yield返回了avg并停止了运行,被print函数输出

4、print(g.send(30))运行时,把'30'返回了yield,程序继续运行,所以get_num=30,total=30+30=60,avg=60/3=20,count=3+1=4,然后又循环一次,碰到了yield,此时avg=20,所以yield返回了avg并停止了运行,被print函数输出

 

三、yield form

yield from 循环遍历容器类型

练习1:使用for循环取出g1生成器中所有的值。

def g1():
    for i in range(3):
        yield i

    for j in 'ab':
        yield j


g = g1()
for gg in g:
    print(gg)
print(list(g1()))

输出为:

0
1
2
a
b
[0, 1, 2, 'a', 'b']

如上代码所示,for循环是遍历出g1()中的值来。

而print(list(g1()))则是直接将g1()中的值赋值到列表中。

 

练习2:使用 yield from 遍历出可变数据类型中的数据。

 

def g1():
    yield from range(3)
    yield from 'ab'


g = g1()
for gg in g:
    print(gg)

print(list(g1()))

 

四、生成器表达式

格式:将列表推导式[] 改成 () 即可。

 

练习1:使用生成器表达式,进行数数。

g=(i for i in range(10))
print(g)
for j in g:
    print(j,end=' ')

输出为:

<generator object <genexpr> at 0x0000000001DF58E0>
0 1 2 3 4 5 6 7 8 9 

练习2:list()函数底层会默认调用g的__next__()方法

def demo():
    for i in range(4):
        yield i


g = demo()
# list()函数底层会默认调用g的__next__()方法
print(list(g))

输出为:

[0, 1, 2, 3]

 

五、生成器作用

可以实现多任务(协程-->模拟并发)

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值