生成器

### 生成器

“”"
#生成器本质是迭代器,允许自定义逻辑的迭代器

#迭代器和生成器区别:
迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑

#生成器可以用两种方式创建:
(1)生成器表达式 (里面是推导式,外面用圆括号)
(2)生成器函数 (用def定义,里面含有yield)
“”"
from collections import Iterator

(1) 生成器表达式 定义一个生成器

gen = (i* 2 for i in range(1,5))
print(gen)

print(isinstance(gen,Iterator))

1.next 调用生成器

	res = next(gen)
	print(res)

2. for 调用生成器

	gen = (i* 2 for i in range(1,5))
	for i in gen:
	print(i)

3.for + next 调用生成器

gen = (i* 2 for i in range(1,5))
for i in range(2):
	res = next(gen)
	print(res)

4.用list强转,瞬间拿到所有数据

res = list(gen)
print(res)

### 生成器函数

“”"

yield 类似于 return

共同点在于:执行到这句话都会把值返回出去
不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走
而return直接终止函数,每次重头调用.
yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
“”"

from collections import Iterator

(1) 基本语法:

def mygen():
	print("one")
	yield 1

	print("two")
	yield 2

	print("three")
	yield 3

初始化生成器函数 , 返回生成器对象, 简称生成器

gen = mygen()
print(isinstance(gen , Iterator))

第一次

res = next(gen)
print(res)

第二次

res = next(gen)
print(res)

第三次

res = next(gen)
print(res)

“”"

error

res = next(gen)
print(res)

“”"

“”"

代码解析:

第一次调用, print(“one”) yield 1 , 记录当前代码执行的状态15行, 把1直接返回,等待下一次调用
res = 1 print(1)
第二次调用, 从上一次代码的位置继续向下执行,print(“two”) yield 2 , 记录当前代码执行的状态18行 , 把2直接返回,等待下一次调用
res = 2 print(2)
第三次调用, 从上一次代码的位置继续向下执行,print(“three”) yield 3 , 记录当前代码执行的状态21行 , 把3直接返回,等待下一次调用
res = 3 print(3)

如果在进行第四次调用,因为没有yield 关键字返回数据, 所以直接报错 StopIteration
“”"

(2) 优化代码

def mygen():
	for i in range(1,101):
		yield "我的球衣号码是%s" % (i)

初始化生成器函数 -> 生成器对象 -> 简称生成器

gen = mygen()

for + next 调用生成器

for i in range(50):
	res = next(gen)
	print(res)

(3) send 可以发送数据,发送给上一个yield

“”"

send

next和send区别:

next 只能取值
send 不但能取值,还能发送值

send注意点:

第一个 send 不能给 yield 传值 默认只能写None
最后一个yield 接受不到send的发送值

def mygen():
	print("start")
	res = yield 111
	print(res)

	res = yield 222
	print(res)

	res = yield 333
	print(res)

	print("end")

初始化生成器函数 -> 返回生成器对象 -> 简称生成器

gen = mygen()

第一次调用

第一次只能默认发送None,因为第一次没有上一个yield

val = gen.send(None)
print(val)

第二次调用

val = gen.send(444)
print(val)

第三次调用

val = gen.send(555)
print(val)

第四次调用 error

val = gen.send(666)

print(val)

“”"
无论是next 还是 send 都可以调用生成器里面的数据
send 不但可以调用,还可以给yield 发送值

第一次调用send , 只能发送None ,因为还没有遇到yield
代码从上到下执行, print(“start”) 遇到 res = yield 111
记录当前代码执行的状态87行,把111值返回,等待下一次调用
外面的val = 111 print(111)

第二次调用send ,把444发送给上一次保存的位置87行

yield 进行接收 res = 444 87行往下执行 print(444) 遇到 res = yield 222
记录当前代码执行的状态90行,把222值返回,等待下一次调用
外面的val = 222 print(222)

第三次调用send ,把555发送给上一次保存的位置90行

yield 进行接收 res = 555 90行往下执行 print(555) 遇到 res = yield 333
记录当前代码执行的状态93行,把333值返回,等待下一次调用
外面的val = 333 print(333)

第四次调用send , 把555发送给上一次保存的位置93行

yield 进行接收 res = 666 93行往下执行 print(666) print(“end”)
没有任何yield 返回数据 , 出现StopIteration
到此程序彻底结束.
“”"

(4)yield from : 将一个可迭代对象变成一个迭代器返回

def mygen():
	lst = ["魏小林","陈宁波","朱胜"]
	yield from lst
gen = mygen()
print(next(gen))
print(next(gen))
print(next(gen))

案例: 用生成器来写一个斐波那契数列

“”"
没有限量,没有 个数时都用生成器
生成器应用在大数据的场景中,按照需求依次取值,
切记不要直接迭代生成器所有数据
一旦数据量较大,类似于死循环
“”"

1 1 2 3 5 8 13 21 34 55 …

def mygen(maxlength):
	a = 0
	b = 1

	i = 0
	while i < maxlength:
		# print(b)
		yield b
		# 当前值 = 上上个值 + 上一个值
		a,b = b,a+b
		i+=1

gen = mygen(50)

按照需求量进行取值

for i in range(30):
	print(next(gen))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值