这里是一段防爬虫文本,请读者忽略。
本文原创首发于CSDN,作者IDYS
博客首页:https://blog.csdn.net/weixin_41633902/
本文链接:https://blog.csdn.net/weixin_41633902/article/details/107807691
未经授权,禁止转载!恶意转载,后果自负!尊重原创,远离剽窃!
生成器
00. 概述
- 生成器
generator
- 生成器指的是生成器对象,可以由生成器表达式得到,也可以使用
yield
关键字得到一个生成器函数,调用这个函数得到一个生成器对象
- 生成器指的是生成器对象,可以由生成器表达式得到,也可以使用
- 生成器函数
- 函数体中包含
yield
语句的函数,返回生成器对象 - 生成器对象,是一个可迭代对象,是一个迭代器
- 生成器对象,是延迟计算、惰性求值
- 函数体中包含
迭代器一定是可迭代对象,可迭代对象不一定是迭代器
01. 生成器对象举例
- 代码演示1
def inc():
for i in range(5):
yield i
print(type(inc))
print(type(inc()))
x = inc()
print(type(x))
print(next(x))
for m in x:
print(m, end="* ")
for m in x:
print(m, "**")
- 运行结果
<class 'function'>
<class 'generator'>
<class 'generator'>
0
1* 2* 3* 4*
- 代码演示2
my_func = (i for i in range(10))
print(type(my_func))
print(next(my_func))
print(next(my_func))
- 运行结果
<class 'generator'>
0
1
- 普通的函数调用
fn()
,函数会立即执行完毕,但是生成器函数可以使用next
函数多次执行 - 生成器函数等价于生成器表达式,只不过生成器函数可以更加的复杂
- 代码演示3
def gen():
print("1")
yield 1
print("2")
yield 2
print("3")
return 3
print(next(gen()))
print(next(gen()))
g = gen()
print("***********************************")
print(next(g))
print(next(g))
# print(next(g)) # 会报StopIteration 错误
print(next(g, "end"))
- 运行结果
1
1
1
1
***********************************
1
1
2
2
3
end
- 在生成器函数中,使用多个
yield
语句,执行一次后会暂停执行,把yield
表达式的值返回 - 再次执行会执行到下一个
yield
语句 return
语句依然可以终止函数运行,但return
语句的返回值不能被获取到return
会导致无法继续获取下一个值,抛出StopIteration
异常- 如果函数没有显示的
return
语句,如果生成器函数执行到结尾,一样会抛出StopIteration
异常
02. 生成器
- 生成器函数
- 包含
yield
语句的生成器函数生成 生成器对象的时候,生成器函数的函数体不会立即执行 next(generator)
会从函数的当前位置向后执行到之后碰到的第一个yield
语句,会弹出值,并且暂停函数执行- 再次调用
next
函数,和上一次一样的处理过程 - 没有多余的
yield
语句能被执行,继续调用next
函数,会抛出StopIteration
- 包含
- 演示1
def fn():
i = 0
while True:
i = i + 1
yield i
def inc(c):
return next(c)
def inc_two():
c = fn()
return next(c)
c = fn()
print(inc(c))
print(inc(c))
print(inc_two()) # 显示1
print(inc_two()) # 显示1
print(inc_two()) # 显示1
- 运行结果
1
2
1
1
1
lambda
表达式是匿名函数return
返回的是一个匿名函数
03. 生成器应用:处理斐波那契数
- 演示代码
def fib():
x = 0
y = 1
while True:
yield y
y, x = x+y, y
foo = fib()
for _ in range(10):
print(next(foo), end=" ")
- 运行结果
1 1 2 3 5 8 13 21 34 55
04. 生成器应用
- 协程
coroutine
- 生成器的高级用法
- 比进程、线程轻量级
- 是在用户空间调度函数的一种实现
Python3
,asyncio
就是协程实现,已经加入到标准库Python3.5
使用async
,await
关键字直接原生支持协程- 协程调度器实现思路
- 有
2
个生成器A
、B
next(A)
后,A
执行到了yield
语句暂停,然后去执行next(B)
,B
执行到yield
语句也暂停,然后再次调用next(A)
,再调用next(B)
,再周而复始,就实现了调度的效果- 可以引入调度的策略来实现切换的方式
- 有
- 协程是一种非抢占式调度
05. yield from
- 演示代码
def inc():
for x in range(1000):
yield x
def inc_two():
yield from range(1000)
foo = inc()
foo1 = inc_two()
print(next(foo))
print(next(foo))
print(next(foo))
print("***************************")
print(next(foo1))
print(next(foo1))
print(next(foo1))
- 运行结果
0
1
2
***************************
0
1
2
-
yield from
是Python 3.3
出现的新语法yield from iterable
是for item in iterable:yield item
形式的语法糖- 从可迭代对象中一个个拿元素
-
演示代码
def counter(n):
for x in range(n):
yield x
def inc(n):
yield from counter(n)
foo1 = inc(10)
print(next(foo1))
print(next(foo1))
print(next(foo1))
print(next(foo1))
- 运行结果
0
1
2
3
写在最后的话:
- 无论每个知识点的难易程度如何,我都会尽力将它描绘得足够细致
- 欢迎关注我的CSDN博客,IDYS’BLOG
- 持续更新内容:
linux基础 | 数据通信(路由交换,WLAN) | Python基础 | 云计算 - 如果你有什么疑问,或者是难题。欢迎评论或者私信我。你若留言,我必回复!
- 虽然我现在还很渺小,但我会做好每一篇内容。谢谢关注!