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

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 問題 你想讓你的對象支持上下文管理協議(with語句)。 ## 解決方案 為了讓一個對象兼容 `with` 語句,你需要實現 `__enter()__` 和 `__exit__()` 方法。例如,考慮如下的一個類,它能為我們創建一個網絡連接: from socket import socket, AF_INET, SOCK_STREAM class LazyConnection: def __init__(self, address, family=AF_INET, type=SOCK_STREAM): self.address = address self.family = family self.type = type self.sock = None def __enter__(self): if self.sock is not None: raise RuntimeError('Already connected') self.sock = socket(self.family, self.type) self.sock.connect(self.address) return self.sock def __exit__(self, exc_ty, exc_val, tb): self.sock.close() self.sock = None 這個類的關鍵特點在于它表示了一個網絡連接,但是初始化的時候并不會做任何事情(比如它并沒有建立一個連接)。連接的建立和關閉是使用 `with` 語句自動完成的,例如: from functools import partial conn = LazyConnection(('www.python.org', 80)) # Connection closed with conn as s: # conn.__enter__() executes: connection open s.send(b'GET /index.html HTTP/1.0\r\n') s.send(b'Host: www.python.org\r\n') s.send(b'\r\n') resp = b''.join(iter(partial(s.recv, 8192), b'')) # conn.__exit__() executes: connection closed ## 討論 編寫上下文管理器的主要原理是你的代碼會放到 `with` 語句塊中執行。當出現 `with` 語句的時候,對象的 `__enter__()` 方法被觸發,它返回的值(如果有的話)會被賦值給 `as` 聲明的變量。然后,`with` 語句塊里面的代碼開始執行。最后,`__exit__()` 方法被觸發進行清理工作。 不管 `with` 代碼塊中發生什么,上面的控制流都會執行完,就算代碼塊中發生了異常也是一樣的。事實上,`__exit__()` 方法的第三個參數包含了異常類型、異常值和追溯信息(如果有的話)。`__exit__()` 方法能自己決定怎樣利用這個異常信息,或者忽略它并返回一個None值。如果 `__exit__()` 返回 `True` ,那么異常會被清空,就好像什么都沒發生一樣,`with` 語句后面的程序繼續在正常執行。 還有一個細節問題就是 `LazyConnection` 類是否允許多個 `with` 語句來嵌套使用連接。很顯然,上面的定義中一次只能允許一個socket連接,如果正在使用一個socket的時候又重復使用 `with` 語句,就會產生一個異常了。不過你可以像下面這樣修改下上面的實現來解決這個問題: from socket import socket, AF_INET, SOCK_STREAM class LazyConnection: def __init__(self, address, family=AF_INET, type=SOCK_STREAM): self.address = address self.family = family self.type = type self.connections = [] def __enter__(self): sock = socket(self.family, self.type) sock.connect(self.address) self.connections.append(sock) return sock def __exit__(self, exc_ty, exc_val, tb): self.connections.pop().close() # Example use from functools import partial conn = LazyConnection(('www.python.org', 80)) with conn as s1: pass with conn as s2: pass # s1 and s2 are independent sockets 在第二個版本中,`LazyConnection` 類可以被看做是某個連接工廠。在內部,一個列表被用來構造一個棧。每次 `__enter__()` 方法執行的時候,它復制創建一個新的連接并將其加入到棧里面。`__exit__()` 方法簡單的從棧中彈出最后一個連接并關閉它。這里稍微有點難理解,不過它能允許嵌套使用 `with` 語句創建多個連接,就如上面演示的那樣。 在需要管理一些資源比如文件、網絡連接和鎖的編程環境中,使用上下文管理器是很普遍的。這些資源的一個主要特征是它們必須被手動的關閉或釋放來確保程序的正確運行。例如,如果你請求了一個鎖,那么你必須確保之后釋放了它,否則就可能產生死鎖。通過實現 `__enter__()` 和 `__exit__()` 方法并使用 `with` 語句可以很容易的避免這些問題,因為 `__exit__()` 方法可以讓你無需擔心這些了。 在 `contextmanager` 模塊中有一個標準的上下文管理方案模板,可參考9.22小節。同時在12.6小節中還有一個對本節示例程序的線程安全的修改版。
                  <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>

                              哎呀哎呀视频在线观看