Ruby生成器与Python生成器

时间:2010-09-25 17:25:41

标签: python ruby generator enumerator

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

然而,我注意到的一个区别是Python Generators支持close()方法,而Ruby Generators则不支持。{1}}方法。从Python文档中可以看出close()方法执行以下操作:

  

在生成器功能暂停的位置引发GeneratorExit。如果生成器函数然后引发StopIteration(通过正常退出,或者由于已经关闭)或GeneratorExit(通过不捕获异常),则关闭返回其调用者。“

Ruby Enumerators不支持close()方法有充分的理由吗?还是偶然的 省略?

我还发现Ruby Enumerators支持rewind()方法但Python生成器不支持...这也是有原因的吗?

由于

3 个答案:

答案 0 :(得分:7)

这个documentation for the rewind method在细节方面有点稀缺。但是为了“重新开始”,发电机必须做两件事之一:

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

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

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