1. 程式人生 > 實用技巧 >python內建裝飾器 @property

python內建裝飾器 @property

最近看Robotframe中SeleniumLibrary 原始碼,發現原始碼中存在許多@property,因此看下python中內建的裝飾器。
簡言之,python 內建的裝飾器常見為3個 ,分別為@property 、@classmethod和@staticmethod。

property 原始碼分析

檢視property定義 class property(fget=None, fset=None, fdel=None, doc=None) ,說明property是一個類,包含3個可呼叫引數,和一個str的引數。返回為一個 property 屬性。


class property(object):
   def __init__(self, fget: Optional[Callable[[Any], Any]] = ...,
                fset: Optional[Callable[[Any, Any], None]] = ...,
                fdel: Optional[Callable[[Any], None]] = ...,
                doc: Optional[str] = ...) -> None: ...
   def getter(self, fget: Callable[[Any], Any]) -> property: ...
   def setter(self, fset: Callable[[Any, Any], None]) -> property: ...
   def deleter(self, fdel: Callable[[Any], None]) -> property: ...
   def __get__(self, obj: Any, type: Optional[type] = ...) -> Any: ...
   def __set__(self, obj: Any, value: Any) -> None: ...
   def __delete__(self, obj: Any) -> None: ...
   def fget(self) -> Any: ...
   def fset(self, value: Any) -> None: ...
   def fdel(self) -> None: ...

採用測試程式碼 python 版本為3.5.2

class C:
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x

    def setx(self, value):
        self._x = value

    def delx(self):
        del self._x

test = C()
x = property(test.getx,test.setx,test.delx,"I'm the 'x' property.")
test.x = 5
print(test.x)
del test.x

通過x = property(test.getx,test.setx,test.delx,"I'm the 'x' property.") 將x變更為類物件test的屬性,可以對其進行 賦值 刪除等操作。

property 作為裝飾器應用

先看下面程式碼

class number(object):
   def __init__(self):
       self._x = 1000
   
   # @property
   def get_x(self):
       return self._x

test = number()
print(test.get_x())

在方法未新增裝飾器前,get_x是一個可以修改的類的方法。而新增 @property裝飾器後,get_x 從類的方法變更為類屬性,從而呼叫方式也發生變化。
在之前的原始碼分析中,property可以傳入三個引數,前面的裝飾器只裝飾了一個函式,可以採用以下方式進行裝飾三個函式


class C:
   def __init__(self):
       self._x = None

   @property
   def x(self):
       """I'm the 'x' property."""
       return self._x

   @x.setter
   def x(self, value):
       self._x = value

   @x.deleter
   def x(self):
       del self._x
test = C()
test.x = 5
print(test.x)

可以看出這與原始碼中的結果是一樣的,實際上 原始碼中的程式碼 屬於 裝飾器的另一種呼叫方法。

小結

property 本身上就是採用類方式實現的裝飾器,若在類內部使用,則將類中定義的方法轉換為類的屬性,且將對類屬性的賦值、刪除操作變得和變數操作一樣,
可以說實現了多型。建議採用@property 裝飾器的呼叫方法。應用方式

  • 單一裝飾 直接採用@property 此裝飾器 相當於呼叫fget, 將類中的方法裝換為類屬性
  • 進一步裝飾 @x.setter 、 @x.deleter 將類方法變更為屬性,且對屬性進行 賦值和刪除操作。