如果是第一次遇到这个关键字,可以直接使用下文中小标题为Next的代码设置断点看一下效果
yield
的函数是一个生成器,而不再是一般意义上的一个函数。yield
在函数中的功能类似于return,不同的是yield每次返回结果之后函数并没有退出,而是 每次遇到yield
关键字后返回相应结果,并保留函数当前的运行状态,等待下一次的调用。yield的
函数成为一个生成器(一开始不运行,而是得到一个对象),生成器同时也是一个迭代器,支持通过next
方法获取下一个值。yield
的好处是通过使用生成器,避免占用内存,提高运行效率。适用场景:一个函数需要多次循环执行一个动作,并且每次执行的结果都是需要的
def foo():
print("starting...")
while True:
result = yield 4
print("result:", result)
test = foo()
print(next(test))
print("*"*20)
print(next(test))
输出
starting...
4
********************
result: None
4
代码分析:
(1) 针对test = foo()
,由于函数foo
中存在yield关键字,所以函数foo
内的代码一开始并不执行,而是得到一个生成器test(相当于一个对象)。
(2) 针对print(next(test))
。由于调用了next
方法,foo
函数开始执行。先输出starting...
,然后进入while循环。在循环内,遇到yield
关键字。这里可以把yield
想象成return
。因此,foo
函数返回4,并通过print
函数输出。注意:这里并没有执行result
的赋值操作。
(3) 针对print("*"*20)
。程序输出20个星号。
(4)针对print(next(test))
。这句代码是接着步骤(2)结束的地方开始执行,执行的是result
的赋值操作。注意:由于在步骤(2)的时候,4已经return出去,并没有完成赋值操作。因此,现在给result
赋的值是None
。所以输出的结果是result: None
。程序接着在While内继续执行,又一次碰到yield
关键字,同样返回4,并通过print
函数输出。
总结一下,带yield
的函数是一个生成器,而不再是一般意义上的一个函数了,这个生成器有一个方法就是next
方法,next
就相当于“下一步”生成哪个数,这一次的next
开始的地方是接着上一次的next
停止的地方执行的,所以第二次调用next
的时候,生成器并不会从foo
函数最开始的地方执行,而是接着上一步停止的地方开始,然后遇到yield
后,return出要生成的数,此步就结束。
def count_up_to(limit):
count = 1
while count <= limit:
yield count
count += 1
# 使用生成器函数
generator = count_up_to(5)
# 调用 next() 函数获取生成器的下一个值
print(next(generator)) # 输出 1
print(next(generator)) # 输出 2
print(next(generator)) # 输出 3
print(next(generator)) # 输出 4
print(next(generator)) # 输出 5
# 超过 limit,再次调用将抛出 StopIteration 异常
# 如果在循环中使用,可以通过捕获异常来结束循环
# 或者使用 for 循环,它会自动处理 StopIteration 异常
除了next
方法,yield
得到的生成器还支持send
方法。该方法可以向生成器传递参数。
python yield用法 (baidu.com)