2010-09-25 90 views
20

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

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

在生成器函数暂停的位置引发一个GeneratorExit。如果发电机的功能,然后引发StopIteration异常(由正常退出,或因已被关闭)或GeneratorExit(由未捕获异常),接近返回到它的调用者。”

有一个很好的理由红宝石Enumerators不支持close()方法呢?还是一个偶然 遗漏?

我还发现,红宝石Enumerators支持rewind()方法尚未Python生成不...是有这个吗?

理由谢谢

+0

好奇,但我不明白你会怎么用这个:你能举个例子吗? – 2010-09-25 20:31:54

+5

@Andrew Vit:这可以用来使发生器保存的资源 - 数据库连接,文件等被清理。它还会阻止从代码的其他部分进一步调用其“下一个”或“发送”方法。例如,您可以调用'close'来指示其中一个消费者向其他人表明已找到期望的值。 – intuited 2010-09-25 20:38:22

+0

@intuited,是Python的'close()'实际上常用吗?我想我在某个地方看到它被python社区认为是“奥术”,并没有真正被利用。 – horseyguy 2010-09-26 12:39:53

回答

2

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

1

Ruby的枚举器的使用的StopIteration类内部,看到How do Enumerators work in Ruby 1.9.1?

(如果你在使用它的每个调用它只是包裹)。所以我会说他们比较接近。话虽如此,我不确定在调查员应该做什么密切的方法,确切地说......清理,也许? (Python的生成器可能会从倒带中受益 - 请注意,在Ruby中,某些枚举器不会响应倒带,因此当您调用该方法时它们会引发异常)。

+2

感谢您的回答。但'StopIteration'也是python使用的 - 事实上Ruby从Python中汲取了这个想法。作为一个close()'可能做什么,请看直觉对我的问题的评论(上面)。 – horseyguy 2010-09-29 20:02:00

+0

yeah ruby​​ 1.9.x的枚举器基本上使它与Python的生成器一致(尽管你也可以在Ruby中使用块来真正模拟生成器)。 – rogerdpack 2010-09-30 16:36:49

6

这个documentation for the rewind method是有点稀缺的细节。但为了“从头再来”时,生成必须做两件事情之一:

  • 记住它的完整输出,重复输出一次倒带,然后恢复它在做什么之前
  • 复位其内部状态以某种方式导致相同的输出重复,而没有其他不需要的副作用

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

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