最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

舉例講解Python裝飾器

 更新時間:2020年12月24日 11:09:26   作者:柯廣  
這篇文章主要介紹了Python裝飾器的相關資料,幫助大家更好的理解和使用python,感興趣的朋友可以了解下

在Python里面,函數可以作為參數傳入一個函數,函數也可以復制給變量,通過變量調用函數。裝飾器可以擴展一個函數的功能,為函數做一個裝飾器注解,可以把裝飾器里面定義的功能于所有函數提前執(zhí)行,提升代碼的復用程度。

現在有這么個場景。

打卡

互聯網公司里面有各種員工,程序員,前臺...,程序員在打開電腦前,需要打卡,前臺要早點來開門(我也不清楚,誰開門,這里假定,前臺開門),前臺開門前也需要打卡。也就是說,打卡是所有員工的最先的公共動作,那么可以把打卡這個功能抽出來作為公共邏輯。

普通函數調用方法

自然想到,可以實現如下。

def di(f):
  print('%s 打卡,滴...' % f.__name__)
  return f()


def boot():
  print('開機')


def open():
  print('開門')


if __name__ == '__main__':
  """
  程序員開機之前,前臺開門之前,都需要先在門外指紋機打卡。
  """
  di(boot)
  di(open)

定義了一個函數di(f),可以打印f.__name__即f的函數名信息,同時返回f()的執(zhí)行結果。

注意:__name__如果作為模塊導入,module.__name__就是模塊自己的名字,如果模塊自己作為腳本執(zhí)行,返回__main__。

執(zhí)行結果:

boot 打卡,滴...
開機
open 打卡,滴...
開門

這樣設計,如果有很多函數都要調用,就很麻煩,那么裝飾器就排上了用場。

簡單裝飾器 與 @語法糖

裝飾器:在代碼運行期間動態(tài)增加功能的方式,稱之為“裝飾器”(Decorator)。

簡單裝飾器

定義一個di(f)方法,還是把要執(zhí)行的邏輯的函數作為參數傳入,里面定義一個wrapper函數,返回值是f的執(zhí)行結果。
在if __name__ == '__main__':里面,調用了這個裝飾器,不修改定義好了的函數,在運行期間動態(tài)添加功能"打卡"。

import functools

# 簡單裝飾器
def di(f):
  """
  程序員開機之前,前臺開門之前,都需要先在門外指紋機打卡。
  :param f: 傳入一個函數
  :return:
  """
  # 把原始函數的__name__等屬性復制到wrapper()
  @functools.wraps(f)
  def wrapper():
    print('%s 打卡,滴...' % f.__name__)
    return f()
  return wrapper


def boot():
  print('開機')


def open():
  print('開門')


if __name__ == '__main__':

  # 第一種,簡單裝飾器
  a = di(boot)
  a1 = di(open)
  print(a.__name__) # 結果wrapper 加@functools.wraps(f)后結果為 boot
  a()
  a1()

di(boot)的返回值a就是wrapper函數,通過a()就調用了wrapper函數,得到boot的返回值。同理,di(open)一樣。

結果

boot
boot 打卡,滴...
開機
open 打卡,滴...
開門

由于di(boot)的返回值a就是wrapper函數,那么print(a.__name__)的結果就理所當然是是wrapper,我們希望是boot,怎么辦,functools.wraps(f)這個注解可以把原始函數boot的__name__等屬性復制到wrapper(),把這行代碼注釋也能運行,那么print(a.__name__)的結果就是wrapper。

第二種,@ 語法糖
通過@語法糖,也能將裝飾器應用于函數上面,推薦。

import functools

def di(f):
  """
  程序員開機之前,前臺開門之前,都需要先在門外指紋機打卡。
  :param f: 傳入一個函數
  :return:
  """
  # 把原始函數的__name__等屬性復制到wrapper()
  @functools.wraps(f)
  def wrapper():
    print('%s 打卡,滴...' % f.__name__)
    return f()
  return wrapper


# @ 語法糖
@di
def boot2():
  print('開機')


@di
def open2():
  print('開門')
  
  
if __name__ == '__main__':

  # 第二種,@ 語法糖
  boot2()
  open2()

@di標記相當于,a2 = di(boot2) a2()。不用這么麻煩,因為加了@符號標記,直接用boot2()調用裝飾器即可。

結果

boot2 打卡,滴...
開機
open2 打卡,滴...
開門

業(yè)務邏輯函數需要參數

業(yè)務邏輯函數可能需要參數,比如:

def boot(name):
  print('%s 開機' % name)

那么,只需要將前面的裝飾器修改為:

import functools

# 業(yè)務邏輯函數需要參數
def di(f):
  """
  程序員開機之前,前臺開門之前,都需要先在門外指紋機打卡。
  :param f: 傳入一個函數
  :return:
  """
  # 把原始函數的__name__等屬性復制到wrapper()
  @functools.wraps(f)
  def wrapper(*args, **kwargs):
    print('%s 打卡,滴...' % f.__name__)
    return f(*args, **kwargs)
  return wrapper


@di
def boot(name):
  print('%s 開機' % name)


if __name__ == '__main__':
  boot('keguang')

結果:

boot 打卡,滴...
keguang 開機

給wrapper也加上*args, **kwargs參數,在boot里面直接調用f(*args, **kwargs)即可。順便提一下:

  • *args:可以傳入一個數組參數
  • **kwargs:可以傳入一個k-v對參數

先后順序對應,數組參數在前。舉例:

def f(*args, **kwargs):
  print('args=', args)
  print('kwargs=', kwargs)

print(f(1, 2, 3, a = 'a', b = 'b'))

