Ruby 生成器与 Python 生成器

发布于 2024-09-24 18:32:23 字数 527 浏览 4 评论 0原文

我一直在研究 Ruby 和 Python 生成器(在 Ruby 中称为枚举器)之间的相似/差异,据我所知,它们几乎是等效的。

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

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

Ruby Enumerators 不支持 close() 方法还是一个意外? 省略?

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

谢谢

I've been researching the similarities/differences between Ruby and Python generators (known as Enumerators in Ruby), and so far as i can tell they're pretty much equivalent.

However one difference i've noticed is that Python Generators support a close() method whereas Ruby Generators do not. From the Python docs the close() method is said to do the following:

Raises a GeneratorExit at the point where the generator function was paused. If the generator function then raises StopIteration (by exiting normally, or due to already being closed) or GeneratorExit (by not catching the exception), close returns to its caller."

Is there a good reason why Ruby Enumerators don't support the close() method? Or is it an accidental
omission?

I also discovered that Ruby Enumerators support a rewind() method yet Python generators do not...is there a reason for this too?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

落日海湾 2024-10-01 18:32:23

这个倒带方法的文档< /a> 的细节有点匮乏。但是为了“重新开始”,生成器必须执行以下两件事之一:

  • 记住其完整的输出,在倒带后重复该输出,然后在重置其内部状态之前恢复其正在执行的操作
  • ,从而导致相同的输出重复进行不会产生其他不良副作用

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

因此,我得出结论,Ruby rewind 方法必须是可选的,并且并不总是受到具体枚举器类的支持。因此,如果Python设计者重视里氏替换原则,那么他们就不需要这样的方法在所有发电机中。

This documentation for the rewind method is a little scarce on details. But in order to "start over" the generator would have to do one of two things:

  • remember its complete output, repeat that output once rewound, then resume what it was doing before
  • reset its internal state in a way that causes the same output to be repeated without other unwanted side effects

The second of these is not always possible; for example, if the generator emits byte buffers from the network, the output is not entirely a function of internal state. But any generator that uses the first technique must necessarily build up a larger and larger buffer in memory as it is used. Such generators offer little performance benefit over lists.

Therefore, I conclude that the Ruby rewind method must be optional and not always supported by a concrete enumerator class. So if the Python designers value the Liskov substitution principle, that would lead them not to require such a method in all generators.

扎心 2024-10-01 18:32:23

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

Generators are stack based, Ruby's Enumerators are often specialised (at the interpreter level) and not stack based.

疯到世界奔溃 2024-10-01 18:32:23

Ruby 的枚举器在内部使用 StopIteration 类,请参阅 枚举器在 Ruby 中如何工作1.9.1?

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

Ruby's Enumerator's use StopIteration class internally, see How do Enumerators work in Ruby 1.9.1?

(it's just wrapped if you use it in a for each call). So I'd say they'are a rather close. That being said, I'm not sure what a close method on an enumerator should do, exactly...cleanup, perhaps? (Python's generators probably would benefit from a rewind--note well that in Ruby, some enumerators don't respond to rewind, so they raise an exception when you call that method).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文