99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

Python學(xué)習(xí)之wraps修飾器

發(fā)布時(shí)間:2017-05-15 23:28  回復(fù):0  查看:2252   最后回復(fù):2017-05-15 23:28  
本文和大家分享的主要是python wraps 修飾器相關(guān)內(nèi)容,一起來看看吧,希望對大家 學(xué)習(xí)python有所幫助。
  在了解  wraps  修飾器之前,我們首先要了解  partial    update_wrapper  這兩個(gè)函數(shù),因?yàn)樵?/span>  wraps  的代碼中,用到了這兩個(gè)函數(shù)。
   partial
  首先說  partial  函數(shù),在  官方文檔  的描述中,這個(gè)函數(shù)的聲明如下:  functools.partial(func, *args, **keywords)  。它的作用就是返回一個(gè)  partial  對象,當(dāng)這個(gè)  partial  對象被調(diào)用的時(shí)候,就像通過  func(*args, **kwargs)  的形式來調(diào)用  func  函數(shù)一樣。如果有額外的  位置參數(shù)( args)  或者  關(guān)鍵字參數(shù)(*kwargs)  被傳給了這個(gè)  partial  對象,那它們也都會被傳遞給 func  函數(shù),如果一個(gè)參數(shù)被多次傳入,那么后面的值會覆蓋前面的值。
  個(gè)人感覺這個(gè)函數(shù)很像C++ 中的  bind  函數(shù),都是把某個(gè)函數(shù)的某個(gè)參數(shù)固定,從而構(gòu)造出一個(gè)新的函數(shù)來。比如下面這個(gè)例子:
   from functools  import partial
   def  add(x:int, y:int):
   return x+y
  這里創(chuàng)造了一個(gè)新的函數(shù) add2 ,只接受一個(gè)整型參數(shù),然后將這個(gè)參數(shù)統(tǒng)一加上 2
  add2 = partial(add, y=2)
  add2(3)  #  這里將會輸出 5
  這個(gè)函數(shù)是使用C 而不是 Python 實(shí)現(xiàn)的,但是官方文檔中給出了 Python 實(shí)現(xiàn)的代碼,如下所示,大家可以進(jìn)行參考:
   def  partial(func, *args, **keywords):
   def  newfunc(*fargs, **fkeywords):
  newkeywords = keywords.copy()
  newkeywords.update(fkeywords)
   return func(*args, *fargs, **newkeywords)
  newfunc.func = func
  newfunc.args = args
  newfunc.keywords = keywords
   return newfunc
   update_wrapper
  接下來,我們再來聊一聊  update_wrapper  這個(gè)函數(shù),顧名思義,這個(gè)函數(shù)就是用來更新修飾器函數(shù)的,具體更新些什么呢,我們可以直接把它的源碼搬過來看一下:
  WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
  '__annotations__')
  WRAPPER_UPDATES = ('__dict__',) def  update_wrapper(wrapper,
  wrapped,
  assigned = WRAPPER_ASSIGNMENTS,
  updated = WRAPPER_UPDATES):
   for attr  in assigned:
   try:
  value = getattr(wrapped, attr)
   except AttributeError:
   pass
   else:
  setattr(wrapper, attr, value)
   for attr  in updated:
  getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
  wrapper.__wrapped__ = wrapped
   return wrapper
  大家可以發(fā)現(xiàn),這個(gè)函數(shù)的作用就是從  被修飾的函數(shù)(wrapped)  中取出一些屬性值來,賦值給 修飾器函數(shù)(wrapper)  。為什么要這么做呢,我們看下面這個(gè)例子。
   自定義修飾器v1
  首先我們寫個(gè)自定義的修飾器,沒有任何的功能,僅有文檔字符串,如下所示:
   def  wrapper(f):
   def  wrapper_function(*args, **kwargs):
  """ 這個(gè)是修飾函數(shù) """
   return f(*args, **kwargs)
   return wrapper_function
  @wrapper def  wrapped():
  """ 這個(gè)是被修飾的函數(shù) """
  print('wrapped')
  print(wrapped.__doc__)  #  輸出 ` 這個(gè)是修飾函數(shù) `
  print(wrapped.__name__)  #  輸出 `wrapper_function`
  從上面的例子我們可以看到,我想要獲取  wrapped  這個(gè)被修飾函數(shù)的文檔字符串,但是卻獲取成了  wrapper_function  的文檔字符串,  wrapped  函數(shù)的名字也變成了  wrapper_function  函數(shù)的名字。這是因?yàn)榻o  wrapped  添加上  @wrapper  修飾器相當(dāng)于執(zhí)行了一句  wrapped = wrapper(wrapped)  ,執(zhí)行完這條語句之后,  wrapped  函數(shù)就變成了  wrapper_function  函數(shù)。遇到這種情況該怎么辦呢,首先我們可以手動地在  wrapper  函數(shù)中更改  wrapper_function    __doc__  __name__  屬性,但聰明的你肯定也想到了,我們可以直接用  update_wrapper  函數(shù)來實(shí)現(xiàn)這個(gè)功能。
   自定義修飾器v2
  我們對上面定義的修飾器稍作修改,添加了一句  update_wrapper(wrapper_function, f)  。
   from functools  import update_wrapper
   def  wrapper(f):
   def  wrapper_function(*args, **kwargs):
  """ 這個(gè)是修飾函數(shù) """
   return f(*args, **kwargs)
  update_wrapper(wrapper_function, f)  # <<   添加了這條語句
   return wrapper_function
  @wrapper def  wrapped():
  """ 這個(gè)是被修飾的函數(shù) """
  print('wrapped')
  print(wrapped.__doc__)  #  輸出 ` 這個(gè)是被修飾的函數(shù) `
  print(wrapped.__name__)  #  輸出 `wrapped`
  此時(shí)我們可以發(fā)現(xiàn),  __doc__    __name__  屬性已經(jīng)能夠按我們預(yù)想的那樣顯示了,除此之外,  update_wrapper  函數(shù)也對 __module__    __dict__  等屬性進(jìn)行了更改和更新。
   wraps修飾器
  OK ,至此,我們已經(jīng)了解了  partial    update_wrapper  這兩個(gè)函數(shù)的功能,接下來我們翻出  wraps  修飾器的源碼:
  WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__qualname__', '__doc__',
  '__annotations__')
  WRAPPER_UPDATES = ('__dict__',) def  wraps(wrapped,
  assigned = WRAPPER_ASSIGNMENTS,
  updated = WRAPPER_UPDATES):
   return partial(update_wrapper, wrapped=wrapped,
  assigned=assigned, updated=updated)
  沒錯(cuò),就是這么的簡單,只有這么一句,我們可以看出,  wraps  函數(shù)其實(shí)就是一個(gè)修飾器版的 update_wrapper  函數(shù),它的功能和  update_wrapper  是一模一樣的。我們可以修改我們上面的自定義修飾器的例子,做出一個(gè)更方便閱讀的版本。
   自定義修飾器v3
   from functools  import wraps
   def  wrapper(f):    @wraps(f)
   def  wrapper_function(*args, **kwargs):
  """ 這個(gè)是修飾函數(shù) """
   return f(*args, **kwargs)
   return wrapper_function
  @wrapper def  wrapped():
  """ 這個(gè)是被修飾的函數(shù)
  """
  print('wrapped')
  print(wrapped.__doc__)  #  輸出 ` 這個(gè)是被修飾的函數(shù) `
  print(wrapped.__name__)  #  輸出 `wrapped`
  至此,我想大家應(yīng)該明白  wraps  這個(gè)修飾器的作用了吧,就是將  被修飾的函數(shù)(wrapped)  的一些屬性值賦值給  修飾器函數(shù)(wrapper)  ,最終讓屬性的顯示更符合我們的直覺。
來源:SegmentFault
您還未登錄,請先登錄

熱門帖子

最新帖子

?