05-生成器:基本使用

目标

  • 能够用两种方法创建生成器

1. 生成器

利用迭代器,我们可以在每次迭代获取数据(通过next()方法)时按照特定的规律进行生成。但是我们在实现一个迭代器时,关于当前迭代到的状态需要我们自己记录,进而才能根据当前状态生成下一个数据。为了达到记录当前状态,并配合next()函数进行迭代使用,我们可以采用更简便的语法,即生成器(generator)生成器是一类特殊的迭代器

2. 创建生成器方法1

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

In [15]: L = [ x*2 for x in range(5)]

In [16]: L
Out[16]: [0, 2, 4, 6, 8]

In [17]: G = ( x*2 for x in range(5))

In [18]: G
Out[18]: <generator object <genexpr> at 0x7f626c132db0>

In [19]:

image-20180724234757911

创建 L 和 G 的区别仅在于最外层的 [ ] 和 ( ) , L 是一个列表,而 G 是一个生成器。我们可以直接打印出列表L的每一个元素,而对于生成器G,我们可以按照迭代器的使用方法来使用,即可以通过next()函数、for循环、list()等方法使用。

In [19]: next(G)
Out[19]: 0

In [20]: next(G)
Out[20]: 2

In [21]: next(G)
Out[21]: 4

In [22]: next(G)
Out[22]: 6

In [23]: next(G)
Out[23]: 8

In [24]: next(G)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-24-380e167d6934> in <module>()
----> 1 next(G)

StopIteration:

In [25]:
In [26]: G = ( x*2 for x in range(5))

In [27]: for x in G:
   ....:     print(x)
   ....:     
0
2
4
6
8

In [28]:

3. 创建生成器方法2

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

我们仍然用上一节提到的斐波那契数列来举例,回想我们在上一节用迭代器的实现方式:

def fibonacci(n):
    # 定义斐波那契数列的前2个值
    a = 0
    b = 1

    # 定义当前的位置
    current_index = 0
    print("------------1111-----------")

    while current_index < n:
        # 定义要返回的值
        result = a
        # 生成新的 a、b值
        a, b = b, a+b
        # 让当前值+1
        current_index += 1
        print("-----------2222----------")
        yield result

        print("-----------3333------------")


# 生成器,生成斐波那契数列
fib = fibonacci(5)

value = next(fib)
print(value)

value = next(fib)
print(value)
运行结果:

------------1111-----------
-----------2222----------
0
-----------3333------------
-----------2222----------
1

Process finished with exit code 0
  • 使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器)

  • yield关键字有两点作用:

保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起

将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用