g generator object foo at 0x000001CB3B2677C8 ********************* 开始执行 ********************* ------------------- 进入foo()函数 ------------------- 第0次循环: 开始 ---------------------------------------- res: None 第0次循环: 结束 第1次循环: 开始 ---------------------------------------- res: None 第1次循环: 结束 第2次循环: 开始 ---------------------------------------- res: None 第2次循环: 结束 第3次循环: 开始 Process finished with exit code 0
代码运行顺序如下
程序开始执行以后 因为foo函数中有yield关键字 所以foo函数并不会真的执行 而是先得到一个生成器generator(相当于一个对象)
直到调用next方法 foo函数正式开始执行 先执行foo函数中的print( ------------------- 进入foo()函数 ------------------- )方法 打印结果
------------------- 进入foo()函数 -------------------
进入for循环
执行for循环里的代码print( 第{0}次循环: 开始 .format(i)) 然后遇到yield关键字 然后把yield想象成return return了一个0之后 程序停止 并没有执行赋值给res操作 此时next(g)语句执行完成 打印结果
第0次循环: 开始
程序执行print( ---------------------------------------- ) 打印结果
----------------------------------------
开始执行接下来的print(next(g))
这个时候和上面那个差不多 不过不同的是 这个时候是从上一个next()程序停止的地方开始执行的 即 继续从上一次yield代码处向下执行代码 也就是要执行res的赋值操作 这时候要注意 这个时候赋值操作的右边是没有值的 因为刚才那个是return出去了 并没有给赋值操作的左边传参数 所以这个时候res赋值是None 程序继续在for执行 直到又一次碰到yield 打印结果
res: None 第0次循环: 结束 第1次循环: 开始
程序执行print( ---------------------------------------- ) 打印结果
----------------------------------------
从上一个next()程序停止的地方开始执行的 即 继续从上一次yield代码处向下执行代码 直到又一次碰到yield 打印结果
res: None 第1次循环: 结束 第2次循环: 开始
直至for循环结束
到这里你可能就明白yield和return的关系和区别了 带yield的函数是一个生成器 而不是一个函数了 这个生成器有一个函数就是next函数 next就相当于“下一步”生成哪个数 这一次的next开始的地方是接着上一次的next停止的地方执行的 所以调用next的时候 生成器并不会从foo函数的开始执行 只是接着上一步停止的地方开始 然后遇到yield后 return出要生成的数 此步就结束。
2、send再看一个这个生成器的send函数的例子 这个例子就把上面那个例子的最后一行换掉了
def foo():
print( ------------------- 进入foo()函数 ------------------- )
for i in range(10):
print( 第{0}次循环: 开始 .format(i))
res yield i
print( res: , res)
print( 第{0}次循环: 结束 .format(i))


