<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 功能強大 支持多語言、二開方便! 廣告
                ## 問題 你的代碼中需要依賴到回調函數的使用(比如事件處理器、等待后臺任務完成后的回調等),并且你還需要讓回調函數擁有額外的狀態值,以便在它的內部使用到。 ## 解決方案 這一小節主要討論的是那些出現在很多函數庫和框架中的回調函數的使用——特別是跟異步處理有關的。為了演示與測試,我們先定義如下一個需要調用回調函數的函數: def apply_async(func, args, *, callback): # Compute the result result = func(*args) # Invoke the callback with the result callback(result) 實際上,這段代碼可以做任何更高級的處理,包括線程、進程和定時器,但是這些都不是我們要關心的。我們僅僅只需要關注回調函數的調用。下面是一個演示怎樣使用上述代碼的例子: >>> def print_result(result): ... print('Got:', result) ... >>> def add(x, y): ... return x + y ... >>> apply_async(add, (2, 3), callback=print_result) Got: 5 >>> apply_async(add, ('hello', 'world'), callback=print_result) Got: helloworld >>> 注意到 `print_result()` 函數僅僅只接受一個參數 `result` 。不能再傳入其他信息。而當你想讓回調函數訪問其他變量或者特定環境的變量值的時候就會遇到麻煩。 為了讓回調函數訪問外部信息,一種方法是使用一個綁定方法來代替一個簡單函數。比如,下面這個類會保存一個內部序列號,每次接收到一個 `result` 的時候序列號加1: class ResultHandler: def __init__(self): self.sequence = 0 def handler(self, result): self.sequence += 1 print('[{}] Got: {}'.format(self.sequence, result)) 使用這個類的時候,你先創建一個類的實例,然后用它的 `handler()` 綁定方法來做為回調函數: >>> r = ResultHandler() >>> apply_async(add, (2, 3), callback=r.handler) [1] Got: 5 >>> apply_async(add, ('hello', 'world'), callback=r.handler) [2] Got: helloworld >>> 第二種方式,作為類的替代,可以使用一個閉包捕獲狀態值,例如: def make_handler(): sequence = 0 def handler(result): nonlocal sequence sequence += 1 print('[{}] Got: {}'.format(sequence, result)) return handler 下面是使用閉包方式的一個例子: >>> handler = make_handler() >>> apply_async(add, (2, 3), callback=handler) [1] Got: 5 >>> apply_async(add, ('hello', 'world'), callback=handler) [2] Got: helloworld >>> 還有另外一個更高級的方法,可以使用協程來完成同樣的事情: def make_handler(): sequence = 0 while True: result = yield sequence += 1 print('[{}] Got: {}'.format(sequence, result)) 對于協程,你需要使用它的 `send()` 方法作為回調函數,如下所示: >>> handler = make_handler() >>> next(handler) # Advance to the yield >>> apply_async(add, (2, 3), callback=handler.send) [1] Got: 5 >>> apply_async(add, ('hello', 'world'), callback=handler.send) [2] Got: helloworld >>> ## 討論 基于回調函數的軟件通常都有可能變得非常復雜。一部分原因是回調函數通常會跟請求執行代碼斷開。因此,請求執行和處理結果之間的執行環境實際上已經丟失了。如果你想讓回調函數連續執行多步操作,那你就必須去解決如何保存和恢復相關的狀態信息了。 至少有兩種主要方式來捕獲和保存狀態信息,你可以在一個對象實例(通過一個綁定方法)或者在一個閉包中保存它。兩種方式相比,閉包或許是更加輕量級和自然一點,因為它們可以很簡單的通過函數來構造。它們還能自動捕獲所有被使用到的變量。因此,你無需去擔心如何去存儲額外的狀態信息(代碼中自動判定)。 如果使用閉包,你需要注意對那些可修改變量的操作。在上面的方案中,`nonlocal` 聲明語句用來指示接下來的變量會在回調函數中被修改。如果沒有這個聲明,代碼會報錯。 而使用一個協程來作為一個回調函數就更有趣了,它跟閉包方法密切相關。某種意義上來講,它顯得更加簡潔,因為總共就一個函數而已。并且,你可以很自由的修改變量而無需去使用 `nonlocal` 聲明。這種方式唯一缺點就是相對于其他Python技術而已或許比較難以理解。另外還有一些比較難懂的部分,比如使用之前需要調用 `next()` ,實際使用時這個步驟很容易被忘記。盡管如此,協程還有其他用處,比如作為一個內聯回調函數的定義(下一節會講到)。 如果你僅僅只需要給回調函數傳遞額外的值的話,還有一種使用 `partial()` 的方式也很有用。在沒有使用 `partial()` 的時候,你可能經常看到下面這種使用lambda表達式的復雜代碼: >>> apply_async(add, (2, 3), callback=lambda r: handler(r, seq)) [1] Got: 5 >>> 可以參考7.8小節的幾個示例,教你如何使用 `partial()` 來更改參數簽名來簡化上述代碼。
                  <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>

                              哎呀哎呀视频在线观看