Python深刻淺出property特性屬性

導語

在Java中,一般在類中定義的成員變量爲私有變量,在類的實例中不能直接經過對象.屬性直接操做,而是要經過getter和setter來操做私有變量。
而在Python中,由於有property這個概念,因此不須要寫getter和setter一堆重複的代碼來操做私有變量。Python「私有變量」一般在變量前加上「_」或者「__」,例如_attr或者__attr,這是約定俗成的規範。python

把私有屬性變成只讀特性

class MyClass:

    def __init__(self, x):
        self._x = x

這裏定義了一個MyClass類,它有一個實例變量_x,綁定了用戶傳來的x值。_x是私有變量,經過obj._x獲取私有變量不符合語言規範,進而咱們要使_x變成property(特性),經過obj.x直接訪問。函數

改造後的代碼以下:性能

class MyClass:

    def __init__(self, x):
        self._x = x

    @property
    def x(self):
        return self._x
    
>>> obj = MyClass(10)
>>> obj.x
10

咱們把_x變成了property特性,以只讀的方式獲取x的值。code

咱們如今想爲x賦值該怎樣作呢?對象

>>> obj.x = 999
Traceback (most recent call last):
  File "xxx", line 14, in <module>
    obj.x = 23
AttributeError: can't set attribute

能夠看到,拋出了AttributeError: can't set attribute。顯然,只讀方法不支持賦值。文檔

把私有變量變成可賦值的特性

咱們只須要在上述代碼改形成:get

class MyClass:

    def __init__(self, x):
        self._x = x

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

>>> obj = MyClass(10)
>>> obj.x = 999
>>> obj.x
999

能夠看到,咱們爲x添加了setter,能夠直接爲obj.x賦值操做it

property屬性可以遮蓋實例屬性

繼續上面的代碼,咱們看看如下的操做:ast

>>> obj = MyClass(10)
>>> obj.__dict__
{'_x': 999}  #此時實例變量中有_x的值
>>> obj.__dict__['x'] = 99999  #設置obj的實例變量有x值,跟property屬性重名!
>>> obj.__dict__
{'_x': 999, 'x': 99999}  #此時實例變量中有_x和x的值

>>> obj.x     #結果是obj的實例變量仍是property屬性?
10

如上代碼所示,obj對象有一個_x實例變量和一個x的property屬性,咱們又強行爲obj增長了一個x實例變量,這個實例變量x和property屬性x同名!
經過obj.x咱們得知,返回的是property屬性,說明property屬性會遮蓋實例屬性!也能夠理解爲property屬性的優先級更大!class

property類解析

咱們一般使用內置的@property裝飾器。但其實property是一個類,python中類和函數的調用方式都差很少,他們都是可調用對象
property的構造方法以下:

class property(object):
    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        """"""

它最大接受4個參數,均可覺得空。
第一個爲getter,第二個爲setter,第三個爲delete函數,第四個爲文檔。

上述代碼的另外一種寫法

class MyClass:

    def __init__(self, x):
        self._x = x

    def get_x(self):
        return self._x

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

    x = property(get_x, set_x)

>>> obj = MyClass(10)
>>> obj.x
10

如上,x是property的實例,設置了getter和setter,做爲類變量放在MyClass類中。

以上就是property屬性的解析。

相關文章
相關標籤/搜索