2010-09-25 93 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,那麼這將導致他們在所有生成器中都不需要這樣的方法。