python[初学] yield的用法以及在斐波那契数列中的简单应用


```python
在这里插入代码片
```'''
这个程序的输出结果
starting...
4
********************
res: None
4
'''
# 一个解释yield函数的小程序
def foo():
    print("starting...")
    while True:
        res = yield 4
        print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(next(g))
'''
下面我们来分析一下这个程序的内在逻辑
程序开始执行后 因为 foo函数中有yield关键字,所以foo函数并不会真正的执行
而是先得到一个生成器也就是g
直到调用next方法,foo函数开始正式执行,先输出一个starting 然后进入while循环
在循环内部,先执行'yield=4'这个语句 给函数一个返回值4
在主函数内输出4
然后下一条语句输出20个*
再一次调用foo函数
这次和上一次不同
从yield的断点开始继续上一次的操作
但是赋值是没有值的,上一次的那个值return出去了,并没有给赋值操作的左边传递参数
所以,res=None 然后到while循环内部的最后一条语句 输出res:None
程序会在while里面继续执行,又一次碰到了yield,同样return出一个4
跳出foo函数,传递给主函数来print一个4的返回值,至此函数才正式结束
'''
'''到这里你可能就明白yield和return的关系和区别了,
带yield的函数是一个生成器,而不是一个函数了,
这个生成器有一个函数就是next函数,
next就相当于“下一步”生成哪个数,
这一次的next开始的地方是接着上一次的next停止的地方执行的,
所以调用next的时候,生成器并不会从foo函数的开始执行,
只是接着上一步停止的地方开始,然后遇到yield后,
return出要生成的数,此步就结束。
'''
'''
但如果是接下来这个函数
下面我们来分析一下这个程序的内在逻辑
程序开始执行后 因为 foo函数中有yield关键字,所以foo函数并不会真正的执行
而是先得到一个生成器也就是g
直到调用next方法,foo函数开始正式执行,先输出一个starting 然后进入while循环
在循环内部,先执行'yield=4'这个语句 给函数一个返回值4
在主函数内输出4
然后下一条语句输出20个*
再一次调用foo函数
这次和上一次不同
从yield的断点开始继续上一次的操作
从这里开始产生了变化,虽然上一次的值4被return了出去没有成功的给到res
但我们又发送了一个7给到yield的位置来继续执行函数
依旧是函数执行从res的赋值语句开始
res被赋值为7 输出res:7
while循环没有结束继续执行知道碰到yield退出foo函数并且返回一个4
在主函数内输出4,程序结束
'''
def foo():
    print("starting...")
    while True:
        res = yield 4
        print("res:",res)
g = foo()
print(next(g))
print("*"*20)
print(g.send(7))












'''
斐波那契数列
从主函数开始
读取到fib(20)关键字  就把20带入fib开始执行fib函数
a=0,b=1,n=20
进入for循环a=1,b=1,返回一个函数值a=1
回到main函数输出1,再回到for循环,先读取 fib(20)这个生成器
这里先强调一下 使用type函数查看的fib(20)的类型是generator生成器类型
从fib(20)生成器开始,到fib函数内的yield点 ,开始重复for循环知
直到再次遇到yield函数,返回一个1
这个函数的特点(yield)就是,每一次调用fib函数的时候
上一次计算所剩下的ab的值都是保留的
循环知道fib的内部循环结束(即_=20)
fib函数结束
生成器不在生成新的数据
main函数里的循环也不再进行
程序结束(最后的那一句带有type的输出函数
是为了确定fib(20)是一个生成器类型的数
'''
def fib(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
        yield a

def main():
    for val in fib(20):
        print(val)
        pass
    print(type(fib(20)))

if __name__ == '__main__':
    main()

猜你喜欢

转载自blog.csdn.net/apple_51930518/article/details/113004138