guxh的python筆記:面向物件之屬性
阿新 • • 發佈:2019-01-07
1,類的私有屬性
class Foo: def __init__(self, x): self.x = x
類的屬性在例項化之後是可以更改的:
f = Foo(1) print(f.x) # 1 f.x = 2 print(f.x) # 2
如果想禁止訪問屬性,即讓屬性私有,可以用“雙下劃線” 或者“單下劃線”:
class Foo: def __init__(self, x, y): self._x = x self.__y = y def __repr__(self): return 'f._x = {}, f.__y = {}'.format(self._x, self.__y)
區別是“雙下劃線”直譯器會對屬性就行“名稱更改”,而“單下劃線”不會有更改,只是約定成俗。
但是知道規則還是可以輕鬆訪問:
f = Foo(1, 1) f._x = 2 f._Foo__y = 2 print(f) # f._x = 2, f.__y = 2
所以如果只是為了屬性私有,用“單下劃線”和“雙下劃線”沒有什麼區別。
但“雙下劃線”在繼承時可以避免基類屬性被子類的屬性覆蓋。
2,屬性只讀(私有 + property)
私有屬性 + property可以讓屬性變的只讀:
class Foo: def __init__(self, x): self._x = x @property def x(self): return self._x
此時對Foo進行例項化後,可以訪問物件的屬性x,但無法給x賦值:
f = Foo(1) print(f.x) # 1 f.x = 2 # AttributeError: can't set attribute
因為例項化時的x存在私有屬性self._x中,當然可以用1中提到的訪問私有屬性的方法去修改,但這被認為是粗略的行為:
f = Foo(1) f._x= 2 print(f.x) # 2
3,屬性管理(init)
4,屬性管理(property)
對屬性的操作有:get,set,del。
property只是完成了get操作,配套的get / del分配由setter / delettr完成,組合起來就可以實現對屬性的管理:
class Foo: def __init__(self, x): self.x = x @property def x(self): return self._x @x.setter def x(self, val): if val < 0: raise ValueError('x must be >= 0') self._x = val @x.deleter def x(self): pass
再看看對x屬性的訪問情況:
f = Foo(1) print(f.x) # 1 f.x = 2 print(f.x) # 2 f = Foo(-1) # ValueError: x must be >= 0 f.x = -1 # ValueError: x must be >= 0
如果__init__中使用self._x = x會出現什麼後果?
class Foo: def __init__(self, x): self._x = x ...... f = Foo(-1) print(c.x) # -1 f.x = -1 # ValueError: x must be >= 0
self.x = x在例項化時會觸發set,而self._x = x在例項化時繞過了set,也就是不會對例項化時的引數做檢查。
另外,del可以不定義,del f.x會觸發AttributeError: can't delete attribute,這裡pass演示,del f.x沒什麼效果。
5,屬性管理(描述符)
6,動態存取屬性
getattr,setattr,delattr,hasattr