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

首頁 > 編程 > Python > 正文

快速了解Python中的裝飾器

2020-02-16 11:35:15
字體:
來源:轉載
供稿:網友

需要理解的一些概念

要理解Python中的裝飾器,我覺得還是應該從最基本的概念開始:

裝飾器模式:所謂的裝飾器模式,可以簡單地理解為“在不改變原有內部實現的情況下,為函數或者類添加某種特性”。這樣我們就可以將一些與業務無關、具有通用性的代碼抽象出來,作為裝飾器附加到需要這些代碼的函數或者類之上。用面向切面編程的思想解釋就是“裝飾器應該是一個切面”。

函數是一等公民:意思就是函數可以被當成普通變量一樣使用。在Python中,可以把函數賦值給變量,可以將函數作為其它函數的參數,也可以將函數作為其它函數的返回值。

閉包:我們都知道局部作用域可以引用全局作用域中的變量,相似的,當一個函數內部又定義了其它函數的時候,內部函數可以使用外部函數所在作用域的變量,這就是閉包。

從最簡單的裝飾器做起

理解完以上的概念之后,我們嘗試一下利用這些特性實現一個簡單的裝飾器。

首先明確一下需求,我們有時候會需要在函數調用時打印一個相應的日志,雖然可以通過在所有需要打印日志的函數代碼中嵌入打印日志的代碼來實現,但這種方法不僅增加了許多重復代碼,而且在業務代碼中嵌入與業務無關的代碼增加了整體的耦合度。因此,我們需要實現一個裝飾器,這個裝飾器在函數調用時可以打印一個日志記錄函數調用行為。

如果我們有以下函數foo,代表具體的業務函數:

def foo():  print('in function foo')

我們設想通過調用foo = deco(foo)實現給函數foo增加打印日志的功能,并且不影響它原有的業務。那么在這種設想下,裝飾器deco應該也是一個函數,它接收另一個函數作為輸入,并返回一個新的、經過裝飾的函數。在Python中,我們可以這么寫:

def deco(func): # 接收一個函數作為參數  def new_func():    print(f'[log] run function {func.__name__}') # 此處使用了Python3.6的格式化字符串    func() # 閉包,在內部函數中使用了外部函數的變量  return new_func # 將新函數作為返回值返回

執行一下試試效果:

>>> foo = deco(foo)>>> foo()[log] run function fooin function foo

不錯,至此我們已經實現了一個最簡單的裝飾器!在上面的代碼中,裝飾器deco接收任意的函數作為參數,再在內部構造另一個函數,利用閉包的特性,可以在新函數里調用存在于裝飾器deco局部作用域中的函數func。

神奇的@

按照上面那么寫,每次我們都得為需要裝飾的函數賦一個新值,萬一函數或者裝飾器的數量增加了,手動寫賦值和函數調用就會變得非常麻煩。那么在Python中,有沒有更優雅的寫法呢?答案是有的,你只需要一個@符號。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 安图县| 布拖县| 田林县| 伊吾县| 民勤县| 广州市| 佛学| 五峰| 巴林左旗| 麻江县| 浦县| 淳化县| 桃园市| 桦川县| 虎林市| 翁源县| 怀宁县| 鄂伦春自治旗| 房产| 鱼台县| 石首市| 临城县| 当雄县| 瑞昌市| 元朗区| 德庆县| 米泉市| 克拉玛依市| 新晃| 萨迦县| 修武县| 镇巴县| 台北县| 达日县| 宁明县| 舞阳县| 图木舒克市| 阳信县| 霞浦县| 英山县| 阿克陶县|