1. 程式人生 > >Python裝飾器之 property()

Python裝飾器之 property()

attribute 比較 智能 處理 error alt nbsp 什麽 我們

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哦,不然會報錯))。

Python裝飾器之 property()