在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
繼續上面的代碼,咱們看看如下的操做: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是一個類,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屬性的解析。