• python--生成器


    生成器


    一、概念

      python中的生成器(generator)保存的是算法,只有当真正调用需要的值的时候才会去计算出值。它是一种惰性计算(lazy evaluation)。

    二、列表生成式

    定义一个列表

    a = [0,1,2,3,4,5,6,7,8,9]
    

    除了上面直接定义外,我们还可以使用列表生成式:

    a = [i for i in range(10)]
    print(a)
    
    #输出
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    

      

    三、生成器

      通过上面的列表生成式,我们可以直接创建一个列表。但是受到内存的限制,列表的容量是有限的。而且如果我们创建了一个包含数百万元素的列表,并且只需要用到前面几个元素,那就有大部分空间浪费了。

      所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断的推算后续的元素?这样就不必创建完整的list,从而节省大量的空间。在pyhong中,一边循环一边计算的机制,称为生成器:generator。

      要创建一个generator有很多种方法,我们可以直接将列表生成式改成生成器:

    >>> a = (i for i in range(10))
    >>> a
    <generator object <genexpr> at 0x0000024897F6B4C0>
    

    3.1 列表生成式和生成器

    a = (i for i in range(100000000))
    
    b = [i for i in range(100000000)]
    

      a的生成时间是瞬时的,并且不会占用什么内存空间。因为生成器根本就没有生成所需的内容,只有在访问的时候才会生成相应的值

    3.2 访问生成器

    • 生成器只保留当前位置的值,直接访问 a[5]是没有值的(报错)
    • 只有一个__next()__方法
    • 只能一个一个取值,并且只能往后取值,不能返回取前面的值

    使用循环来取值:

    a = (i for i in range(10))
    for i in a:
        print(i)
    
    #输出
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    

      

    使用__next()__方法取值:

    a = (i for i in range(10))
    print(a.__next__())
    print(a.__next__())
    print(a.__next__())
    print("插入")
    print(a.__next__())
    print(a.__next__())
    
    #输出
    0
    1
    2
    插入
    3
    4
    

      每调用一个__next()__方法,我们就能取到一个值,并且我们只能往后取值。生成器能记住当前位置的值,但是并不知道前后位置的值,这也是生成器能够节省内存的原因。只有调用到该位置时才会生成相应的数据。

    四、yield将函数转换成生成器

      利用列表只能实现一部分的功能,一下复杂的运行就不能通过列表生成式这样的来实现了。但是我们可以将一个函数变成生成器。

    斐波那契函数:

    def fib(n):
        a = 1
        b = 1
        number = 0
        while number < n:
            print(b)
            a,b = b,a+b
            number += 1
    

    将该函数变成生成器只需要将print(b) 改为 yield b

    def fib(n):
        a = 0
        b = 1
        number = 0
        while number < n:
            #print(b)
            yield b
            a,b = b,a+b
            number += 1
    
    f = fib(10)
    print(f.__next__())
    print(f.__next__())
    print(f.__next__())
    print(f.__next__())
    
    #输出
    1
    1
    2
    3
    

      

    五、生成器结束

      生成器不会把结果保存在一个系列中,而是保存生成器的状态,在每次进行迭代时返回一个值,直到遇到StopIteration异常结束。

    def fib(n):
        a = 0
        b = 1
        number = 0
        while number < n:
            #print(b)
            yield b
            a,b = b,a+b
            number += 1
        return '--done--'
    
    f = fib(6)
    while True:
        try:
            x = next(f)
            print(x)
        except StopIteration as e:
            print('Generator return value:',e.value)
            break
    
    #输出
    1
    1
    2
    3
    5
    8
    Generator return value: --done--
    

      

  • 相关阅读:
    我在ZZ这八年
    安装JBpm
    用程序实现HTTP压缩和缓存
    (转)WPF Custom Control Dependency Property Gotcha
    开发一个Word的代码高亮插件
    (转)Getting rid of the DSL model explorer
    (翻译)LearnVSXNow! #16 创建简单的编辑器2
    对 COM 组件的调用返回了错误 HRESULT E_FAIL。
    Word中使用代码高亮插件
    使用HttpWebRequest post数据时要注意UrlEncode
  • 原文地址:https://www.cnblogs.com/bigberg/p/6714172.html
Copyright © 2020-2023  润新知