[python]面向?qū)ο蟾呒壘幊?

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

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


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

**重要!F悄弧!使用@property**
`@property `將方法變成了屬性颖杏,就跟寫在__init__中一樣纯陨。因此其不能用()調(diào)用,只能直接賦值
這時候你可以決定這個屬性可以讀寫或者只讀留储。
只讀: 不加setter方法翼抠。
讀寫:再加一個`@a.setter`方法
另外:沒有`__init__`就沒有屬性,除非在方法中輸入數(shù)據(jù)获讳。


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

b指向的不是a而是1這個數(shù)據(jù)的內(nèi)存位置阴颖,每次給變量賦值都是直接到位置,而不是指向變量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```

不知道哪里錯了就對比了教程前面的代碼,發(fā)現(xiàn)是少了下劃線帅矗,于是加上測試偎肃。

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方法已經(jīng)變成了屬性累颂,調(diào)用的時候直接self.width,所以內(nèi)部的數(shù)據(jù)要用self._width更合適凛俱,否則會重名造成嵌套死循環(huán)
循環(huán)次數(shù)過多的時候就會造成錯誤:
RecursionError: maximum recursion depth exceeded

最終結(jié)果

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輸出就一樣了,一個是方法變成的屬性蒲犬,一個是方法中返回的屬性朱监。
然后發(fā)現(xiàn)自己還沒有給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赌朋?凰狞?篇裁?為什么沒報錯?
然后把教程里的代碼試了一下 發(fā)現(xiàn)依然不報錯..不懂赡若。


------
解決:怪我前面不認真看达布,結(jié)合前面的限制訪問章節(jié)。
1.其實@property和@a.setter實際上是看做是定義的一個函數(shù)逾冬,其中的`s._width`可以省略黍聂,相當于直接return value躺苦,于是如果是使用`s.width`,就相當于是修改value产还,如果value滿足了條件就會提示錯誤匹厘。
2.但是如果是使用`s._width`,其實只是一個傳遞的媒介脐区,改變了self.width的屬性值愈诚,但這時候的屬性值并不是通過value傳入的,而是從中間傳入牛隅,因此不會出錯炕柔,因為條件判斷的是value的值。
3.其實實際調(diào)用方法查看屬性的時候媒佣,我們是不知道內(nèi)部函數(shù)的匕累,如果你不小心知道了,就可以隨便修改默伍,就很不安全欢嘿。雖然我們默認一個下劃線就屬于private內(nèi)部變量,但是全靠自覺巡验。但是不是每個人都是好人的<什濉!
So显设!如果想要隔絕內(nèi)部與外部的聯(lián)系框弛,看限制訪問章節(jié),提供了一個方法:
把內(nèi)部的變量定義為`s.__width`(2個下劃線)捕捂,來限制訪問瑟枫,注意區(qū)分,如果是`__init__`之類的前后都有兩個下劃線的是外部變量指攒。即你在外部如果修改`s.__width`是做不到的慷妙,這時候?qū)慲s.__width=...`相當于重新加了一個外部變量(屬性),即內(nèi)部和外部的變量名相同但其實不一樣允悦。這時候就算你知道了內(nèi)部函數(shù)名也修改不了它的值膝擂。它已經(jīng)被解析為了`_類名__name`

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市全闷,隨后出現(xiàn)的幾起案子叉寂,更是在濱河造成了極大的恐慌,老刑警劉巖总珠,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件屏鳍,死亡現(xiàn)場離奇詭異勘纯,居然都是意外死亡,警方通過查閱死者的電腦和手機钓瞭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門驳遵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人山涡,你說我怎么就攤上這事超埋。” “怎么了佳鳖?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵霍殴,是天一觀的道長。 經(jīng)常有香客問我系吩,道長来庭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任穿挨,我火速辦了婚禮月弛,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘科盛。我一直安慰自己帽衙,他們只是感情好,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布贞绵。 她就那樣靜靜地躺著厉萝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪榨崩。 梳的紋絲不亂的頭發(fā)上谴垫,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機與錄音母蛛,去河邊找鬼翩剪。 笑死,一個胖子當著我的面吹牛彩郊,可吹牛的內(nèi)容都是我干的前弯。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼秫逝,長吁一口氣:“原來是場噩夢啊……” “哼恕出!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起筷登,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤剃根,失蹤者是張志新(化名)和其女友劉穎哩盲,沒想到半個月后前方,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體狈醉,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年惠险,在試婚紗的時候發(fā)現(xiàn)自己被綠了苗傅。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡班巩,死狀恐怖渣慕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抱慌,我是刑警寧澤逊桦,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站抑进,受9級特大地震影響强经,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寺渗,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一匿情、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧信殊,春花似錦炬称、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鳄乏,卻和暖如春府蔗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汞窗。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工姓赤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人仲吏。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓不铆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親裹唆。 傳聞我的和親對象是個殘疾皇子誓斥,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容