yield 和 return 混用的问题

260 天前
 xing393939
def fun1(batch):
    if batch:
        return range(10)
    else:
        for item in range(10):
            yield item


a = fun1(True)
for v in list(a):
    print(v)
print("-------------")
b = fun1(False)
for v in list(b):
    print(v)

直觉上最后的结果分割线之上也是能输出 0~9 的,但是实际上是空,把 yield 改成 return 就好了,这是什么原因呢?

2848 次点击
所在节点    Python
12 条回复
leonshaw
260 天前
In a generator function, the return statement indicates that the generator is done and will cause StopIteration to be raised. The returned value (if any) is used as an argument to construct StopIteration and becomes the StopIteration.value attribute.
jadehare
260 天前
@leonshaw https://v2ex.com/about 看看规则最后一条
SantuZ
260 天前
GPT 回答:
在 Python 中,return 和 yield 可以出现在同一个函数中,但它们的作用和影响是截然不同的:

return 在函数中用来返回一个值,并结束函数的执行。一旦函数执行到 return 语句,函数会立即结束,并且只能返回一次值。
yield 使函数成为一个生成器函数。使用 yield 的函数每执行到一个 yield 语句,就会产生一个值,并在那个点暂停执行,等待下一次迭代请求值。
当 yield 和 return 在同一个函数中共存时,需要注意以下几点:

如果函数中包含 yield 语句,该函数就是一个生成器函数,调用该函数将返回一个生成器对象,而不是直接执行函数中的代码。

在生成器函数中使用 return 语句可以用来提供生成器的终止原因,但这不会返回值给调用者。在 Python 3.3 及以上版本中,当生成器正常完成迭代时,任何 return 语句中的返回值都会被包装进一个 StopIteration 异常中。通过 StopIteration 异常的.value 属性可以访问到 return 语句中的返回值。

如果 return 语句后有返回值,该值会成为生成器终止时 StopIteration 异常的属性。如果 return 没有返回值(即 return 或 return None ),生成器终止时不会有 StopIteration 值。

一旦执行到 return 语句,即使是在生成器函数中,函数也会立即结束。后续的 yield 语句将不会执行。

def my_generator():
yield 1
return "No more elements" # 结束生成器,并指示原因
yield 2 # 这行代码不会被执行

gen = my_generator()

try:
print(next(gen)) # 输出 1
print(next(gen)) # 触发 StopIteration 异常
except StopIteration as e:
print(e.value) # 输出 "No more elements"
leonshaw
260 天前
@jadehare 啥意思
lovelylain
260 天前
一个函数中出现 yield 语句后,就不再是函数而是生成器了,生成器中 return x 等价于 raise StopIteration(x),大部分时候它只是使迭代停止的特殊异常,不关心这个返回值。如果你需要 True 分支能输出 0~9 ,可以把 return range(10)改为 yield from range(10)
NoOneNoBody
260 天前
@jadehare #2
@leonshaw #1 的回复不是 AI 生成的,就是从手册复制的说明,我刚刚还想粘贴过来呢,看到#1 已经做了,就不需要了
zzl22100048
260 天前
不能 return 可以 yield from
jadehare
260 天前
@leonshaw #4 以为是 ai 生成的回答,不是的话不好意思。
noahlias
260 天前
If the compiler detects the yield keyword anywhere inside a function, that function no longer returns via the return statement. Instead, it immediately returns a lazy "pending list" object called a generator


https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do-in-python
krixaar
260 天前
@jadehare #2
在一个生成器函数中,return 语句表示生成器已完成并将导致 StopIteration 被引发。 返回值(如果有的话)会被当作一个参数用来构建 StopIteration 并成为 StopIteration.value 属性。

https://docs.python.org/zh-cn/3/reference/simple_stmts.html#the-return-statement

Python 官方文档里的,不是 AI 生成的,多虑了😂
leonshaw
260 天前
@jadehare 嗯,是文档里的
oDVN6afUQ2v29715
249 天前
生成器本质上也就是一个迭代器,他里面的一个关键点就是`yield`关键字,当 Python 执行到 yield 语句时,它会生成一个值,然后暂停函数的执行。当下一次调用生成器的`next()`函数时,它会从上次暂停的地方继续执行,直到再次遇到`yield`语句。

`yield`和`return`的区别是:`yield`可以有多个,`return`只能有一个,但站在功能的角度:都是返回值。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1031653

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX