程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了实际上,Python 3.3中新的“ yield from”语法的主要用途是什么?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决实际上,Python 3.3中新的“ yield from”语法的主要用途是什么??

开发过程中遇到实际上,Python 3.3中新的“ yield from”语法的主要用途是什么?的问题如何解决?下面主要结合日常开发的经验,给出你关于实际上,Python 3.3中新的“ yield from”语法的主要用途是什么?的解决方法建议,希望对你解决实际上,Python 3.3中新的“ yield from”语法的主要用途是什么?有所启发或帮助;

让我们先解决一件事。yIEld from g等同的解释for v in g: yIEld v yIEld from所有内容 处理。因为,让我们面对现实,如果yIEld from要做的就是扩大for循环,那么它就不必保证会增加yIEld from语言并阻止在Python 2.x中实现一堆新功能。

什么yIEld from所做的就是 :

  • 某种意义上说,该连接是“透明的”,它也将正确传播所有内容,而不仅仅是生成的元素(例如,传播异常)。

  • 该连接是在意义上是“双向”的数据可以同时寄给 一个发电机。

如果我们在谈论TCP,yIEld from g可能意味着“现在暂时断开客户端的套接字,然后将其重新连接到该其他服务器套接字”。

便说一句,如果您不确定 向生成器发送数据 意味着什么,则需要删除所有内容并首先阅读 协程 ,它们非常有用(将它们与 子例程进行 对比),但不幸的是在Python中鲜为人知。戴夫·比兹利(Dave Beazley)的《协程》好奇课程是一个很好的开始。阅读幻灯片24-33以获得快速入门。

使用以下命令从生成器读取数据

def reader():
    """A generator that fakes a read from a file, socket, etc."""
    for i in range(4):
        yIEld '<< %s' % i

def reader_wrapper(g):
    # Manually iterate over data produced by reader
    for v in g:
        yIEld v

wrap = reader_wrapper(reader())
for i in wrap:
    print(i)

# Result
<< 0
<< 1
<< 2
<< 3

无需手动迭代reader(),我们可以yIEld from做到。

def reader_wrapper(g):
    yIEld from g

那行得通,我们消除了一行代码。意图可能会更清晰(或不太清楚)。但是生活没有改变。

使用第1部分中的收益将数据发送到生成器(协程)

现在,让我们做一些更有趣的事情。让我们创建一个名为协程的程序writer,它接受发送给它的数据并写入套接字,fd等。

def writer():
    """A coroutIne that writes data *sent* to it to fd, socket, etc."""
    while True:
        w = (yIEld)
        print('>> ', w)

现在的问题是,包装器函数应如何处理将数据发送到编写器,以便将发送到包装器的任何数据 透明地 发送到writer()

def writer_wrapper(coro):
    # TBD
    pass

w = writer()
wrap = writer_wrapper(w)
wrap.send(NonE)  # "prime" the coroutIne
for i in range(4):
    wrap.send(i)

# Expected result
>>  0
>>  1
>>  2
>>  3

包装器需要(显然) 接受 发送给它的数据,并且还应处理stopiterationfor循环耗尽时的。显然只是做for x in coro: yIEld x不会做。这是一个有效的版本。

def writer_wrapper(coro):
    coro.send(NonE)  # prime the coro
    while True:
        try:
            x = (yIEld)  # Capture the value that's sent
            coro.send(X)  # and pass it to the writer
        except stopiteration:
            pass

或者,我们可以这样做。

def writer_wrapper(coro):
    yIEld from coro

这样可以节省6行代码,使其更具可读性,并且可以正常工作。魔法!

从第2部分-异常处理将数据发送到生成器收益

让我们变得更加复杂。如果我们的作者需要处理异常怎么办?假设writer句柄a遇到一个SpamException它将打印***

class SpamException(Exception):
    pass

def writer():
    while True:
        try:
            w = (yIEld)
        except SpamException:
            print('***')
        else:
            print('>> ', w)

如果我们不改变writer_wrapper怎么办?它行得通吗?我们试试吧

# writer_wrapper same as above

w = writer()
wrap = writer_wrapper(w)
wrap.send(NonE)  # "prime" the coroutIne
for i in [0, 1, 2, 'spam', 4]:
    if i == 'spam':
        wrap.throw(SpamException)
    else:
        wrap.send(i)

# Expected Result
>>  0
>>  1
>>  2
***
>>  4

# Actual Result
>>  0
>>  1
>>  2
TraceBACk (most recent call last):
  ... redacted ...
  file ... in writer_wrapper
    x = (yIEld)
__main__.SpamException

嗯,它不起作用,因为x = (yIEld)只是引发了异常,一切都崩溃了。让它正常工作,但手动处理异常并将其发送或将其抛出到子生成器(writer)中

def writer_wrapper(coro):
    """Works. Manually catches exceptions and throws them"""
    coro.send(NonE)  # prime the coro
    while True:
        try:
            try:
                x = (yIEld)
            except Exception as e:   # This catches the SpamException
                coro.throw(E)
            else:
                coro.send(X)
        except stopiteration:
            pass

这有效。

# Result
>>  0
>>  1
>>  2
***
>>  4

但是,这也是!

def writer_wrapper(coro):
    yIEld from coro

yIEld from透明地处理发送值或抛出的值到副发电机。

但是,这仍然不能涵盖所有极端情况。如果外部发电机关闭,会发生什么?如果子生成器返回一个值(是的,在Python 3.3+中,生成器可以返回值),该如何处理?这yield from透明地处理所有角落的情况下确实是令人印象深刻。yIEld from只是神奇地工作并处理了所有这些情况。

我个人认为这yIEld from是一个糟糕的关键字选择,因为它不会使 双向 性变得显而易见。还提出了其他关键字(例如,delegate但被拒绝了,因为向该语言添加新关键字比合并现有关键字要困难得多。

总之,最好将其yIEld from视为 调用方和子生成方之间的。

文献:

  1. PEP 380-委派给子发电机的语法(Ewing)[v3.3,2009-02-13]
  2. PEP 342-通过增强型生成器进行协同程序(GvR,Eby)[v2.5,2005-05-10]

解决方法

我很难把脑袋包在PEP 380上。

  1. 在什么情况下“产生于”有用?
  2. 什么是经典用例?
  3. 为什么与微线程相比?

[更新]

现在,我了解了造成困难的原因。我曾经使用过生成器,但从未真正使用过协程(由PEP-342引入)。尽管有一些相似之处,但生成器和协程基本上是两个不同的概念。了解协程(不仅是生成器)是了解新语法的关键。

恕我直言, 协程是最晦涩的Python功能 ,大多数书籍使它看起来毫无用处且无趣。

感谢您做出的出色回答,特别感谢agf及其与David
Beazley演讲相关的评论。大卫·罗克。

大佬总结

以上是大佬教程为你收集整理的实际上,Python 3.3中新的“ yield from”语法的主要用途是什么?全部内容,希望文章能够帮你解决实际上,Python 3.3中新的“ yield from”语法的主要用途是什么?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。