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、执行原理

  • 相关阅读:
    LeetCode Subsets II
    LeetCode Rotate Image
    LeetCode Palidrome Number
    LeetCode Generate Parentheses
    LeetCode Maximum Subarray
    LeetCode Set Matrix Zeroes
    LeetCode Remove Nth Node From End of List
    Linux Loop设备 使用
    Linux 文件系统大小调整
    LeetCode N-Queens II
  • 原文地址:https://www.cnblogs.com/bianfengjie/p/10844899.html
Copyright © 2011-2022 走看看