簡單生成器有許多優(yōu)點(diǎn)。生成器除了能夠用更自然的方法表達(dá)一類問題的流程之外,還極大地改善了許多效率不足之處。在 Python 中,函數(shù)調(diào)用代價(jià)不菲;除其它因素外,還要花一段時(shí)間解決函數(shù)參數(shù)列表(除了其它的事情外,還要分析位置參數(shù)和缺省參數(shù))。初始化框架對(duì)象還要采取一些建立步驟(據(jù) Tim Peters 在 comp.lang.python 上所說,有 100 多行 C 語言程序;我自己還沒檢查 Python 源代碼呢)。與此相反,恢復(fù)一個(gè)生成器就相當(dāng)省力;參數(shù)已經(jīng)解析完了,而且框架對(duì)象正“無所事事地”等待恢復(fù)(幾乎不需要額外的初始化)。當(dāng)然,如果速度是最重要的,您不應(yīng)該使用字節(jié)碼已編譯過的動(dòng)態(tài)語言;但即使在速度不是主要考慮因素的情況下,快點(diǎn)總比慢點(diǎn)好。
回憶狀態(tài)機(jī)
在“可愛的 Python”前面的另一篇文章中,我介紹了StateMachine 類 ,給定的機(jī)器需要多少狀態(tài)處理程序,它就允許用戶添加多少狀態(tài)處理程序。在模型中,將一個(gè)或多個(gè)狀態(tài)定義為終態(tài)(end state),僅將一個(gè)狀態(tài)定義為初始狀態(tài)(start state)(調(diào)用類方法對(duì)此進(jìn)行配置)。每個(gè)處理程序都有某種必需的結(jié)構(gòu);處理程序?qū)?zhí)行一系列操作,然后過一會(huì)兒,它帶著一個(gè)標(biāo)記返回到 StateMachine.run() 方法中的循環(huán)內(nèi),該標(biāo)記指出了想得到的下一個(gè)狀態(tài)。同樣,用 cargo 變量允許一個(gè)狀態(tài)把一些(未處理的)信息傳遞給下一個(gè)狀態(tài)。
我介紹的 StateMachine 類的典型用途是以一個(gè)有狀態(tài)的方式使用輸入。例如,我所用的一個(gè)文本處理工具(Txt2Html)從一個(gè)文件中讀取數(shù)行內(nèi)容;依據(jù)每行所屬的類別,需要以特殊的方式對(duì)其進(jìn)行處理。然而,您經(jīng)常需要看看前面幾行提供的上下文來確定當(dāng)前行屬于哪個(gè)類別(以及應(yīng)該怎樣處理它)。構(gòu)建在 StateMachine 類上的這個(gè)過程的實(shí)現(xiàn)可以定義一個(gè) A 處理程序,該處理程序讀取幾行,然后以類似 A 的方式處理這些行。不久,滿足了一個(gè)條件,這樣下一批的幾行內(nèi)容就應(yīng)該由 B 處理程序來處理了。 A 把控制傳遞回 .run() 循環(huán),同時(shí)指示切換到 B 狀態(tài) ― 以及任何 A 不能正確處理的、 B 應(yīng)該在閱讀額外的幾行之前處理的額外的行。最后,某個(gè)處理程序?qū)⑺目刂苽鬟f給某個(gè)被指定為終態(tài)的狀態(tài),處理停止(halt)。
對(duì)于前面一部分中的具體代碼示例,我使用了一個(gè)簡化過的應(yīng)用程序。我處理由迭代函數(shù)產(chǎn)生的數(shù)字流,而不是處理多行內(nèi)容。每個(gè)狀態(tài)處理程序僅打印那些在期望的數(shù)字范圍內(nèi)的數(shù)字(以及關(guān)于有效狀態(tài)的一些消息)。當(dāng)數(shù)字流中的一個(gè)數(shù)字傳到一個(gè)不同的范圍內(nèi),另一個(gè)不同的處理程序就會(huì)接管“處理”。對(duì)于這一部分,我們將看看另一種用生成器實(shí)現(xiàn)相同數(shù)字流處理的方式(有一些額外的技巧和功能)。但是,一個(gè)更復(fù)雜的生成器示例有可能對(duì)更象上一段中提到的輸入流進(jìn)行處理。我們再來看看前一個(gè)狀態(tài)機(jī)刪減過代碼的版本:
新聞熱點(diǎn)
疑難解答
圖片精選