我很难理解PEP 380。

在什么情况下yield from是有用的? 经典用例是什么? 为什么将其与微线程进行比较?

到目前为止,我使用过生成器,但从未真正使用过协程(由PEP-342引入)。尽管有一些相似之处,生成器和协程基本上是两个不同的概念。理解协程(不仅仅是生成器)是理解新语法的关键。

以我之见,协程是Python中最晦涩的特性,大多数书籍都让它看起来毫无用处和无趣。


感谢这些精彩的回答,但特别感谢agf和他的评论链接到David Beazley的演讲。


当前回答

Yield将产生单个值到集合中。

从一个集合到另一个集合,让它变平。

请看这个例子:

def yieldOnly():
    yield "A"
    yield "B"
    yield "C"

def yieldFrom():
    for i in [1, 2, 3]:
        yield from yieldOnly()

test = yieldFrom()
for i in test:
print(i)

在控制台,你会看到:

A
B
C
A
B
C
A
B
C

其他回答

在异步IO协程的实际使用中,yield from与协程函数中的await具有类似的行为。两者都用于暂停协程的执行。

Yield from由基于生成器的协程使用。 Await用于async def协程。(Python 3.5+开始)

对于Asyncio,如果不需要支持旧的Python版本(即>3.5),async def/await是定义协程的推荐语法。因此,yield from在协程中不再需要。

但一般来说,在asyncio之外,yield from <子生成器>在迭代子生成器时仍有一些其他用途,如前面的回答中所述。

Yield从基本链迭代器以有效的方式:

# chain from itertools:
def chain(*iters):
    for it in iters:
        for item in it:
            yield item

# with the new keyword
def chain(*iters):
    for it in iters:
        yield from it

正如您所看到的,它删除了一个纯Python循环。这几乎就是它所做的一切,但是链接迭代器是Python中非常常见的模式。

线程基本上是一种特性,它允许您在完全随机的点跳出函数,并跳回另一个函数的状态。线程管理器经常这样做,因此程序似乎同时运行所有这些函数。问题是这些点是随机的,所以您需要使用锁定来防止管理器在有问题的点上停止函数。

在这个意义上,生成器与线程非常相似:它们允许您指定特定的点(当它们屈服时),您可以在那里插入和退出。当以这种方式使用时,生成器称为协程。

阅读这篇关于Python协程的优秀教程,了解更多细节

这段代码定义了一个函数fixed_sum_digits,返回一个枚举所有6位数字的生成器,使得数字和为20。

def iter_fun(sum, deepness, myString, Total):
    if deepness == 0:
        if sum == Total:
            yield myString
    else:  
        for i in range(min(10, Total - sum + 1)):
            yield from iter_fun(sum + i,deepness - 1,myString + str(i),Total)

def fixed_sum_digits(digits, Tot):
    return iter_fun(0,digits,"",Tot) 

试着不屈服地写它。如果你找到了有效的方法,请告诉我。

我认为对于这样的情况:访问树,yield from使代码更简单、更干净。

Yield将产生单个值到集合中。

从一个集合到另一个集合,让它变平。

请看这个例子:

def yieldOnly():
    yield "A"
    yield "B"
    yield "C"

def yieldFrom():
    for i in [1, 2, 3]:
        yield from yieldOnly()

test = yieldFrom()
for i in test:
print(i)

在控制台,你会看到:

A
B
C
A
B
C
A
B
C

简单地说,yield from为迭代器函数提供了尾部递归。