yield 和 return 混用的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
xing393939
V2EX    Python

yield 和 return 混用的问题

  •  
  •   xing393939
    xing393939 2024-04-11 15:17:50 +08:00 3259 次点击
    这是一个创建于 622 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 就好了,这是什么原因呢?

    12 条回复    2024-04-22 12:31:35 +08:00
    leonshaw
        1
    leonshaw  
       2024-04-11 15:34:30 +08:00
    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
        2
    jadehare  
       2024-04-11 15:36:29 +08:00
    @leonshaw https://v2ex.com/about 看看规则最后一条
    SantuZ
        3
    SantuZ  
       2024-04-11 15:37:58 +08:00
    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
        4
    leonshaw  
       2024-04-11 15:39:52 +08:00
    @jadehare 啥意思
    lovelylain
        5
    lovelylain  
       2024-04-11 15:41:19 +08:00
    一个函数中出现 yield 语句后,就不再是函数而是生成器了,生成器中 return x 等价于 raise StopIteration(x),大部分时候它只是使迭代停止的特殊异常,不关心这个返回值。如果你需要 True 分支能输出 0~9 ,可以把 return range(10)改为 yield from range(10)
    NoOneNoBody
        6
    NoOneNoBody  
       2024-04-11 15:44:26 +08:00
    @jadehare #2
    @leonshaw #1 的回复不是 AI 生成的,就是从手册复制的说明,我刚刚还想粘贴过来呢,看到#1 已经做了,就不需要了
    zzl22100048
        7
    zzl22100048  
       2024-04-11 15:52:41 +08:00
    不能 return 可以 yield from
    jadehare
        8
    jadehare  
       2024-04-11 16:15:08 +08:00
    @leonshaw #4 以为是 ai 生成的回答,不是的话不好意思。
    noahlias
        9
    noahlias  
       2024-04-11 16:21:18 +08:00
    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
        10
    krixaar  
       2024-04-11 16:22:53 +08:00
    @jadehare #2
    在一个生成器函数中,return 语句表示生成器已完成并将导致 StopIteration 被引发。 返回值(如果有的话)会被当作一个参数用来构建 StopIteration 并成为 StopIteration.value 属性。

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

    Python 官方文档里的,不是 AI 生成的,多虑了
    leonshaw
        11
    leonshaw  
       2024-04-11 16:23:50 +08:00
    @jadehare 嗯,是文档里的
    oDVN6afUQ2v29715
        12
    oDVN6afUQ2v29715  
       2024-04-22 12:31:35 +08:00
    生成器本质上也就是一个迭代器,他里面的一个关键点就是`yield`关键字,当 Python 执行到 yield 语句时,它会生成一个值,然后暂停函数的执行。当下一次调用生成器的`next()`函数时,它会从上次暂停的地方继续执行,直到再次遇到`yield`语句。

    `yield`和`return`的区别是:`yield`可以有多个,`return`只能有一个,但站在功能的角度:都是返回值。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2944 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 13:45 PVG 21:45 LAX 05:45 JFK 08:45
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86