1. 何為裝飾器? 官方定義:裝飾器是一個很著名的設計模式,經常被用於有切麵需求的場景,較為經典的有插入日誌、性能測試、事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量函數中與函數功能本身無關的雷同代碼並繼續重用。概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能。 ...
1. 何為裝飾器?
官方定義:裝飾器是一個很著名的設計模式,經常被用於有切麵需求的場景,較為經典的有插入日誌、性能測試、事務處理等。裝飾器是解決這類問題的絕佳設計,有了裝飾器,我們就可以抽離出大量函數中與函數功能本身無關的雷同代碼並繼續重用。概括的講,裝飾器的作用就是為已經存在的對象添加額外的功能。
Python中總共包括三個內置裝飾器:
① staticmethod
② classmethod
③ property
更加詳細的解釋,請點擊(傳送門)
2. 屬性函數 property() 淺談
2.1 為什麼要使用 property?
通常,我們在訪問屬性和給屬性賦值的時候,都是對 類和實例 __dict__ 打交道的;但如果我們想要規範屬性訪問,有兩種方式可用:①數據描述符 ,②. property() 屬性函數。
然而,我們知道,描述符相對比較複雜,對於新手來說,用起來很吃力,那麼不妨試試property(),相對於描述符這個大的進程,property就相當於線程。
2.2 函數原型:
property(fget=None, fset=None, fdel=None, doc=None)
2.3 普通方法定義:
假設 calss Normal中有一個私有變數 __x,如下代碼所示:
1 #code 1 2 3 class Normal: 4 def __init__(self): 5 self.__x = None 6 def getx(self): 7 return self.__x 8 def setx(self, value): 9 self.__x = value 10 def delx(self): 11 del self.__x 12 13 14 tN = Normal() 15 print(tN.__count) 16 17 #輸出結果(報錯了) 18 Traceback (most recent call last): 19 File "C:/Users/Administrator/AppData/Local/Programs/Python/Python35/property.py", line 15, in <module> 20 print(tN.__count) 21 AttributeError: 'Normal' object has no attribute '__count'
為啥報錯了呢?因為 實例tN的屬性 __x 為私有屬性,不能直接訪問,為此我們只能調用內部定義的 方法;
1 tN = Normal() 2 tN.setx(10) 3 print(tN.getx()) 4 5 #輸出結果: 6 10
嗯,使用內部的方法,可以容易的得到實例的或者類的私有屬性值;
然而,如果我那一天興緻來潮,把 class Normal 的 setx方法名改成了其它(如 Normal_setx),外部很多地方用到了該函數,是不是我需要一個一個的去找該方法的調用地點,然後一個一個的改呢?
c語言或許會,但Python,一個智能化的語言,怎麼會這麼點事都解決不了呢?
那麼,該如何解決以上請呢?
哈哈,其實有兩種方法哦,聽我慢慢道來哦!
方法一:採用 屬性函數property()
1 #改進方法一 2 3 class Normal: 4 def __init__(self): 5 self.__x = None 6 def getx(self): 7 print('getx(): self.__x=', self.__x) 8 return self.__x 9 def setx(self, value): 10 self.__x = value 11 print('setx()') 12 def delx(self): 13 print('delx()') 14 del self.__x 15 16 y = property(getx, setx, delx, "I'm a property") 17 18 19 tN=Normal() 20 tN.y=10 21 tN.y 22 del tN.y 23 24 #輸出結果: 25 setx() 26 getx(): self.__x= 10 27 delx()
哈哈,直接把方法當屬性來操作了,好流弊的樣子!
方法二:採用 @property 裝飾器
1 #改進方法二 2 3 class Normal: 4 5 def __init__(self): 6 self.__x = None 7 8 @property 9 def xx(self): 10 print('getx(): self.__x=', self.__x) 11 return self.__x 12 13 @xx.setter 14 def xx(self, value): 15 self.__x = value 16 print('setx()') 17 18 @xx.deleter 19 def xx(self): 20 print('delx()') 21 del self.__x 22 23 24 tN=Normal() 25 tN.xx=10 26 tN.xx 27 del tN.xx 28 29 #輸出結果信息: 30 setx() 31 getx(): self.__x= 10 32 delx()
哈哈,怎麼樣,跟方法一輸出一樣的結果,證明,這兩種方法都可行的(註意哦,第一個一定是 @property(替代getter哦,不然會報錯))。