一位「垃圾」工程師 對Python 裝飾器的理解!

首先,本垃圾文檔工程師又來了。開始日常的水文寫作。起因是看到這個問題如何理解Python裝飾器?,正好不久前給人講過這些,本垃圾於是又開始新的一輪辣雞文章寫作行為了。

預備知識

這段代碼輸出和之前的一樣,這裡我們將在 abc1 內部定義的函數 abc 作為一個變數返回,然後我們在調用 abc1 獲取到返回值后,繼續調用返回的函數。

好了,我們再來做一個思考題,實現一個函數 add ,達到 add(m)(n) 等價於 m+n 的效果。這題如果把之前的 First-Class Member 這一概念理清楚后,我們便能很清楚的寫出來了

嗯,這裡輸出就是 3 。

正文

看了前面的預備知識后,我們便可以開始今天的主題了

Advertisements

先來看一個需求吧

現在我們有一個函數

先且不論,這樣計算時間是不是準確的,現在我們要給如下很多函數加上一個時間計算的功能

我們初略一想,嗯,Ctrl+C,Ctrl+V。emmmm 好了,現在你們不覺得這段代碼特別臟么?我們想讓他變得乾淨點怎麼辦?

我們想了想,按照之前說的 First-Class Member 的概念。然後寫出了如下的代碼

很簡單嘛,替換一下不就好了

說說 Decorator

我們前面已經實現了,在不改變函數特性的情況下,給原有的代碼新增一點功能,但是我們也覺得這樣手動的替換,太噁心了,是的 Python 官方也覺得這樣很噁心,所以新的語法糖來了

我們上面的代碼可以寫成這樣了

這段代碼會發生什麼?答:會拋出異常。為啥啊?答:因為裝飾的時候發生了替換,abc=decorator(abc) ,替換后 abc 的值為 1 。整數默認不能作為一個函數進行調用。

Advertisements

這段代碼怎麼替換的?答:time_count(decorator(decorator1(range_loop)))

嗯,現在是不是對裝飾器什麼的有了基本的了解?

擴展一下

我們想實現的效果是這樣的

好了,現在返回了一個函數來作為裝飾函數,然後我們說了 @ 其實觸發了一次替換過程,好那麼我們現在的替換是不是range_loop=time_count_plus(flag=True)(range_loop) 好了,現在大家應該很清楚了,我們在 wrap1 裡面是不是還應該有一個函數並返回?

是不是這樣就清楚多啦!

現在我們有字元串 a , a 的值可能為 +-*/ 那麼現在,我們想根據 a的值來調用對應的函數怎麼辦?

我們煎蛋一想,嗯,邏輯判斷嘛

但是這段代碼,if else 是不是太多了點?我們仔細一想,用一下 First-Class Member 的特性,然後配合 dict 實現操作符和函數之間的關聯。

總結

其實全文下來,大家應該能知道這樣一點東西。Python 中的裝飾器其實是 First-Class Member 概念的更進一層應用,我們將函數傳遞給其餘函數,包裹上新的功能后再行返回。@其實只是將這樣一個過程進行了簡化而已。在 Python 中,裝飾器無處不在,很多官方庫中的實現也依賴於裝飾器

如有侵權,請聯繫小編刪除

Advertisements

你可能會喜歡