[python]面向對象高級編程1

__slots__限制class實例能添加的屬性

class 類名(object):
    __slots__ = (‘a', ‘b') # 用tuple定義允許綁定的屬性名稱```
`__slots__`定義的屬性僅對當前類實例起作用,對繼承的子類是不起作用的。除非在子類中也定義`__slots__`,這樣,**子類實例允許定義的屬性就是自身的`__slots__`加上父類的`__slots__`**。


**多重繼承**
只需要在`class a(多寫幾個就可以啦,都需要是已經定義過的類)`
`MixIn`只是為了便于區分自行在類名后面加上的,不是一種方法

**重要?。。∈褂聾property**
`@property `將方法變成了屬性,就跟寫在__init__中一樣。因此其不能用()調用,只能直接賦值
這時候你可以決定這個屬性可以讀寫或者只讀。
只讀: 不加setter方法。
讀寫:再加一個`@a.setter`方法
另外:沒有`__init__`就沒有屬性,除非在方法中輸入數據。


a = 1
b = a
a = 2
b = 1

b指向的不是a而是1這個數據的內存位置,每次給變量賦值都是直接到位置,而不是指向變量a,實例與類也是如此。

定義a為類1
定義實例在類1中
重新定義a為類2
實例仍然在類1中 ```

練習

>>> class Screen(object):
...     @property
...     def width(self):
...         return self.width
...     @width.setter
...     def width(self,value):
...         self.width = value
... 
>>> s = Screen()
>>> s.width = 1024
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in width
  File "<stdin>", line 7, in width
  File "<stdin>", line 7, in width
  [Previous line repeated 495 more times]
RecursionError: maximum recursion depth exceeded```

不知道哪里錯了就對比了教程前面的代碼,發現是少了下劃線,于是加上測試。

class Screen(object):
... @property
... def width(self):
... return self._width
... @width.setter
... def width(self,value):
... self._width = value
...
s = Screen()
s._width = 1024

然后就沒有報錯,WHY!

原因
因為此時的width方法已經變成了屬性,調用的時候直接self.width,所以內部的數據要用self._width更合適,否則會重名造成嵌套死循環
循環次數過多的時候就會造成錯誤:
RecursionError: maximum recursion depth exceeded

最終結果

class Screen(object):
    @property
    def width(self):
        return self._width
    @width.setter
    def width(self,value):
        self._width = value
    @property
    def height(self):
        return self._height
    @height.setter
    def height(self,value2):
        self._height = value2   
    @property
    def resolution(self):
        return self._height * self._width

s = Screen()
s._width = 1024
s.height = 768
print(s.resolution)```

輸出正確啦!這時候的s.height 其實和s._height輸出就一樣了,一個是方法變成的屬性,一個是方法中返回的屬性。
然后發現自己還沒有給setter加上限制條件。

class Screen(object):
@property
def width(self):
return self._width
@width.setter
def width(self,value):
if not isinstance(value,int):
raise ValueError('width must be an integer!')
if value < 0:
raise ValueError('width must bigger then 0 ')
self._width = value
@property
def height(self):
return self._height
@height.setter
def height(self,value2):
if not isinstance(value2,int):
raise ValueError('height must be an integer!')
if value2 < 0:
raise ValueError('height must bigger then 0')
self._height = value2
@property
def resolution(self):
return self._height * self._width```

然而 ,可是

>>> s = Screen()
>>> s._width = '1'
>>> s.height = 10
>>> s.resolution
'1111111111'```
WHAT???為什么沒報錯?
然后把教程里的代碼試了一下 發現依然不報錯..不懂。


------
解決:怪我前面不認真看,結合前面的限制訪問章節。
1.其實@property和@a.setter實際上是看做是定義的一個函數,其中的`s._width`可以省略,相當于直接return value,于是如果是使用`s.width`,就相當于是修改value,如果value滿足了條件就會提示錯誤。
2.但是如果是使用`s._width`,其實只是一個傳遞的媒介,改變了self.width的屬性值,但這時候的屬性值并不是通過value傳入的,而是從中間傳入,因此不會出錯,因為條件判斷的是value的值。
3.其實實際調用方法查看屬性的時候,我們是不知道內部函數的,如果你不小心知道了,就可以隨便修改,就很不安全。雖然我們默認一個下劃線就屬于private內部變量,但是全靠自覺。但是不是每個人都是好人的?。?So!如果想要隔絕內部與外部的聯系,看限制訪問章節,提供了一個方法:
把內部的變量定義為`s.__width`(2個下劃線),來限制訪問,注意區分,如果是`__init__`之類的前后都有兩個下劃線的是外部變量。即你在外部如果修改`s.__width`是做不到的,這時候寫`s.__width=...`相當于重新加了一個外部變量(屬性),即內部和外部的變量名相同但其實不一樣。這時候就算你知道了內部函數名也修改不了它的值。它已經被解析為了`_類名__name`

**這就告訴我們,如果是自己寫程序的話,在定義方法的時候,一定要注意限制訪問**
我把定義中的`_height`改為`__height`有下面的結果:

a = Screen()
a.height
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 14, in height
AttributeError: 'Screen' object has no attribute '_Screen__height'
a.height = '11'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 18, in height
ValueError: height must be an integer!
a.__height = 123
a.__height
123
a.height = 12
a.__height
123
a.height
12

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,923評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,740評論 3 420
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,856評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,175評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,931評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,321評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,383評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,533評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,082評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,891評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,618評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,319評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,732評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,987評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,794評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,076評論 2 375

推薦閱讀更多精彩內容

  • 1. 使用__slots__ 正常情況下,當我們定義了一個class,創建了一個class的實例后,我們可以給該實...
    時間之友閱讀 294評論 0 1
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,796評論 18 139
  • 使用 __slots__ 限制實例屬性, 比如,只允許對Student實例添加name和age屬性。 然后,我們試...
    時間之友閱讀 420評論 0 0
  • 01 上學期女兒班里UOI課正在探究《如何表達你自己》這個主題,邀請家長去給孩子們做個小演講。我本來想給孩子們讀親...
    蘆屋主人閱讀 1,208評論 4 17
  • 日行西邊落 水去東海流 天下無聊事 瞬間到白頭 細數來時路 暗生幾許愁 曾欲關山外 卻泊太湖舟 經春復又夏 青絲早...
    東風888閱讀 147評論 0 0