zoukankan      html  css  js  c++  java
  • 生成器

    一、概述

    我们在使用一组数据时,通常会定义一个列表,然后循环里面的元素,但是如果你只需要使用列表中的其中几个元素,其他的元素用不到,这样就会造成内存资源的浪费,所以,生成器登上历史舞台。

    生成器的作用:列表的元素按某种算法推算出来,我们在后续的循环中不断推算出后续的元素,在python中,这种一边循环一边计算的机制,称之为生成器(generator)。

    二、列表生成器

    如何给列表ff中的每个元素加1

    a=[0,1,2,3,4,5,6,7,8,9]
    for index,i in enumerate(a):
        a[index]+=1
    print (a)
    #结果
    [1,2, 3, 4, 5, 6, 7, 8, 9, 10]
    

     方法2:

    a=[i+1 for i in range(10)]
    print(a)
    

      以上这种就叫列表生成

    三、生成器

    1、创建生成器

    生成一个list

    >>> a=[i+1 for i in range(10)]
    >>> a
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    

    生成一个generator

    >>> b=(i+1 for i in range(10))
    >>> b
    <generator object <genexpr> at 0x103ca42a0>
    

    python3是通过__next__()去获得generator的下一个返回值,没有元素时,则会抛出抛出StopIteration的错误 

    >>> b.__next__()
    1
    >>> b.__next__()
    2
    >>> b.__next__()
    3
    >>> b.__next__()
    4
    >>> b.__next__()
    5
    >>> b.__next__()
    6
    >>> b.__next__()
    7
    >>> b.__next__()
    8
    >>> b.__next__()
    9
    >>> b.__next__()
    10
    >>> b.__next__()  #没有元素时,则会抛出抛出StopIteration的错误
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

     小结:①generator保存的是算法,每次调用next方法时,就会计算下一个元素的值,直到计算到最后一个元素,如果没有更多元素,则会抛出StopIteration的错误。

        ②generator只记住当前位置,它访问不到当前位置元素之前和之后的元素,只能往后访问元素,不能访问元素之前的元素。

    2、用for循环去访问generator中的元素

    用next方法去一个一个访问元素实际coding场景不适用,因为generator也是可迭代对象,实际coding使用for循环去访问,不用关心StopIteration错误

    >>> c=(i+2 for i in range(10))
    >>> c
    <generator object <genexpr> at 0x103ca4318>
    >>> for i in c:    #迭代生成器中的元素
        print(i)  

    四、函数实现生成器

    推算的算法比较复杂,用类似列表生成式的for循环无法实现时,可以使用函数来实现

    1、斐波那契数列

    实现原理:除第一个和第二个数外,任意一个数都可由前两个数相加得到:1, 1, 2, 3, 5, 8, 13, 21, 34, ...,很明显斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易。

    def fibna(max):
        n,a,b=0,0,1
        while n < max:
            print(b)
            a,b=b,a+b
            n=n+1
        return "----done---"
    fibna(5)
    

      结果:

    1
    1
    2
    3
    5
    

     这种逻辑推算非常类似一个生成器(generator),如何把一个函数转换成一个生成器?

    2、用yield函数转换为生成器(generator)

    def fibna(max):
        n,a,b=0,0,1
        while n < max:
            yield b  # 用yield替换print,把fib函数转化成一个生成器
            a,b=b,a+b
            n=n+1
        return "----done---"
    f=fibna(5)
    print(f)
    

      结果:

    <generator object fibna at 0x10ec8b750>
    

     如果一个函数中包含yield关键字,那么这个函数就不是一个普通的函数,而是一个生成器(generator)。

    注:

    ①函数是顺序执行的,遇到return语句或者最后一行函数语句就返回

    ②变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

    def fibna(max):
        n,a,b=0,0,1
        while n < max:
            yield b  # 用yield替换print,把fib函数转化成一个生成器
            a,b=b,a+b
            n=n+1
        return "----done---"
    f=fibna(5)
    print(f.__next__())
    print(f.__next__())
    print(f.__next__())
    print("--------------")
    print(f.__next__())
    print(f.__next__())#访问的是最后一个元素
    print(f.__next__()) #没有多余的元素
    

     结果:

    1
    1
    2
    ----------------
    3
    5
    Traceback (most recent call last):
      File "/Users/bianbian/PycharmProjects/test/test12.py", line 15, in <module>
        print(f.__next__()) #没有多余的元素
    StopIteration: ----done---  

    访问生成器中的元素,不用是连续的,可以中间去执行其他程序。

    return在这里的作用:当发生异常时,打印ruturn后面的值。

    def fibna(max):
        n,a,b=0,0,1
        while n < max:
            yield b  # 用yield替换print,把fib函数转化成一个生成器
            a,b=b,a+b
            n=n+1
        return "----done---"
    f=fibna(5)
    for i in f:
        print(i)
    #结果
    1
    1
    2
    3
    5
    

     可以用for循环访问 

    3、异常捕获

    def fibna(max):
        n,a,b=0,0,1
        while n < max:
            yield b  # 用yield替换print,把fib函数转化成一个生成器
            a,b=b,a+b
            n=n+1
        return "----done---"
    f=fibna(5)
    while True:
        try:
            x = f.__next__()
            print("f:",x)
        except StopIteration as e:  #当try中的程序执行错误了,才会执行except下面的代码
            print("Generator return value:",e.value)
            break
    

      结果

    f: 1
    f: 1
    f: 2
    f: 3
    f: 5
    Generator return value: ----done---
    

      捕获这个StopIteration这个异常,当try中的程序执行错误了,就会执行except下面的代码

    五、生成器执行原理

    1、执行原理

  • 相关阅读:
    关于cocoapods中的一些报错解决方案
    基于 声网Agora SDK 实现 iOS 端的多人音视频互动
    AppStore中使用IDFA后提交应用的注意事项
    iOS打包测试和发布
    LLDB常用调试命令
    MRC与ARC区别以及五大内存区
    关于友盟分享和微信支付冲突的解决办法
    iOS开发集成支付宝支付、支付宝&微信支付
    关于iOS引导页图层的相关属性类
    遇见的奇葩问题
  • 原文地址:https://www.cnblogs.com/bianfengjie/p/10844899.html
Copyright © 2011-2022 走看看