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

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

Python Decorator基礎(chǔ)

發(fā)布時間:2017-07-31 16:55  回復(fù):0  查看:2544   最后回復(fù):2017-07-31 16:55  

本文和大家分享的主要是python Decorator相關(guān)內(nèi)容,一起來看看吧,希望對大家學(xué)習(xí)python有所幫助。

  一般來說,裝飾器是一個函數(shù),接受一個函數(shù)(或者類)作為參數(shù),返回值也是也是一個函數(shù)(或者類)。首先來看一個簡單的例子:

  # -*- coding: utf-8 -*-

  def log_cost_time(func):

  def wrapped(*args, **kwargs):

  import time

  begin = time.time()

  try:

  return func(*args, **kwargs)

  finally:

  print 'func %s cost %s' % (func.__name__, time.time() - begin)

  return wrapped

  @log_cost_time

  def complex_func(num):

  ret = 0

  for i in xrange(num):

  ret += i * i

  return ret

  #complex_func = log_cost_time(complex_func)

  if __name__ == '__main__':

  print complex_func(100000)

  code snippet 0

  代碼中,函數(shù)log_cost_time就是一個裝飾器,其作用也很簡單,打印被裝飾函數(shù)運行時間。

  裝飾器的語法如下:

  @dec

  def func():pass

  本質(zhì)上等同于: func = dec(func)。

  在上面的代碼(code snippet 0)中,把line12注釋掉,然后把line18的注釋去掉,是一樣的效果。另外staticmethodclassmethod是兩個我們經(jīng)常在代碼中用到的裝飾器,如果對pyc反編譯,得到的代碼一般也都是 func = staticmthod(func)這種模式。當(dāng)然,@符號的形式更受歡迎些,至少可以少拼寫一次函數(shù)名。

  裝飾器是可以嵌套的,如

  @dec0

  @dec1

  def func():pass

  等將于 func = dec0(dec1(fun))

  裝飾器也有副作用“”,對于被log_cost_time裝飾的complex_calc, 我們查看一下complex_func.__name__,輸出是:”wrapped“”。額,這個是log_cost_time里面inner function(wrapped)的名字,調(diào)用者當(dāng)然希望輸出是”complex_func”,為了解決這個問題,python提供了兩個函數(shù)。

  · functools.update_wrapper

  原型: functools.update_wrapper(wrapper, wrapped[, assigned][, updated])

  第三個參數(shù),將wrapped的值直接復(fù)制給wrapper,默認(rèn)為(__doc__, __name__, __module__)

  第四個參數(shù),update,默認(rèn)為(__dict__)

  · unctools.wrapsupdate_wrapper的封裝

  This is a convenience function for invoking partial(update_wrapper,wrapped=wrapped,assigned=assigned,updated=updated) as a function decorator when defining a wrapper function.

  簡單改改代碼:

  import functools

  def log_cost_time(func):

  @functools.wraps(func)

  def wrapped(*args, **kwargs):

  import time

  begin = time.time()

  try:

  return func(*args, **kwargs)

  finally:

  print 'func %s cost %s' % (func.__name__, time.time() - begin)

  return wrapped

  再查看complex_func.__name__ 輸出就是 “complex_func”

  裝飾器也是可以帶參數(shù)的。我們將上面的代碼略微修改一下:

  def log_cost_time(stream):

  def inner_dec(func):

  def wrapped(*args, **kwargs):

  import time

  begin = time.time()

  try:

  return func(*args, **kwargs)

  finally:

  stream.write('func %s cost %s \n' % (func.__name__, time.time() - begin))

  return wrapped

  return inner_dec

  import sys

  @log_cost_time(sys.stdout)

  def complex_func(num):

  ret = 0

  for i in xrange(num):

  ret += i * i

  return ret

  if __name__ == '__main__':

  print complex_func(100000)

  code snippet 1

  log_cost_time函數(shù)也接受一個參數(shù),該參數(shù)用來指定信息的輸出流,對于帶參數(shù)的decorator

  @dec(dec_args)

  def func(*args, **kwargs):pass

  等價于 func = dec(dec_args)(*args, **kwargs)。

  裝飾器對類的修飾也是很簡單的,只不過平時用得不是很多。舉個例子,我們需要給修改類的__str__方法,代碼很簡單。

  def Haha(clz):

  clz.__str__ = lambda s: "Haha"

  return clz

  @Haha

  class Widget(object):

  ''' class Widget '''

  if __name__ == '__main__':

  w = Widget()

  print w

  那什么場景下有必要使用decorator呢,設(shè)計模式中有一個模式也叫裝飾器。我們先簡單回顧一下設(shè)計模式中的裝飾器模式,簡單的一句話概述

  動態(tài)地為某個對象增加額外的責(zé)任

  由于裝飾器模式僅從外部改變組件,因此組件無需對它的裝飾有任何了解;也就是說,這些裝飾對該組件是透明的。

Python Decorator基礎(chǔ) 

  回到Python中來,用decorator語法實現(xiàn)裝飾器模式是很自然的,比如文中的示例代碼,在不改變被裝飾對象的同時增加了記錄函數(shù)執(zhí)行時間的額外功能。當(dāng)然,由于Python語言的靈活性,decorator是可以修改被裝飾的對象的(比如裝飾類的例子)。decoratorpython中用途非常廣泛,下面列舉幾個方面:

  (1)修改被裝飾對象的屬性或者行為

  (2)處理被函數(shù)對象執(zhí)行的上下文,比如設(shè)置環(huán)境變量,加log之類

  (3)處理重復(fù)的邏輯,比如有N個函數(shù)都可能跑出異常,但是我們不關(guān)心這些異常,只要不向調(diào)用者傳遞異常就行了,這個時候可以寫一個catchalldecorator,作用于所用可能跑出異常的函數(shù)

  def catchall(func):

  @functools.wraps(func)

  def wrapped(*args, **kwargs):

  try:

  return func(*args, **kwargs)

  except:

  pass

  return wrapped

  (4)框架代碼,如flask, bottle等等,讓使用者很方便就能使用框架,本質(zhì)上也避免了重復(fù)代碼。

 

來源:51CTO

您還未登錄,請先登錄

熱門帖子

最新帖子

?