<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      functools下的partial模塊應用

      0|1問題


      你有一個被其他python代碼使用的callable對象,可能是一個回調函數或者是一個處理器, 但是它的參數太多了,導致調用時出錯。

      0|1解決方案


      如果需要減少某個函數的參數個數,你可以使用 functools.partial()partial() 函數允許你給一個或多個參數設置固定的值,減少接下來被調用時的參數個數。 為了演示清楚,假設你有下面這樣的函數:

      def spam(a, b, c, d):
          print(a, b, c, d)

      現在我們使用 partial() 函數來固定某些參數值:

      復制代碼
      >>> from functools import partial
      >>> s1 = partial(spam, 1) # a = 1
      >>> s1(2, 3, 4)
      1 2 3 4
      >>> s1(4, 5, 6)
      1 4 5 6
      >>> s2 = partial(spam, d=42) # d = 42
      >>> s2(1, 2, 3)
      1 2 3 42
      >>> s2(4, 5, 5)
      4 5 5 42
      >>> s3 = partial(spam, 1, 2, d=42) # a = 1, b = 2, d = 42
      >>> s3(3)
      1 2 3 42
      >>> s3(4)
      1 2 4 42
      >>> s3(5)
      1 2 5 42
      >>>
      復制代碼

      可以看出 partial() 固定某些參數并返回一個新的callable對象。這個新的callable接受未賦值的參數, 然后跟之前已經賦值過的參數合并起來,最后將所有參數傳遞給原始函數。

      0|1討論


      本節要解決的問題是讓原本不兼容的代碼可以一起工作。下面我會列舉一系列的例子。

      第一個例子是,假設你有一個點的列表來表示(x,y)坐標元組。 你可以使用下面的函數來計算兩點之間的距離:

      復制代碼
      points = [ (1, 2), (3, 4), (5, 6), (7, 8) ]
      
      import math
      def distance(p1, p2):
          x1, y1 = p1
          x2, y2 = p2
          return math.hypot(x2 - x1, y2 - y1)
      復制代碼

      說明一下這里的math.hypot默認是以坐標原點為幾點計算坐標到原點的直線距離

      import math
      print(math.hypot(6,8))
      >>>10

      現在假設你想以某個點為基點,根據點和基點之間的距離來排序所有的這些點。 列表的 sort() 方法接受一個關鍵字參數來自定義排序邏輯, 但是它只能接受一個單個參數的函數(distance()很明顯是不符合條件的)。 現在我們可以通過使用 partial() 來解決這個問題:

      >>> pt = (4, 3)
      >>> points.sort(key=partial(distance,pt))
      >>> points
      [(3, 4), (1, 2), (5, 6), (7, 8)]
      >>>

      更進一步,partial() 通常被用來微調其他庫函數所使用的回調函數的參數。 例如,下面是一段代碼,使用 multiprocessing 來異步計算一個結果值, 然后這個值被傳遞給一個接受一個result值和一個可選logging參數的回調函數:

      復制代碼
      def output_result(result, log=None):
          if log is not None:
              log.debug('Got: %r', result)
      
      # A sample function
      def add(x, y):
          return x + y
      
      if __name__ == '__main__':
          import logging
          from multiprocessing import Pool
          from functools import partial
      
          logging.basicConfig(level=logging.DEBUG)
          log = logging.getLogger('test')
      
          p = Pool()
          p.apply_async(add, (3, 4), callback=partial(output_result, log=log))
          p.close()
          p.join()
      復制代碼

      當給 apply_async() 提供回調函數時,通過使用 partial() 傳遞額外的 logging 參數。 而 multiprocessing 對這些一無所知——它僅僅只是使用單個值來調用回調函數。

      作為一個類似的例子,考慮下編寫網絡服務器的問題,socketserver 模塊讓它變得很容易。 下面是個簡單的echo服務器:

      復制代碼
      from socketserver import StreamRequestHandler, TCPServer
      
      class EchoHandler(StreamRequestHandler):
          def handle(self):
              for line in self.rfile:
                  self.wfile.write(b'GOT:' + line)
      
      serv = TCPServer(('', 15000), EchoHandler)
      serv.serve_forever()
      復制代碼

      不過,假設你想給EchoHandler增加一個可以接受其他配置選項的 __init__ 方法。比如:

      復制代碼
      class EchoHandler(StreamRequestHandler):
          # ack is added keyword-only argument. *args, **kwargs are
          # any normal parameters supplied (which are passed on)
          def __init__(self, *args, ack, **kwargs):
              self.ack = ack
              super().__init__(*args, **kwargs)
      
          def handle(self):
              for line in self.rfile:
                  self.wfile.write(self.ack + line)
      復制代碼

      這么修改后,我們就不需要顯式地在TCPServer類中添加前綴了。 但是你再次運行程序后會報類似下面的錯誤:

      Exception happened during processing of request from ('127.0.0.1', 59834)
      Traceback (most recent call last):
      ...
      TypeError: __init__() missing 1 required keyword-only argument: 'ack'

      初看起來好像很難修正這個錯誤,除了修改 socketserver 模塊源代碼或者使用某些奇怪的方法之外。 但是,如果使用 partial() 就能很輕松的解決——給它傳遞 ack 參數的值來初始化即可,如下:

      from functools import partial
      serv = TCPServer(('', 15000), partial(EchoHandler, ack=b'RECEIVED:'))
      serv.serve_forever()

      在這個例子中,__init__() 方法中的ack參數聲明方式看上去很有趣,其實就是聲明ack為一個強制關鍵字參數。 關于強制關鍵字參數問題我們在7.2小節我們已經討論過了,讀者可以再去回顧一下。

      很多時候 partial() 能實現的效果,lambda表達式也能實現。比如,之前的幾個例子可以使用下面這樣的表達式:

      points.sort(key=lambda p: distance(pt, p))
      p.apply_async(add, (3, 4), callback=lambda result: output_result(result,log))
      serv = TCPServer(('', 15000),
              lambda *args, **kwargs: EchoHandler(*args, ack=b'RECEIVED:', **kwargs))

      這樣寫也能實現同樣的效果,不過相比而已會顯得比較臃腫,對于閱讀代碼的人來講也更加難懂。 這時候使用 partial() 可以更加直觀的表達你的意圖(給某些參數預先賦值)。


       

      posted @ 2019-05-17 11:36  Legendary1  閱讀(206)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 牙克石市| 亚洲欧洲精品成人久久曰| 亚洲一区中文字幕人妻| julia无码中文字幕一区| 高潮射精日本韩国在线播放| 亚洲色拍拍噜噜噜最新网站| 成人无码精品1区2区3区免费看| 亚洲中文字幕无码爆乳| 国产精品一区二区插插插| 久久久精品国产精品久久| 久久久久久综合网天天| 国产微拍一区二区三区四区| 亚洲av成人在线一区| 欧洲lv尺码大精品久久久| 国产老肥熟一区二区三区| 亚洲一区二区三区在线观看精品中文 | 国产精品亚欧美一区二区三区| 亚洲二区中文字幕在线| 久久国产成人午夜av影院| 久久国产免费观看精品| 日韩国产成人精品视频| 国产精品一区二区性色av| 欧美精品人人做人人爱视频| 黑森林福利视频导航| 久久精品国产亚洲av久| 亚洲qingse中文字幕久久| 国产网友愉拍精品视频手机| 国产极品粉嫩尤物一线天| 久久中文字幕日韩无码视频| 国产精品伦人视频免费看| 亚洲精品国产男人的天堂| 这里只有精品在线播放| 国产一区二区三区色噜噜| 国产高清一区二区三区视频| 精品国产一区二区三区久久女人| 亚洲av日韩av永久无码电影| 国产高清在线精品一区二区三区 | 亚洲性无码av在线| 无码专区人妻系列日韩精品 | 成人亚洲一级午夜激情网| 国内不卡的一区二区三区|