Python中在哪里使用yield最好?

Python中在哪里使用yield最好?,python,yield,Python,Yield,我知道收益率是如何运作的。我知道排列,我认为它只是一个简单的数学问题 但是什么是屈服的真正力量呢?我应该什么时候用?一个简单而好的例子更好 yield当您有一个返回序列的函数,并且您希望迭代该序列,但不需要一次将所有值都存储在内存中时,最好使用它 例如,我有一个python脚本,它解析一个CSV文件的大列表,我想返回要在另一个函数中处理的每一行。我不想一次在内存中存储所有兆字节的数据,所以我在python数据结构中产生每一行。因此,从文件中获取行的函数可能类似于: def get_lines(f

我知道收益率是如何运作的。我知道排列,我认为它只是一个简单的数学问题


但是什么是屈服的真正力量呢?我应该什么时候用?一个简单而好的例子更好

yield
当您有一个返回序列的函数,并且您希望迭代该序列,但不需要一次将所有值都存储在内存中时,最好使用它

例如,我有一个python脚本,它解析一个CSV文件的大列表,我想返回要在另一个函数中处理的每一行。我不想一次在内存中存储所有兆字节的数据,所以我在python数据结构中产生每一行。因此,从文件中获取行的函数可能类似于:

def get_lines(files):
    for f in files:
        for line in f:
            #preprocess line
            yield line
然后,我可以使用与列表相同的语法来访问此函数的输出:

for line in get_lines(files):
    #process line

但是我节省了大量内存使用。

另一个用途是网络客户端。在生成器函数中使用“yield”通过多个套接字进行循环,而不需要线程的复杂性

例如,我有一个硬件测试客户端,它需要将映像的R、G、B平面发送到固件。需要同步发送的数据:红、绿、蓝、红、绿、蓝。我没有产生三个线程,而是使用了一个生成器来读取文件,对缓冲区进行编码。每个缓冲区都是一个“产量buf”。文件结束,函数返回,迭代结束


我的客户端代码在三个生成器函数中循环,得到缓冲区,直到迭代结束。

简单地说,
yield
为您提供一个生成器。您可以在函数中通常使用
返回的地方使用它。作为一个真正做作的例子,从提示中剪切粘贴

>>> def get_odd_numbers(i):
...     return range(1, i, 2)
... 
>>> def yield_odd_numbers(i):
...     for x in range(1, i, 2):
...             yield x
... 
>>> foo = get_odd_numbers(10)
>>> bar = yield_odd_numbers(10)
>>> foo
[1, 3, 5, 7, 9]
>>> bar
<generator object yield_odd_numbers at 0x1029c6f50>
>>> bar.next()
1
>>> bar.next()
3
>>> bar.next()
5
>>def获取奇数(i):
...     返回范围(1,i,2)
... 
>>>def产量奇数(i):
...     对于范围(1,i,2)内的x:
...             产量x
... 
>>>foo=获取奇数(10)
>>>条=产量(奇数)(10)
>>>福
[1, 3, 5, 7, 9]
>>>酒吧
>>>bar.next()
1.
>>>bar.next()
3.
>>>bar.next()
5.
如您所见,在第一种情况下,
foo
一次将整个列表保存在内存中。对于一个包含5个元素的列表来说没什么大不了的,但是如果你想要一个500万元素的列表呢?这不仅是一个巨大的内存消耗器,而且在调用函数时构建它也要花费大量时间。在第二种情况下,
bar
只提供一个生成器。生成器是一个iterable——这意味着您可以在for循环等中使用它,但每个值只能访问一次。所有值也不会同时存储在内存中;generator对象“记住”上次调用它时它在循环中的位置——这样,如果使用iterable来(比如)计数到500亿,则不必一次全部计数到500亿,并存储500亿个数字进行计数。同样,这是一个非常做作的例子,如果你真的想数到500亿,你可能会使用
itertools
。)

这是生成器最简单的用例。正如您所说的,它可以用来编写有效的排列,使用
yield
通过调用堆栈而不是使用某种堆栈变量来推动事情。生成器还可以用于专门的树遍历和所有其他事情

进一步阅读:

  • python维基
  • 发电机上的PEP
我正在阅读Python中的数据结构和算法

有一个使用收益率的斐波那契函数。我认为现在是使用收益率的最佳时机

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a+b
您可以这样使用:

gen = fibonacci()
for i, f in enumerate(gen):
    print(i, f)
    if i >= 100: break

所以,我认为,也许,当下一个元素取决于之前的元素时,例如,数字滤波器,是时候使用产量了

在这个例子中,
yield
在哪里可能重复?谢谢,我有点困惑。对于f.readlines()中的行:#处理行也执行相同的操作。看起来没有必要屈服,或者readall()中是屈服吗?我添加了实际的函数定义来澄清这一点,所以get_lines()封装了文件的工作,但用户也可以使用迭代调用readlines(),同样的效果,我认为不需要屈服。其思想是
get_lines()
可以是返回具有已知结构的对象序列的任意函数,
yield
允许它返回大量此类对象,而不会占用太多内存。谢谢。是的,“3线程+锁”不好。但是为什么在同一条主线上呢?简单。该脚本是一个小型命令行应用程序。没有图形用户界面。此外,同一线程中的所有内容都意味着一个套接字上的错误将关闭整个客户端。由于我只与一台服务器通信,一个套接字的死亡意味着我可以快速停止所有套接字。第二个示例还将整个列表同时保存在内存中,因为它需要保留整个列表以支持生成器。