在Python中哪里使用yield最好?

whi*_*whi 30 python yield

我知道怎么yield运作.我知道排列,认为它只是一个简单的数学.

但是什么yield是真正的力量?我应该什么时候使用它?一个简单而好的例子就更好了.

mur*_*d99 61

yield 当你有一个函数返回一个序列而你想迭代该序列时,最好使用它,但你不需要一次在内存中包含每个值.

例如,我有一个python脚本解析大量的CSV文件,我想返回每一行在另一个函数中处理.我不想一次将兆字节的数据存储在内存中,所以我yield在python数据结构中的每一行.因此从文件中获取行的功能可能如下所示:

def get_lines(files):
    for f in files:
        for line in f:
            #preprocess line
            yield line
Run Code Online (Sandbox Code Playgroud)

然后,我可以使用与列表相同的语法来访问此函数的输出:

for line in get_lines(files):
    #process line
Run Code Online (Sandbox Code Playgroud)

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


waf*_*dox 15

简单地说,yield给你一个发电机.您可以在通常return在函数中使用的地方使用它.作为一个真正做作的例子,从提示中切割和粘贴......

>>> 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
Run Code Online (Sandbox Code Playgroud)

如您所见,在第一种情况下,foo将整个列表一次保存在内存中.对于包含5个元素的列表来说,这不是什么大问题,但是如果你想要一个500万的列表怎么办?这不仅是一个巨大的内存消耗者,而且在调用函数时也需要花费大量时间来构建.在第二种情况下,bar只给你一个发电机.生成器是可迭代的 - 这意味着您可以在for循环等中使用它,但每个值只能被访问一次.所有值也不会同时存储在内存中; 生成器对象"记住"上次调用它时循环的位置 - 这样,如果你使用一个可迭代(比方说)计数到500亿,你就不必数到500亿全部立即存储500亿个数字.同样,这是一个非常人为的例子,itertools如果你真的想要数到500亿,你可能会使用它.:)

这是生成器最简单的用例.正如你所说,它可以用来编写有效的排列,yield用于通过调用堆栈向上推送而不是使用某种堆栈变量.生成器也可以用于专门的树遍历,以及其他各种方式.

进一步阅读:

  • 第二个示例还将整个列表同时保存在内存中,因为它需要保留整个列表以支持生成器. (2认同)

Dav*_*ole 5

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

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

我的客户端代码循环访问三个生成器函数,获取缓冲区直到迭代结束。