V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zjsxwc
V2EX  ›  程序员

yield 明明是用来做生成器 generator 的, 为什么好多人要用来做"协程"?

  •  
  •   zjsxwc ·
    zjsxwc · 2017-10-14 13:31:19 +08:00 · 3661 次点击
    这是一个创建于 2596 天前的主题,其中的信息可能已经有所发展或是发生改变。

    yield 本意作为 generator 是很方便的,但好多人要用来做"协程"...

    这种 yield 做"协程"的方式,让我想到了当年 C 里的 goto 语句, 把代码写到很混乱, 明明是种反模式, 却会被人追捧.

    你们怎么看?

    17 条回复    2017-10-15 16:11:24 +08:00
    sunjourney
        1
    sunjourney  
       2017-10-14 13:49:06 +08:00
    这取决于你怎么 yield,你既可以 yield 符合调度器协议的东西,也可以不,但你总归需要去调试它,要么自动(携协),要么手动。
    sunjourney
        2
    sunjourney  
       2017-10-14 13:49:31 +08:00
    携协 -> 协程

    手快了
    kindjeff
        3
    kindjeff  
       2017-10-14 13:50:38 +08:00 via iPhone
    啥叫好多人,官方不都这么做了么。
    GeruzoniAnsasu
        4
    GeruzoniAnsasu  
       2017-10-14 13:51:04 +08:00
    不是 yield 用来做协程
    首先你要明白协程解决了什么问题
    在异步模式下,传统的解决方式是用各种回调来处理异步 IO 的结果,当 IO 完成时产生事件并由回调去处理事件
    然而这样的模式 io 发起代码和回调无法写在一起,当异步操作多了之后回调大量增加代码可读性会急剧下降
    而采用协程的模式,发起请求和回调处理写在一起就像一个普通的 block 线程一样
    发起 io 时 yield 出当前函数,当请求完成后由调度器调度回本函数继续在 yield 的位置往下执行,结构就简单清晰很多
    并不是 yield 做协程,而是协程模式必须要有 yield 才可能实现
    hjc4869
        5
    hjc4869  
       2017-10-14 13:52:45 +08:00
    问题是 coroutine 代码一点都不混乱,可读性比别的写法强啊(
    hjc4869
        6
    hjc4869  
       2017-10-14 13:53:16 +08:00
    coroutine 做得好的比如 C#,你把 async await 关键字和方法签名里的 Async 后缀忽略掉,就跟同步阻塞的程序没有什么区别了。
    beginor
        7
    beginor  
       2017-10-14 14:06:34 +08:00 via Android
    @hjc4869 async 和 await 最早出现在 F#中,巨硬觉得这个比较屌,可以甩 Java 多少年,可是 F#始终是少数派中的少数派,最终移值到了 C#
    NoAnyLove
        8
    NoAnyLove  
       2017-10-14 14:29:01 +08:00
    那是因为 Guido 对于添加关键字过于谨慎了,不过在后来的版本中还是加入了 async 和 await 关键字。另外,Python 的 coroutine 就是在 generator 之上发展出来的,事实上在官方支持 coroutine 之前,第三方的库就基于 generator 实现了 coroutine,所以也可以说是历史遗留问题。

    最后,yield 的语法用于 coroutine 并没有觉得凌乱,虽然有可能让人不能一下区分一个函数到底是 coroutine 还是 generator ;另外,goto 虽然被认为是经典的反例,但其实是被过度宣传了,在适合它的场景中,goto 是非常好用的。
    hcnhcn012
        9
    hcnhcn012  
       2017-10-14 14:41:55 +08:00 via iPhone
    。。。完成协程还有比 yield 更 python 的特性么?
    geelaw
        10
    geelaw  
       2017-10-14 14:51:25 +08:00 via iPhone   ❤️ 1
    呃……迭代器不是 coroutine 的一个例子么?

    我更感兴趣为什么要造出 coroutine 这个名词,因为从形式上来说 subroutine 更简单,并且 coroutine 就是保存了调用栈的、多次运行第一步是跳转到上次结束位置之后的一段构造。或许对于 programming 的 philosophy 是有好处的吧。
    jiangzhuo
        11
    jiangzhuo  
       2017-10-14 14:57:06 +08:00
    这事你得问 tj
    ipwx
        12
    ipwx  
       2017-10-14 15:10:07 +08:00
    你可以选择 Python 3.5+,有 async await 替代历史遗留的 @coroutine 和 yield from。

    当然,内部实现还是差不多的。
    QAPTEAWH
        13
    QAPTEAWH  
       2017-10-14 16:42:59 +08:00 via iPhone
    背后的原理是一样的( continuation )
    gouchaoer
        14
    gouchaoer  
       2017-10-14 17:09:32 +08:00 via Android
    写起来很麻烦,还是全协程好用
    chengluyu
        15
    chengluyu  
       2017-10-15 00:04:49 +08:00
    协程怎么和 goto 划等号的……
    ivechan
        16
    ivechan  
       2017-10-15 09:15:23 +08:00
    "The yield expression is used when defining a generator function or an asynchronous generator"
    "A Python generator is a form of coroutine,"
    说白了 generator 其实也是一种 coroutine。
    sexrobot
        17
    sexrobot  
       2017-10-15 16:11:24 +08:00
    http://www.laruence.com/2015/05/28/3038.html
    yield 的造物主都这么用了.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2272 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 16:10 · PVG 00:10 · LAX 08:10 · JFK 11:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.