从例子中来到例子中去-Python生成器

生成器

生成器是一种特殊的迭代器,它内部不需要实现__iter__方法和__next__方法。

创建生成器的方法1

之前有一道面试题目是这样的,求结果:a. [ i % 2 for i in range(10) ] b. ( i % 2 for i in range(10) )
运行出来的结果是:

[i%2 for i in range(10)]
"""
上述代码的输出结果:
[[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]]
"""
(i%2 for i in range(10))
"""
上述代码的输出结果:
<generator object <genexpr> at 0x7fc1e31a0ba0>
输出的是一个迭代器的对象
"""

即,想要创建一个生成器,最简单的方法就是将一个列表生成式的[]修改成().

创建生成器的方法2

使用yeild关键字,创建生成器。

def fib(n):
    current = 0
    a,b = 0,1
    while current < n:
        a,b = b,a+b
        current += 1
        yield a

F = fib(5)
for i in F:
    print(i)

"""
上述程序输出的结果为:
1
1
2
3
5
"""

可以从上述程序看出,此时的F = fib(5)不再是执行一个函数体了,而是返回了一个生成器对象,并且可以使用for进行迭代。
那么这里的yield关键字起到了什么作用呢?我们还是看一个例子:

def fib(n):
    current = 0
    a,b = 0,1
    while current < n:
        a,b = b,a+b
        current += 1
        print("-----1------")
        yield a
        print("-----2------")

F = fib(5)
next(F)
print("###################")
next(F)
"""
上述程序输出的结果为:
-----1------
###################
-----2------
-----1------
"""

从这个代码可以总结出,yield关键字的两个作用:

  1. 相当于运行程序中的一个断点,使得程序暂停到yield语句为止,即将生成器(函数)挂起
  2. 将yield关键字后面表达式的值作为返回值进行返回,此时可以理解为起到了return的作用
    可以使用next()函数让生成器从断点处继续执行,即唤醒生成器(函数)。

除了上面的使用next()函数进行唤醒的方式外,还可以使用send()函数来唤醒执行,并且在调用执行send()函数时可以传递一个附加数据参数。我们看一个例子:

def fib(n):
    current = 0
    a,b = 0,1
    while current < n:
        a,b = b,a+b
        current += 1
        print("-----1------")
        ret = yield a
        print(ret)
        print("-----2------")

F = fib(5)
ret = next(F)
print(ret)
print("###################")
ret = F.send("程序暂停")
print(ret)
"""
上述程序输出的结果为:
-----1------
1
###################
程序暂停
-----2------
-----1------
1
"""

我们来分析一下上述例子的一个执行流程,当程序执行到yield时程序暂停,很显然 ret = yield a这句代码在python解释器执行的时候,是当成两句话进行处理的,因此程序会执行到yield a结束,然后将yield后面的值进行返回。调用send方法,传递了一个参数,程序从断点处开始执行,send方法传递的参数,由ret接收,程序执行到下一次yield a结束。

需要注意的是,yield后面的值,是作为我们唤醒生成器函数的返回值,而send函数传递的参数,是作为执行yield a的返回值,两者要注意区分。

注:当send()函数中传递的参数为None时,其等价于next()函数。

总结

当函数的代码中出现yield关键字时,这个函数就变成了一个生成器,yield后面表达式的值作为返回值返回。
yield关键字,可以使得程序暂停,并且可以继续向下执行,而return关键字,程序执行到return,程序就执行结束了,不会在向下执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值