Python入门篇-生成器函数

              Python入门篇-生成器函数

                                      作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 

 

一.生成器概述

1>.生成器generator

  生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yield关键字得到一个生成器函数,调用这个函数得到一个生成器对象

2>. 生成器函数

复制代码
  函数体中包含yield语句的函数,返回生成器对象

  生成器对象,是一个可迭代对象,是一个迭代器

  生成器对象,是延迟计算,惰性求值的

  包含yield语句的生成器函数生成生成器对象的时候,生成器函数的函数体不会立即执行

  next(generator)会从函数的当前位置向后执行到之后碰到的第一个yield语句,会弹出值,并暂停函数执行

  再次调用next函数,和上一条一样的处理过程
  
  没有多余的yield语句能被执行,继续调用next函数,会抛出StopIteration异常
  
复制代码

3>.编写一个生成器函数样例

复制代码
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 
 7 """
 8 关于生成器函数的相关说明:
 9 
10     在生成器函数中,使用多个yield语句,执行一次后会暂停执行,把yield表达式的值返回
11     
12     再次执行会执行到下一个yield语句
13     
14     return 语句依然可以终止函数运行,但return语句返回值不能被捕获到
15     
16     return 会导致无法继续获取下一个值,抛出StopIteration异常
17     
18     如果函数没有显示的return语句,如果生成器函数执行到结尾,一样会抛出StopIteration异常哟
19 
20 """
21 def gen():
22     print('line 1')
23     yield 1
24     print('line 2')
25     yield 2
26     print('line 3')
27     return 3
28 
29 next(gen())
30 
31 next(gen())
32 
33 g = gen()
34 
35 print(next(g))
36 print(next(g))
37 
38 # print(next(g))              #报错:StopIteration: 3,因为已经没有多余的yield语句啦,上面已经被调用两次了
39 
40 print(next(g, 'End'))         #如果没有元素就给个缺省值
41 
42 
43 
44 #以上代码执行结果如下:
45 line 1
46 line 1
47 line 1
48 1
49 line 2
50 2
51 line 3
52 End
复制代码

 

二.生成器应用

1>.无限循环

复制代码
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 
 7 
 8 def counter():
 9     i = 0
10     while True:
11         i += 1
12         yield i
13 
14 def inc(c):
15         return next(c)
16 
17 c = counter()           #这是一个生成器对象
18 
19 print(inc(c))
20 print(inc(c))
21 
22 
23 
24 #以上代码输出结果如下:
25 1
26 2
复制代码

2>.计数器

复制代码
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 
 7 def inc():
 8     def counter():
 9         i = 0
10         while True:
11             i += 1
12             yield i
13     c = counter()
14     return lambda : next(c)  #这里返回的是匿名函数
15 
16 foo = inc()
17 print(foo())
18 print(foo())
19 
20 
21 
22 #以上代码输出结果如下:
23 1
24 2
复制代码

3>.处理递归问题

复制代码
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 
 7 
 8 def fib():
 9     x = 0
10     y = 1
11     while True:
12         yield y
13         x, y = y, x+y
14 
15 foo = fib()
16 
17 for _ in range(5):
18     print(next(foo))
19 
20 for _ in range(100):
21     next(foo)
22 
23 print(next(foo))
24 
25 
26 #以上代码输出结果如下:
27 1
28 1
29 2
30 3
31 5
32 6356306993006846248183
复制代码
复制代码
#!/usr/bin/env python
#_*_coding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
#EMAIL:y1053419035@qq.com


pre = 0
cur = 1
print(pre,cur,end=" ")

def fib(n,pre=0,cur=1):
    pre,cur = cur,pre + cur
    print(cur,end=" ")
    if n == 2:
        return
    fib(n-1,pre,cur)



fib(106)
以上代码改写成递归方式戳我~
复制代码

4>.协程(coroutine)

复制代码
(1)生成器的高级用法

(2)比进程,线程轻量级

(3)是在用户空间调度的一种实现

(4)Python3 asyncio就是协程实现,已经加入到标准库

(5)Python3.5 使用async,await关键字直接原生支持协程
协程调度器实现思路:
    有2个生成器A,B
    next(A)后,A执行到了yield语句暂停,然后去执行next(B),B执行到yield语句也暂停,然后再次调用next(A),再调用next(B),周而复始,就实现了调度的效果
    可以引入调度的策略来实现切换的方式

(6)协程就是一种非抢占式调度
复制代码

 

三.yield from

复制代码
 1 #!/usr/bin/env python
 2 #_*_coding:utf-8_*_
 3 #@author :yinzhengjie
 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
 5 #EMAIL:y1053419035@qq.com
 6 
 7 
 8 def inc():
 9     for x in range(1000):
10         yield x
11 
12 foo = inc()
13 print(next(foo))
14 print(next(foo))
15 print(next(foo))
16 
17 print("*" * 20 + "我是分割符" +"*" * 20)
18 
19 """
20     以上代码可以使用yield from代码改写,等价于下的代码:
21 """
22 def inc():
23     yield from range(1000)
24 
25 bar = inc()
26 print(next(bar))
27 print(next(bar))
28 print(next(bar))
29 
30 
31 
32 #以上代码输出结果如下:
33 0
34 1
35 2
36 ********************我是分割符********************
37 0
38 1
39 2
复制代码
复制代码
#!/usr/bin/env python
#_*_coding:utf-8_*_
#@author :yinzhengjie
#blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/
#EMAIL:y1053419035@qq.com


"""
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)

foo = inc(10)
print(next(foo))
print(next(foo))



#以上代码执行结果如下:
0
1
yield from是Python 3.3出现新的语法
复制代码

 

posted @   尹正杰  阅读(741)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2018-06-02 Hadoop基础-Apache Avro串行化的与反串行化
点击右上角即可分享
微信分享提示