zoukankan      html  css  js  c++  java
  • (十)python3 生成器

    生成器(generator):在 Python 中,不必创建完整的 list,从而节省大量的空间。一边循环一边计算的机制。

    创建一个 generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的 [] 改成 () ,就创建了一个 generator:

    >>> L = [x * x for x in range(10)]
    >>> L
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> g = (x * x for x in range(10))
    >>> g
    <generator object <genexpr> at 0x1022ef630>
    

      如果要一个一个打印出来,可以通过 next() 函数获得 generator 的下一个返回值:

    >>> next(g)
    0
    >>> next(g)
    1
    >>> next(g)
    4
    ...
    ...
    >>> next(g)
    81
    >>> next(g)
    Traceback (most recent call last):File "<stdin>", line 1, in <module> StopIteration
    

      generator 保存的是算法,每次调用 next(g) ,就计算出 g 的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration 的错误。

    常用的方法是使用for 循环,因为 generator 也是可迭代对象:

    >>> g = (x * x for x in range(10))
    >>> for n in g:
    ... print(n)
    ...
    0
    1
    4
    9
    16
    25
    36
    49
    64
    81
    

      

    generator 非常强大。如果推算的算法比较复杂,用类似列表生成式的 for循环无法实现的时候,还可以用函数来实现。

      比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:  

    1, 1, 2, 3, 5, 8, 13, 21, 34, ...
    

      斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

    def fib(max):
      n, a, b = 0, 0, 1
      while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
      return 'done'

    >>> fib(6)
    1
    1
    2
    3
    5
    8
    'done'

      

      

    上面的函数和 generator 仅一步之遥。要把 fib 函数变成generator,只需要把 print(b) 改为 yield b 就可以了:

    def fib(max):
      n, a, b = 0, 0, 1
      while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
      return 'done'
    

      如果一个函数定义中包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个 generator:

    >>> f = fib(6)
    >>> f
    <generator object fib at 0x104feaaa0>
    

      函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成generator 的函数,在每次调用 next() 的时候执行,遇到 yield 语句返回,再次执行时从上次返回的 yield 语句处继续执行。

    for 循环调用 generator 时,发现拿不到 generator 的 return 语句的返回值。如果想要拿到返回值,必须捕获 StopIteration 错误,返回值包含在 StopIteration 的 value 中:

    >>> g = fib(6)
    >>> while True:
    ...  try:
    ...    x = next(g)
    ...       print('g:', x)
    ...  except StopIteration as e:
    ...    print('Generator return value:', e.value)
    ...        break
    ...
    g: 1
    g: 1
    g: 2
    g: 3
    g: 5
    g: 8
    Generator return value: done   
    

     

    小结
      generator 是非常强大的工具,在 Python 中,可以简单地把列表生成式改成 generator,也可以通过函数实现复杂逻辑的 generator。


      要理解 generator 的工作原理,它是在 for 循环的过程中不断计算出下一个元素,并在适当的条件结束 for 循环。对于函数改成的 generator 来说,遇到 return 语句或者执行到函数体最后一行语句,就是结束 generator的指令, for 循环随之结束。

     

  • 相关阅读:
    python学习笔记 day14 各种推导式
    python学习笔记 day14 生成器表达式
    python学习笔记 day14 生成器进阶(二)
    python学习笔记 day14 生成器进阶
    python学习笔记 day13 迭代器
    python 学习笔记 day12 作业讲解--员工信息表
    PAT L3-020 至多删三个字符
    2019省赛训练组队赛3.26周二---FJUT 2016
    PAT L3-007 天梯地图
    POJ 2234 Matches Game
  • 原文地址:https://www.cnblogs.com/a-ant/p/10940634.html
Copyright © 2011-2022 走看看