欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

老生常談Python進(jìn)階之裝飾器

 更新時(shí)間:2017年05月11日 07:51:53   投稿:jingxian  
下面小編就為大家?guī)?lái)一篇老生常談Python進(jìn)階之裝飾器。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

函數(shù)也是對(duì)象

要理解Python裝飾器,首先要明白在Python中,函數(shù)也是一種對(duì)象,因此可以把定義函數(shù)時(shí)的函數(shù)名看作是函數(shù)對(duì)象的一個(gè)引用。既然是引用,因此可以將函數(shù)賦值給一個(gè)變量,也可以把函數(shù)作為一個(gè)參數(shù)傳遞或返回。同時(shí),函數(shù)體中也可以再定義函數(shù)。

裝飾器本質(zhì)

可以通過(guò)編寫一個(gè)純函數(shù)的例子來(lái)還原裝飾器所要做的事。

def decorator(func):
  
  def wrap():
    print("Doing someting before executing func()")
    func()
    print("Doing someting after executing func()")

  return wrap


def fun_test():
  print("func")


fun_test = decorator(fun_test)
fun_test()

# Output:
# Doing someting before executing func()
# func
# Doing someting after executing func()

fun_test所指向的函數(shù)的引用傳遞給decorator()函數(shù)

decorator()函數(shù)中定義了wrap()子函數(shù),這個(gè)子函數(shù)會(huì)調(diào)用通過(guò)func引用傳遞進(jìn)來(lái)的fun_test()函數(shù),并在調(diào)用函數(shù)的前后做了一些其他的事情

decorator()函數(shù)返回內(nèi)部定義的wrap()函數(shù)引用

fun_test接收decorator()返回的函數(shù)引用,從而指向了一個(gè)新的函數(shù)對(duì)象

通過(guò)fun_test()調(diào)用新的函數(shù)執(zhí)行wrap()函數(shù)的功能,從而完成了對(duì)fun_test()函數(shù)的前后裝飾

Python中使用裝飾器

在Python中可以通過(guò)@符號(hào)來(lái)方便的使用裝飾器功能。

def decorator(func):
  
  def wrap():
    print("Doing someting before executing func()")
    func()
    print("Doing someting after executing func()")

  return wrap

@decorator
def fun_test():
  print("func")


fun_test()

# Output:
# Doing someting before executing func()
# func
# Doing someting after executing func()

裝飾的功能已經(jīng)實(shí)現(xiàn)了,但是此時(shí)執(zhí)行:

 

print(fun_test.__name__)

# Output:
# wrap

 fun_test.__name__已經(jīng)變成了wrap,這是應(yīng)為wrap()函數(shù)已經(jīng)重寫了我們函數(shù)的名字和注釋文檔。此時(shí)可以通過(guò)functools.wraps來(lái)解決這個(gè)問(wèn)題。wraps接受一個(gè)函數(shù)來(lái)進(jìn)行裝飾,并加入了復(fù)制函數(shù)名稱、注釋文檔、參數(shù)列表等等功能。這可以讓我們?cè)谘b飾器里面訪問(wèn)在裝飾之前的函數(shù)的屬性。

更規(guī)范的寫法:

from functools import wraps

def decorator(func):
  @wraps(func)
  def wrap():
    print("Doing someting before executing func()")
    func()
    print("Doing someting after executing func()")

  return wrap


@decorator
def fun_test():
  print("func")


fun_test()
print(fun_test.__name__)

# Output:
# Doing someting before executing func()
# func
# Doing someting after executing func()
# fun_test

帶參數(shù)的裝飾器

通過(guò)返回一個(gè)包裹函數(shù)的函數(shù),可以模仿wraps裝飾器,構(gòu)造出一個(gè)帶參數(shù)的裝飾器。

from functools import wraps

def loginfo(info='info1'):
  def loginfo_decorator(func):
    @wraps(func)
    def wrap_func(*args, **kwargs):
      print(func.__name__ + ' was called')
      print('info: %s' % info)
      
      return func(*args, **kwargs)
    return wrap_func
  return loginfo_decorator
  
@loginfo()
def func1():
  pass
  
func1()

# Output:
# func1 was called
# info: info1

