<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 17.7.?`plural.py`, 第 6 階段 現在你已準備好探討生成器 (Generator) 了。 ## 例?17.17.?`plural6.py` ``` import re def rules(language): for line in file('rules.%s' % language): pattern, search, replace = line.split() yield lambda word: re.search(pattern, word) and re.sub(search, replace, word) def plural(noun, language='en'): for applyRule in rules(language): result = applyRule(noun) if result: return result ``` 這里使用了被稱作生成器的技術,我不打算在你看過一個簡單例子之前試圖解釋它。 ## 例?17.18.?介紹生成器 ``` >>> def make_counter(x): ... print 'entering make_counter' ... while 1: ... yield x ... print 'incrementing x' ... x = x + 1 ... >>> counter = make_counter(2) >>> counter <generator object at 0x001C9C10> >>> counter.next() entering make_counter 2 >>> counter.next() incrementing x 3 >>> counter.next() incrementing x 4 ``` | | | | --- | --- | | \[1\] | `make_counter` 中出現關鍵字 `yield` 意味著這不是一個普通的函數。它是一種每次生成一個值的特殊函數。你可以把它看成是一個可恢復函數。調用它會返回一個生成器,它可以返回 `x` 的連續值。 | | \[2\] | 想要創建一個 `make_counter` 生成器的實例,只要像其它函數一樣調用。注意這并沒有真正執行函數代碼。你可以分辨出這一點,因為 `make_counter` 的第一行是 `print` 語句,然而沒有任何內容輸出。 | | \[3\] | `make_counter` 函數返回一個生成器對象。 | | \[4\] | 你第一次調用生成器對象的 `next()` 方法,將執行 `make_counter` 中的代碼執行到第一個 `yield` 語句,然后返回生產 (yield) 出來的值。在本例中,這個值是 `2`,因為你是通過 `make_counter(2)` 來創建最初的生成器的。 | | \[5\] | 不斷調用生成器對象的 `next()` _將從你上次離開的位置重新開始_ 并繼續下去直到你又一次遇到 `yield` 語句。接下來執行 `print` 語句來打印 `incrementing x`,然后執行 `x = x + 1` 語句來真正地增加。然后你進入 `while` 的又一次循環,你所做的第一件事是 `yield x`,返回目前的 `x` 值 (現在是3)。 | | \[6\] | 第二次你調用 `counter.next()` 時,你又做一遍相同的事情,但是這次 `x` 是 `4`。如此繼續。因為 `make_counter` 設置的是一個無限循環,理論上你可以永遠這樣繼續下去,不斷地遞增并彈出 `x` 值。現在讓我們看看生成器更具意義的應用。 | ## 例?17.19.?使用生成器替代遞歸 ``` def fibonacci(max): a, b = 0, 1 while a < max: yield a a, b = b, a+b ``` | | | | --- | --- | | \[1\] | 斐波納契數列 (Fibonacci sequence) 是每個數都是前面兩個數值和的一個數列。它從 `0` 和 `1` 開始,開始增長得很慢,但越來越快。開始這個數列你需要兩個變量:`a` 從 `0`開始,`b` 從 `1` 開始。 | | \[2\] | `a` 是數列的當前值,彈出它。 | | \[3\] | `b` 是數列的下一個數,把它賦值給 `a`,同時計算出 (`a+b`) 并賦值給 `b` 放在一邊稍后使用。注意這是并行發生的,如果 `a` 是 `3`,`b` 是 `5`,那么 `a, b = b, a+b` 將會設置 `a` 為 `5` (`b` 的原值),`b` 為 `8` (`a` 和 `b` 之和)。 | 這樣你就有了生成連續的 Fibonacci 數的函數了。當然你也可以通過遞歸做到,但是這里的方法更加易讀。并且也與 `for` 工作得很好。 ## 例?17.20.?`for` 循環中的生成器 ``` >>> for n in fibonacci(1000): ... print n, 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 ``` | | | | --- | --- | | \[1\] | 你可以在 `for` 循環中直接使用 `fibonacci` 這樣的生成器。`for` 循環將會創建一個生成器對象并連續調用其 `next()` 方法獲得值并賦予 `for` 循環變量 (`n`)。 | | \[2\] | 每輪 `for` 循環 `n` 都從 `fibonacci` 的 `yield` 語句獲得一個新的值。當 `fibonacci` 超出數字限定 (`a` 超過 `max`,你在這里限定的是 `1000`) 很自然地退出 `for` 循環。 | 好了,讓我們回到 `plural` 函數看看如何可以把它用起來。 ## 例?17.21.?生成器生成動態函數 ``` def rules(language): for line in file('rules.%s' % language): pattern, search, replace = line.split() yield lambda word: re.search(pattern, word) and re.sub(search, replace, word) def plural(noun, language='en'): for applyRule in rules(language): result = applyRule(noun) if result: return result ``` | | | | --- | --- | | \[1\] | `for line in file(...)` 是從文件中一行行讀取的通用方法,每次一行。它能正常工作是因為 _`file` 實際上返回一個生成器_,它的 `next()` 方法返回文件中的下一行。簡直太酷了,光是想想就讓我滿頭大汗。 | | \[2\] | 這沒有什么神奇之處。還記得規則文件的每一行都用空白分開三個值嗎?所以 `line.split()` 返回一個三元素元組,你把這些值賦給了 3 個局部變量。 | | \[3\] | _然后你不斷地彈出。_ 你彈出什么呢?一個使用 `lambda` 動態生成的函數,而這個函數實際上是一個閉合 (把本地變量 `pattern`,`search` 和 `replace` 作為常量)。換句話說,`rules` 是一個彈出規則函數的生成器。 | | \[4\] | 既然 `rules` 是一個生成器,你就可以在 `for` 循環中直接使用它。`for` 循環的第一輪你調用 `rules` 函數,打開規則文件,讀取第一行,動態構建一個根據規則文件第一行匹配并應用規則的函數。`for` 循環的第二輪將會從上一輪 `rules` 中停下的位置 (`for line in file(...)` 循環內部) 讀取規則文件的第二行,動態構建根據規則文件第二行匹配并應用規則的另一個函數。如此繼續下去。 | 你在[第 5 階段](stage5.html "17.6.?plural.py, 第 5 階段")得到的是什么?第 5 階段中,你讀取整個規則文件并在使用第一條規則之前構建一個所有規則組成的列表。現在有了生成器,你可以更舒適地做到這一切:你打開并讀取第一條規則,根據它創建函數并使用之,如果它適用則根本不去讀取規則文件剩下的內容,也不去建立另外的函數。 ## 進一步閱讀 * PEP 255 定義生成器。 * Python Cookbook 有[生成器的例子](http://www.google.com/search?q=generators+cookbook+site:aspn.activestate.com)。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看