20

我一直在研究 Ruby 和 Python 生成器(Enumerators在 Ruby 中称为)之间的相似之处/不同之处,据我所知,它们几乎是等价的。

然而,我注意到的一个区别是 Python 生成器支持一种close()方法,而 Ruby 生成器不支持。在 Python 文档中,close()据说该方法执行以下操作:

在生成器函数暂停的点引发一个 GeneratorExit。如果生成器函数随后引发 StopIteration(通过正常退出,或由于已经被关闭)或 GeneratorExit(通过不捕获异常),则 close 将返回给它的调用者。”

EnumeratorsRuby不支持该close()方法有充分的理由吗?还是意外遗漏?

我还发现 RubyEnumerators支持一种rewind()方法,但 Python 生成器不支持……这也有原因吗?

谢谢

4

3 回答 3

7

这个rewind 方法的文档在细节上有点稀缺。但是为了“重新开始”,生成器必须做以下两件事之一:

  • 记住它的完整输出,重绕后重复该输出,然后恢复之前的操作
  • 以某种方式重置其内部状态,从而导致重复相同的输出而不会产生其他不需要的副作用

其中第二个并不总是可能的。例如,如果生成器从网络发出字节缓冲区,则输出不完全是内部状态的函数。但是任何使用第一种技术的生成器都必须在使用时在内存中建立一个越来越大的缓冲区。与列表相比,此类生成器几乎没有性能优势。

因此,我得出结论,Rubyrewind方法必须是可选的,并不总是由具体的枚举器类支持。因此,如果 Python 设计者重视Liskov 替换原则,那将导致他们不需要在所有生成器中都使用这种方法。

于 2012-06-28T18:02:02.360 回答
2

生成器是基于堆栈的,Ruby 的枚举器通常是专门的(在解释器级别)而不是基于堆栈的。

于 2010-09-26T01:25:24.167 回答
1

Ruby 的 Enumerator 在内部使用 StopIteration 类,请参阅How do Enumerators work in Ruby 1.9.1?

(如果您在每次通话中使用它,它就会被包装起来)。所以我会说他们是相当接近的。话虽如此,我不确定枚举器上的 close 方法该做什么,确切地说......清理,也许?(Python 的生成器可能会从 rewind 中受益——请注意,在 Ruby 中,一些枚举器不会响应 rewind,因此当您调用该方法时它们会引发异常)。

于 2010-09-29T19:49:55.353 回答