@loginfo(info='info2')
def func2():
  pass

func2()
# Output:
# func2 was called
# info: info2

裝飾器類

通過(guò)編寫類的方法也可以實(shí)現(xiàn)裝飾器,并讓裝飾器具備繼承等面向?qū)ο笾懈鼘?shí)用的特性

首先編寫一個(gè)裝飾器基類:

from functools import wraps

class loginfo:
  def __init__(self, info='info1'):
    self.info = info
    
  def __call__(self, func):
    @wrap
    def wrap_func(*args, **kwargs):
      print(func.__name__ + ' was called')
      print('info: %s' % self.info)
      
      self.after()  # 調(diào)用after方法,可以在子類中實(shí)現(xiàn)
      return func(*args, **kwargs)
    return wrap_func

  def after(self):
    pass


@loginfo(info='info2')
def func1():
  pass
  
# Output:
# func1 was called
# info: info1

再通過(guò)繼承l(wèi)oginfo類,擴(kuò)展裝飾器的功能:

class loginfo_after(loginfo):
  def __init__(self, info2='info2', *args, **kwargs):
    self.info2 = info2
    super(loginfo_after, self).__init__(*args, **kwargs)

  def after(self):
    print('after: %s' % self.info2)


@loginfo_after()
def func2():
  pass

func2()
  
# Output:
# func2 was called
# info: info1
# after: info2

以上這篇老生常談Python進(jìn)階之裝飾器就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • python實(shí)現(xiàn)銀行實(shí)戰(zhàn)系統(tǒng)

    python實(shí)現(xiàn)銀行實(shí)戰(zhàn)系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)銀行實(shí)戰(zhàn)系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • Python中pygame游戲模塊的用法詳解

    Python中pygame游戲模塊的用法詳解

    Pygame是一組用來(lái)開發(fā)游戲軟件的 Python 程序模塊,Pygame 在 SDL(Simple DirectMedia Layer) 的基礎(chǔ)上開發(fā)而成,它提供了諸多操作模塊,本文給大家介紹了Python中pygame游戲模塊的用法,需要的朋友可以參考下
    2024-01-01
  • python如何快速生成時(shí)間戳

    python如何快速生成時(shí)間戳

    在本篇內(nèi)容里小編給大家整理的是關(guān)于python生成時(shí)間戳的簡(jiǎn)單方法,需要的朋友們可以學(xué)習(xí)下。
    2020-07-07
  • Pytorch自定義Dataset和DataLoader去除不存在和空數(shù)據(jù)的操作

    Pytorch自定義Dataset和DataLoader去除不存在和空數(shù)據(jù)的操作

    這篇文章主要介紹了Pytorch自定義Dataset和DataLoader去除不存在和空數(shù)據(jù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • Python pytest.main()運(yùn)行測(cè)試用例

    Python pytest.main()運(yùn)行測(cè)試用例

    這篇文章主要介紹了Python pytest.main()運(yùn)行測(cè)試用例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-12-12
  • PyTorch里面的torch.nn.Parameter()詳解

    PyTorch里面的torch.nn.Parameter()詳解

    今天小編就為大家分享一篇PyTorch里面的torch.nn.Parameter()詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-01-01
  • pandas 如何保存數(shù)據(jù)到excel,csv

    pandas 如何保存數(shù)據(jù)到excel,csv

    這篇文章主要介紹了pandas 如何保存數(shù)據(jù)到excel,csv的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • Python入門Anaconda和Pycharm的安裝和配置詳解

    Python入門Anaconda和Pycharm的安裝和配置詳解

    這篇文章主要介紹了Python入門Anaconda和Pycharm的安裝和配置詳解,文章通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • python密碼學(xué)列置換密碼學(xué)習(xí)

    python密碼學(xué)列置換密碼學(xué)習(xí)

    這篇文章主要為大家介紹了python密碼學(xué)列置換密碼學(xué)習(xí)的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • python連接數(shù)據(jù)庫(kù)的方法

    python連接數(shù)據(jù)庫(kù)的方法

    這篇文章主要為大家詳細(xì)介紹了python連接數(shù)據(jù)庫(kù)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10

最新評(píng)論