我很难理解PEP 380。
在什么情况下yield from是有用的? 经典用例是什么? 为什么将其与微线程进行比较?
到目前为止,我使用过生成器,但从未真正使用过协程(由PEP-342引入)。尽管有一些相似之处,生成器和协程基本上是两个不同的概念。理解协程(不仅仅是生成器)是理解新语法的关键。
以我之见,协程是Python中最晦涩的特性,大多数书籍都让它看起来毫无用处和无趣。
感谢这些精彩的回答,但特别感谢agf和他的评论链接到David Beazley的演讲。
我很难理解PEP 380。
在什么情况下yield from是有用的? 经典用例是什么? 为什么将其与微线程进行比较?
到目前为止,我使用过生成器,但从未真正使用过协程(由PEP-342引入)。尽管有一些相似之处,生成器和协程基本上是两个不同的概念。理解协程(不仅仅是生成器)是理解新语法的关键。
以我之见,协程是Python中最晦涩的特性,大多数书籍都让它看起来毫无用处和无趣。
感谢这些精彩的回答,但特别感谢agf和他的评论链接到David Beazley的演讲。
当前回答
这段代码定义了一个函数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从基本链迭代器以有效的方式:
# 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协程的优秀教程,了解更多细节
Wherever you invoke a generator from within a generator you need a "pump" to re-yield the values: for v in inner_generator: yield v. As the PEP points out there are subtle complexities to this which most people ignore. Non-local flow-control like throw() is one example given in the PEP. The new syntax yield from inner_generator is used wherever you would have written the explicit for loop before. It's not merely syntactic sugar, though: It handles all of the corner cases that are ignored by the for loop. Being "sugary" encourages people to use it and thus get the right behaviors.
这条讨论线程中的消息讨论了这些复杂性:
对于PEP 342引入的附加生成器特性,这是不可能的 更长的情况:正如Greg的PEP中所描述的,简单的迭代不会 正确支持send()和throw()。体操需要支持 当您破坏Send()和throw()时,它们实际上并不复杂 向下,但它们也不是微不足道的。
我不能与微线程进行比较,只能观察到生成器是一种并行。您可以将挂起生成器视为一个线程,它通过yield将值发送给消费线程。实际的实现可能不是这样的(Python开发人员显然对实际的实现非常感兴趣),但这与用户无关。
语法带来的新成果并没有在线程方面为语言增加任何额外的功能,它只是使正确使用现有功能变得更容易。或者更准确地说,它使专家编写的复杂内部生成器的新手更容易通过该生成器,而不会破坏其任何复杂特性。
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为迭代器函数提供了尾部递归。
这段代码定义了一个函数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使代码更简单、更干净。