国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Python > 正文

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

2019-11-25 16:11:21
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

函數(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 wrapdef 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@decoratordef 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 wrapsdef decorator(func):  @wraps(func)  def wrap():    print("Doing someting before executing func()")    func()    print("Doing someting after executing func()")  return wrap@decoratordef 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 wrapsdef 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():  passfunc2()# Output:# func2 was called# info: info2

裝飾器類

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

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

from functools import wrapsclass 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():  passfunc2()  # Output:# func2 was called# info: info1# after: info2

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

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 泾源县| 开封市| 昌都县| 新乡县| 大城县| 阜平县| 平舆县| 乌什县| 二连浩特市| 都匀市| 贵定县| 潍坊市| 仙桃市| 鹿邑县| 呼图壁县| 迁西县| 德钦县| 河西区| 株洲县| 安龙县| 新建县| 巴楚县| 甘洛县| 邻水| 蕲春县| 长乐市| 远安县| 宝应县| 莲花县| 武安市| 右玉县| 大庆市| 新疆| 丰城市| 准格尔旗| 镇坪县| 黔东| 巴彦县| 涞源县| 航空| 六枝特区|