<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # Python 生成器 > 原文: [https://www.programiz.com/python-programming/generator](https://www.programiz.com/python-programming/generator) #### 在本教程中,您將學習如何使用 Python 生成器輕松創建迭代,它與迭代器和常規函數的區別以及為什么要使用它。 ## Python 中的生成器 在 Python 中構建[迭代器](/python-programming/iterator)的工作很多。 我們必須使用`__iter__()`和`__next__()`方法實現一個類,跟蹤內部狀態,并在沒有值要返回時提高`StopIteration`。 這既冗長又違反直覺。 在這種情況下,發電機將進行救援。 Python 生成器是創建迭代器的簡單方法。 我們上面提到的所有工作都由 Python 的生成器自動處理。 簡而言之,生成器是一個函數,它返回一個對象(迭代器),我們可以對其進行迭代(一次一個值)。 * * * ## 用 Python 創建生成器 在 Python 中創建生成器非常簡單。 它與定義普通函數一樣簡單,但是使用`yield`語句而不是`return`語句。 如果一個函數至少包含一個`yield`語句(它可能包含其他`yield`或`return`語句),則它將成為生成器函數。`yield`和`return`都將從函數返回一些值。 不同之處在于,雖然`return`語句完全終止了一個函數,但`yield`語句暫停了該函數并保存了所有狀態,然后在后續調用中從那里繼續。 * * * ## 生成器函數與常規函數之間的區別 這是生成器功函數與常規[函數](/python-programming/function)不同的地方。 * 生成器函數包含一個或多個`yield`語句。 * 調用時,它返回一個對象(迭代器),但不會立即開始執行。 * `__iter__()`和`__next__()`之類的方法會自動實現。 因此,我們可以使用`next()`遍歷項目。 * 一旦函數屈服,函數將暫停并將控件轉移到調用方。 * 連續調用之間會記住局部變量及其狀態。 * 最后,當函數終止時,`StopIteration`在以后的調用中自動加高。 這是一個示例,用于說明上述所有要點。 我們有一個名為`my_gen()`的生成器函數,帶有幾個`yield`語句。 ```py # A simple generator function def my_gen(): n = 1 print('This is printed first') # Generator function contains yield statements yield n n += 1 print('This is printed second') yield n n += 1 print('This is printed at last') yield n ``` 解釋器中的交互式運行如下所示。 在 Python Shell 中運行這些命令以查看輸出。 ```py >>> # It returns an object but does not start execution immediately. >>> a = my_gen() >>> # We can iterate through the items using next(). >>> next(a) This is printed first 1 >>> # Once the function yields, the function is paused and the control is transferred to the caller. >>> # Local variables and theirs states are remembered between successive calls. >>> next(a) This is printed second 2 >>> next(a) This is printed at last 3 >>> # Finally, when the function terminates, StopIteration is raised automatically on further calls. >>> next(a) Traceback (most recent call last): ... StopIteration >>> next(a) Traceback (most recent call last): ... StopIteration ``` 在上面的示例中要注意的一件有趣的事情是,每次調用之間都會記住變量`n`的值。 與普通函數不同,函數屈服時不會破壞局部變量。 此外,生成器對象只能被迭代一次。 要重新啟動該過程,我們需要使用`a = my_gen()`之類的東西來創建另一個生成器對象。 最后要注意的一點是,我們可以將[生成器直接用于`for`循環](/python-programming/for-loop)。 這是因為`for`循環使用一個迭代器,并使用`next()`函數對其進行迭代。 拋出`StopIteration`時,它自動結束。 檢查這里[知道在 Python](/python-programming/iterator#for-loop-working) 中實際上是如何實現`for`循環的。 ```py # A simple generator function def my_gen(): n = 1 print('This is printed first') # Generator function contains yield statements yield n n += 1 print('This is printed second') yield n n += 1 print('This is printed at last') yield n # Using for loop for item in my_gen(): print(item) ``` 運行該程序時,輸出為: ```py This is printed first 1 This is printed second 2 This is printed at last 3 ``` * * * ## 帶有循環的 Python 生成器 上面的例子用處不大,我們研究它只是為了了解背景中發生的事情。 通常,生成器函數通過具有合適終止條件的循環來實現。 讓我們以反轉字符串的生成器為例。 ```py def rev_str(my_str): length = len(my_str) for i in range(length - 1, -1, -1): yield my_str[i] # For loop to reverse the string for char in rev_str("hello"): print(char) ``` **輸出** ```py o l l e h ``` 在此示例中,我們使用`range()`函數使用`for`循環以相反的順序獲取索引。 **注意**:此生成器函數不僅適用于字符串,還適用于其他種類的可迭代變量,例如[列表](/python-programming/list),[元組](/python-programming/tuple)等。 * * * ## Python 生成器表達式 使用生成器表達式可以輕松地動態創建簡單的生成器。 它使建造發電機變得容易。 類似于創建[匿名函數](/python-programming/anonymous-function)的 lambda 函數,生成器表達式創建匿名生成器函數。 生成器表達式的語法類似于 Python 中的[列表推導式語法](/python-programming/list#list-comprehension)。 但是方括號將替換為圓括號。 列表推導式與生成器表達式之間的主要區別在于,列表生成器生成整個列表,而生成器表達式一次生成一個項。 他們懶惰的執行(僅在需要時才生成項目)。 因此,生成器表達式比等效的列表推導式具有更高的內存效率。 ```py # Initialize the list my_list = [1, 3, 6, 10] # square each term using list comprehension list_ = [x**2 for x in my_list] # same thing can be done using a generator expression # generator expressions are surrounded by parenthesis () generator = (x**2 for x in my_list) print(list_) print(generator) ``` **輸出**: ```py [1, 9, 36, 100] <generator object <genexpr> at 0x7f5d4eb4bf50> ``` 上面我們可以看到生成器表達式沒有立即產生所需的結果。 相反,它返回一個生成器對象,該對象僅按需生成項目。 這是我們如何開始從生成器獲取項目的方法: ```py # Initialize the list my_list = [1, 3, 6, 10] a = (x**2 for x in my_list) print(next(a)) print(next(a)) print(next(a)) print(next(a)) next(a) ``` 當我們運行上面的程序時,我們得到以下輸出: ```py 1 9 36 100 Traceback (most recent call last): File "<string>", line 15, in <module> StopIteration ``` 生成器表達式可以用作函數參數。 以這種方式使用時,可以刪除圓括號。 ```py >>> sum(x**2 for x in my_list) 146 >>> max(x**2 for x in my_list) 100 ``` * * * ## 使用 Python 生成器 有幾個原因使生成器成為強大的實現。 ### 1.易于實現 與生成器類的生成器相比,生成器可以以簡潔明了的方式實現。 下面是一個使用迭代器類實現 2 的冪序列的示例。 ```py class PowTwo: def __init__(self, max=0): self.n = 0 self.max = max def __iter__(self): return self def __next__(self): if self.n > self.max: raise StopIteration result = 2 ** self.n self.n += 1 return result ``` 上面的程序冗長而令人困惑。 現在,讓我們使用生成器函數執行相同的操作。 ```py def PowTwoGen(max=0): n = 0 while n < max: yield 2 ** n n += 1 ``` 由于生成器自動跟蹤細節,因此實現簡潔明了。 ### 2.內存有效 一個普通的返回序列的函數會在返回結果之前在內存中創建整個序列。 如果序列中的項目數量很大,這是一個過大的殺傷力。 這種序列的生成器實現是內存友好的,因此是首選的,因為它一次只能生成一項。 ### 3.表示無限流 生成器是代表無限數據流的絕佳媒介。 無限流不能存儲在內存中,并且由于生成器一次只生成一項,因此它們可以表示無限數據流。 以下生成器函數可以生成所有偶數(至少在理論上)。 ```py def all_even(): n = 0 while True: yield n n += 2 ``` ### 4.像流水線一樣連接生成器 可以使用多個生成器來流水線化一系列操作。 最好用一個例子來說明。 假設我們有一個生成斐波那契數列中數字的生成器。 我們還有另一個用于平方的生成器。 如果我們想找出斐波那契數列中數字的平方和,可以通過以下方式將生成器函數的輸出流水線化來實現。 ```py def fibonacci_numbers(nums): x, y = 0, 1 for _ in range(nums): x, y = y, x+y yield x def square(nums): for num in nums: yield num**2 print(sum(square(fibonacci_numbers(10)))) ``` **輸出**: ```py 4895 ``` 這種流水線高效且易于閱讀(是的,非常酷!)。
                  <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>

                              哎呀哎呀视频在线观看