# 結果
# args= (1, 2, 3)
# kwargs= {'a': 'a', 'b': 'b'}

帶參數的裝飾器

如果裝飾器也帶參數,比如現在如果某個員工早晨上班來得早< 9:00,咱可以做個表揚,那么相當于只需要在前面的di()外面套一層函數,di_args即可,在wrapper里面。使用這個參數

import functools

# 帶參數的裝飾器
def di_args(time):
  def di(f):
    """
    程序員開機之前,前臺開門之前,都需要先在門外指紋機打卡。
    :param f: 傳入一個函數
    :return:
    """
    # 把原始函數的__name__等屬性復制到wrapper()
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
      if time < '9:00':
        print('來的真早,很棒。。。')

      print('%s 打卡,滴...' % f.__name__)
      return f(*args, **kwargs)
    return wrapper
  return di


@di_args('8:00')
def boot(name):
  print('%s 開機' % name)


if __name__ == '__main__':
  boot('keguang')

參數在@di_args('8:00')傳入即可,有點像java里面的注解。最后還是通過boot('keguang')調用即可,結果:

來的真早,很棒。。。
boot 打卡,滴...
keguang 開機

類裝飾器

類裝飾器主要依靠類的__call__方法,當使用 @ 形式將裝飾器附加到函數上時,就會調用此方法。

# 類裝飾器
class di(object):
  def __init__(self, f):
    self._f = f

  def __call__(self, *args, **kwargs):
    print('decorator start...')
    self._f()
    print('decorator end...')


@di
def boot():
  print('開機')


if __name__ == '__main__':
  boot()

加上@di裝飾器標識,會用boot去實例化di類,然后執(zhí)行__call__函數,object表示這個類可以傳入任何類型參數。
運行結果

decorator start...
開機
decorator end...

裝飾器有一個典型的應用場景就是打log日志,如果所有邏輯都需要日志記錄程序的運行狀況,那么可以對這些邏輯(函數)加日志模塊裝飾器,就能達到相應目的。

以上就是舉例講解Python裝飾器的詳細內容,更多關于python裝飾器的資料請關注腳本之家其它相關文章!

相關文章

  • Swin?Transformer圖像處理深度學習模型

    Swin?Transformer圖像處理深度學習模型

    這篇文章主要為大家介紹了Swin?Transformer圖像處理深度學習模型詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • Python基于OpenCV的視頻圖像處理詳解

    Python基于OpenCV的視頻圖像處理詳解

    OpenCV是一個開源的,跨平臺的計算機視覺庫,它采用優(yōu)化的C/C++代碼編寫,能夠充分利用多核處理器的優(yōu)勢。本文主要和大家來聊聊基于Python?OpenCv的視頻圖像處理,感興趣的可以了解一下
    2023-02-02
  • Python網絡編程基于多線程實現多用戶全雙工聊天功能示例

    Python網絡編程基于多線程實現多用戶全雙工聊天功能示例

    這篇文章主要介紹了Python網絡編程基于多線程實現多用戶全雙工聊天功能,結合實例形式分析了Python網絡編程中使用多線程進行多用戶異步通信的原理與相關實現技巧,需要的朋友可以參考下
    2018-04-04
  • 解析Pytorch中的torch.gather()函數

    解析Pytorch中的torch.gather()函數

    本文給大家介紹了Pytorch中的torch.gather()函數,通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-11-11
  • Pytorch數據讀取與預處理該如何實現

    Pytorch數據讀取與預處理該如何實現

    這篇文章主要介紹了Pytorch數據讀取與預處理該如何實現,幫助大家更好的理解和學習使用Pytorch,感興趣的朋友可以了解下
    2021-03-03
  • Pytorch 解決自定義子Module .cuda() tensor失敗的問題

    Pytorch 解決自定義子Module .cuda() tensor失敗的問題

    這篇文章主要介紹了Pytorch 解決自定義子Module .cuda() tensor失敗的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • 使用Python的Matplotlib繪制漸變的彩色曲線

    使用Python的Matplotlib繪制漸變的彩色曲線

    這篇文章主要介紹了使用Python的Matplotlib繪制漸變的彩色曲線,Matplotlib是Python生態(tài)圈中應用最為廣泛的2D繪圖庫,通過擴展工具包mplot3d,也可以繪制簡單的3D模型,需要的朋友可以參考下
    2023-08-08
  • Python中的np.vstack()和np.hstack()詳解

    Python中的np.vstack()和np.hstack()詳解

    這篇文章主要介紹了np.vstack()和np.hstack(),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • windows系統(tǒng)Tensorflow2.x簡單安裝記錄(圖文)

    windows系統(tǒng)Tensorflow2.x簡單安裝記錄(圖文)

    這篇文章主要介紹了windows系統(tǒng)Tensorflow2.x簡單安裝記錄(圖文),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • 淺談Python基礎之列表那些事兒

    淺談Python基礎之列表那些事兒

    這篇文章主要介紹了淺談Python基礎之列表那些事兒,文中有非常詳細的代碼示例,對正在學習Python基礎的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05

最新評論

武冈市| 台南县| 正安县| 鄂伦春自治旗| 萨嘎县| 务川| 固始县| 兴国县| 枞阳县| 黄冈市| 德保县| 怀安县| 罗定市| 孟州市| 邵武市| 增城市| 彰化市| 灵石县| 筠连县| 卓资县| 福贡县| 论坛| 六安市| 安西县| 乌拉特前旗| 通河县| 金坛市| 盐源县| 沭阳县| 泸定县| 巴林左旗| 永新县| 巴林右旗| 易门县| 东至县| 安徽省| 宁津县| 五台县| 都匀市| 同江市| 威信县|