• 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出现新的语法
  • 相关阅读:
    Java实现荷兰国旗问题
    Java实现荷兰国旗问题
    QTcpSocket 对连接服务器中断的不同情况进行判定(六种情况,其中一种使用IsNetworkAlive API方法)
    怀旧老游戏
    我的第一个Chrome插件:天气预报应用
    ddd
    Android 反编译工具
    ASP.NET MVC局部视图
    jQuery类库的设计
    jquery+html三级联动下拉框
  • 原文地址:https://www.cnblogs.com/yinzhengjie/p/10962910.html
Copyright © 2020-2023  润新知