Python - 生成器

什么是生成器?

一种特殊的迭代器

如何创建生成器?

  • 列表解析的[ ] 换为()
>>> a = (x for x  in range(1, 10))
>>> type(a)
<class 'generator'>

>>> b = [ x for x in range(1,10)]
>>> type(b)
<class 'list'>

  • 函数中使用了yield 关键字

    跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

    在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

    调用一个生成器函数,返回的是一个迭代器对象。

>>> def func1():
...     yield 10
...
>>> f = func1()
>>> type(f)
<class 'generator'>
>>> next(f)
10
>>> next(f)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

生成器实现斐波那契数列

"""
斐波那契数列的特点:
第一二项为1, 从第三项起每一项为前两项的和
定义b列记录前两项的和,a等于b,
a, b = b, a + b
"""
def fibnacci(n):
    # 定义斐波那契数列前两个值
    a = 1
    b = 1

    current_index = 0
    while current_index < n:
        # data 为生成的斐波那契数值
        data = a
        a, b = b, a + b
        current_index += 1
        yield data

fi = fibnacci(5)
for var in fi:
    print(var, end=' ')   # out: 1 1 2 3 5


yield 关键字的作用

  • 充当return
  • 保存程序的运行状态,并暂停程序的执行
  • 当next的时候,可以唤醒程序的状态并从yield的位置向下执行
"""

"""
def fibnacci(n):
    # 定义斐波那契数列前两个值
    a = 1
    b = 1
    print('-----111-----')
    current_index = 0
    while current_index < n:
        # data 为生成的斐波那契数值
        data = a
        a, b = b, a + b
        current_index += 1
        print('-----222-----')
        yield data
        print('-----333-----')

fi = fibnacci(5)
print(next(fi))
print(next(fi))

"""
输出:
-----111-----
-----222-----
1
-----333-----
-----222-----
1

生成器结合return和send使用


send() 方法可以给生成器传递一个值,通过该值结合return

可以控制生成器结束,执行到return后,生成器会停止迭代抛出异常

Demo:

def fibnacci(n):
    # 定义斐波那契数列前两个值
    a = 1
    b = 1
    print('-----111-----') # 只会执行一次
    current_index = 0
    while current_index < n:
        # data 为生成的斐波那契数值
        data = a
        a, b = b, a + b
        current_index += 1
        print('-----222-----')
        flag =  yield data  # flag 为send()函数传的值
        print(f"flag : {flag}")
        if flag == 1:
            return "我是return, 我可以结束yield"

if __name__ == '__main__':
    fi = fibnacci(5)
    print(next(fi))
    print(next(fi))
    try:
        fi.send(1)
    except Exception as e:
        print(e)
"""
-----111-----
-----222-----
1
flag : None
-----222-----
1
flag : 1
我是return, 我可以结束yield
"""
posted @ 2022-01-12 16:43  chuangzhou  阅读(30)  评论(0编辑  收藏  举报