python生成器能用while吗_Python——生成器详解

1. 什么是生成器

利用迭代器,我们可以在每次迭代获取数据(通过next()方法)时按照特定的规律进行生成。但是我们在实现一个迭代器时,关于当前迭代到的状态需要我们自己记录,进而才能根据当前的状态生成下一个数据。为了达到记录当前的状态,并配合next()函数进行迭代使用,我们可以采用更加简便的语法,即生成器。生成器是一种特殊的迭代器

2.创建生成器的两种方法

2.1 类似列表解析

我们都清楚列表解析,举个例子:

data = [x*2 for x in range(5)]

for i in data:

print(i,end=' ')

# result

0,2,4,6,8

当我们将列表解析中的 “[]” 换成 " () "时,就创建了一个生成器,即:

data = (x*2 for x in range(5))

print(data)

# result

at 0x0000027968E71D48>

# 考虑生成器时特殊的迭代器,故我们可以调用next()方法获取下一个值

print(next(data))

# result

0

2.2 函数中使用yield,则函数为生成器

函数中没有yield关键字的还是原本的函数,函数中一旦出现yield关键字,函数不再是函数,而是生成器

def test():

yield 10

m = test()

print(m)

# result 可以看到函数返回的是一个生成器对象

# 调用next()获取下一个值

next(m) # 10

2.3 用斐波那契例子体验yield的作用

yield的作用1)充当return作用

2)保存程序的运行状态,并且暂停程序执行

3)当调用next时,可以继续唤醒程序从yield的位置继续向下执行

用生成器生成斐波那契数列

代码思路:1)定义斐波那契生成器(定义函数的方式)

2)用next()方法生成数字

def fib(n):

a = 1

b = 1

current_index = 0

while current_index < n:

data = a

a,b = b,a+b

current_index += 1

yield data

fib = fib(5) # 创建了一个生成器

print(next(fib)) # 1

print(next(fib)) # 1

print(next(fib)) # 2

print(next(fib)) # 3

print(next(fib)) # 5

print(next(fib)) # StopIteration Error

这个例子很简单,我们重点理解yield在该函数中执行的流程:fib = fib(5)该语句将参数5传入到生成器内,开始进入生成器内部执行代码

当执行第一个print(next(fib))语句时,此时data = 1,则yield将data=1返回(这里体现了yield充当return的功能),此时程序停在了 yield data 这条语句上

当执行第二个print(next(fib))语句时,此时程序在上一次的暂停处被唤醒,也即在yield data处被再次唤醒,程序接着执行,接着进行while循环,直到再次遇见yield data。这里体现了yield的保存程序的运行状态,并且暂停程序执行的作用,因为每次生成的数值都不一样,说明程序保存了上一次的状态

以此类推,每次程序到yield data语句都会被终止暂停,直到再次调用next()方法,程序从上一次终止处继续执行,再次遇到yield,又暂停,反反复复,直到循环条件不满足或者自动抛出StopIteration Error结束

为了更加清晰地认识到yield作用,我们为上述代码增加几行print语句:

def fib(n):

a = 1

b = 1

current_index = 0

print('111111111111111111111') # add this

while current_index < n:

data = a

a,b = b,a+b

current_index += 1

print('2222222222222222222') # add this

yield data

print('3333333333333333333') # add this

fib = fib(5) # 创建了一个生成器

next(fib) # 程序停在yield data 处

# result

'11111111111111111111111'

'22222222222222222222222'

# 当我们再次调用next方法时,程序在yield处被唤醒,继续执行

next(fib)

# result

'33333333333333333333333'

'22222222222222222222222'

3. 生成器中使用return问题

考虑上面斐波那契生成器,我们因为规定了while循环所以可以使生成器停止运行,加入我们没有while循环来控制生成器,那么可以一致用next()方法去生成,从而进行无终止地迭代。那么我们怎么让生成器停止推出呢?

使用return终止生成器:一旦遇到return,则终止生成器,异常信息为return的内容

def fib(n):

a = 1

b = 1

current_index = 0

while current_index < n:

data = a

a,b = b,a+b

current_index += 1

yield data

return '终止迭代器'

fib = fib(5) # 创建了一个生成器

print(next(fib)) # 输出1,此时程序执行到了yield data处

print(next(fib)) # 从yield data处继续执行,遇到return抛出StopIteration: 终止迭代器

一般我们再写生成器时,yield 数据左边都会有一个接收值x,这是为了使用生成器对象的send函数,接下来介绍send函数:

def fib(n):

a = 1

b = 1

current_index = 0

while current_index < n:

data = a

a,b = b,a+b

current_index += 1

x = yield data # 用x接收值

print(x)

return '终止生成器'

fib = fib(5) # 创建了一个生成器

print(next(fib)) # 输出1,此时程序执行到了yield data处,注意执行的是等号右边,左边没有执行

print(next(fib)) # 执行yield data 左边,但是此时x并没有值,所以为None.

# result

1

None

StopIteration: 终止迭代器

那么x怎么才能有值呢,有值以后又能干什么呢?

3.1 使用生成器对象的函数send()send也可以将程序唤醒,并且send函数接收一个参数用来传递给x,这是next函数做不到的地方,next函数不能给x传递值。

def fib(n):

a = 1

b = 1

current_index = 0

while current_index < n:

data = a

a,b = b,a+b

current_index += 1

x = yield data # 用x接收值

print(x)

return '终止生成器'

fib = fib(5) # 创建了一个生成器

print(next(fib)) # 程序停在yield data 处

print(fib.send(2)) # 程序从yield data 处被唤醒继续执行,并且将1传递给x

# result

1

2

StopIteration: 终止迭代器

所以我们可以用send函数来控制生成器退出:

def fib(n):

a = 1

b = 1

current_index = 0

while current_index < n:

data = a

a,b = b,a+b

current_index += 1

x = yield data # 用x接收值

print(x)

if x == 2:

return '终止生成器'

fib = fib(5) # 创建了一个生成器

print(next(fib)) # 程序停在yield data 处

print(fib.send(1)) # x值为1,不退出生成器

print(fib.send(2)) # x值为2,退出生成器

# result

1 # 这是生成的数据

1 # print(x)产生的1

1 # 这是生成的数据

2 # print(x)产生的2

StopIteration: 终止迭代器

小结:return作用:结束生成器的运行

send作用:生成器对象.send(传递给生成器的值)

小编这里还有python学习资料(书籍视频),需要学习资料的小伙伴可以私信小编“资料”

喜欢的小伙伴点赞关注转发一下~。

注:本文取自网络,如有侵权,请联系小编。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值