python 中__init__怕磨, self解釋

self代表類的實例喂饥,而非類。同樣肠鲫,__init__也是用來初始化實例子的员帮。

http://www.jb51.net/article/85871.htm

實例來說明:


classTest:

defprt(self):

print(self)

print(self.__class__)

t=Test()

t.prt()

執(zhí)行結(jié)果如下

<__main__.Test object at 0x000000000284E080>

從上面的例子中可以很明顯的看出,self代表的是類的實例导饲。而self.class則指向類捞高。

self不必非寫成self

有很多童鞋是先學習別的語言然后學習Python的,所以總覺得self怪怪的渣锦,想寫成this硝岗,可以嗎?

當然可以袋毙,還是把上面的代碼改寫一下

classTest:

defprt(this):

print(this)

print(this.__class__)

t=Test()

t.prt()

改成this后型檀,運行結(jié)果完全一樣。

當然听盖,最好還是尊重約定俗成的習慣胀溺,使用self。

self可以不寫嗎

在Python的解釋器內(nèi)部皆看,當我們調(diào)用t.prt()時仓坞,實際上Python解釋成Test.prt(t),也就是說把self替換成類的實例腰吟。

有興趣的童鞋可以把上面的t.prt()一行改寫一下无埃,運行后的實際結(jié)果完全相同。

實際上已經(jīng)部分說明了self在定義時不可以省略毛雇,如果非要試一下嫉称,那么請看下面

classTest:

defprt():

print(self)

t=Test()

t.prt()

運行時提醒錯誤如下:prt在定義時沒有參數(shù),但是我們運行時強行傳了一個參數(shù)禾乘。

由于上面解釋過了t.prt()等同于Test.prt(t)澎埠,所以程序提醒我們多傳了一個參數(shù)t。

Traceback (most recent call last):

File "h.py", line 6, in

t.prt()

TypeError: prt() takes 0 positional arguments but 1 was given

當然始藕,如果我們的定義和調(diào)用時均不傳類實例是可以的蒲稳,這就是類方法

classTest:

defprt():

print(__class__)

Test.prt()

運行結(jié)果如下

在繼承時氮趋,傳入的是哪個實例,就是那個傳入的實例江耀,而不是指定義了self的類的實例剩胁。

先看代碼

classParent:

defpprt(self):

print(self)

classChild(Parent):

defcprt(self):

print(self)

c=Child()

c.cprt()

c.pprt()

p=Parent()

p.pprt()

運行結(jié)果如下

<__main__.Child object at 0x0000000002A47080>

<__main__.Child object at 0x0000000002A47080>

<__main__.Parent object at 0x0000000002A47240>

解釋:

運行c.cprt()時應該沒有理解問題,指的是Child類的實例祥国。

但是在運行c.pprt()時昵观,等同于Child.pprt(c),所以self指的依然是Child類的實例舌稀,由于self中沒有定義pprt()方法啊犬,所以沿著繼承樹往上找,發(fā)現(xiàn)在父類Parent中定義了pprt()方法壁查,所以就會成功調(diào)用觉至。

在描述符類中,self指的是描述符類的實例

不太容易理解睡腿,先看實例:

classDesc:

def__get__(self, ins,cls):

print('self in Desc: %s '%self)

print(self, ins,cls)

classTest:

x=Desc()

defprt(self):

print('self in Test: %s'%self)

t=Test()

t.prt()

t.x

運行結(jié)果如下:

self in Test: <__main__.Test object at 0x0000000002A570B8>

self in Desc: <__main__.Desc object at 0x000000000283E208>

<__main__.Desc object at 0x000000000283E208> <__main__.Test object at 0x0000000002A570B8>

大部分童鞋開始有疑問了语御,為什么在Desc類中定義的self不是應該是調(diào)用它的實例t嗎?怎么變成了Desc類的實例了呢席怪?

注意:此處需要睜大眼睛看清楚了应闯,這里調(diào)用的是t.x,也就是說是Test類的實例t的屬性x挂捻,由于實例t中并沒有定義屬性x碉纺,所以找到了類屬性x,而該屬性是描述符屬性细层,為Desc類的實例而已惜辑,所以此處并沒有頂用Test的任何方法唬涧。

那么我們?nèi)绻苯油ㄟ^類來調(diào)用屬性x也可以得到相同的結(jié)果疫赎。

下面是把t.x改為Test.x運行的結(jié)果。

self in Test: <__main__.Test object at 0x00000000022570B8>

self in Desc: <__main__.Desc object at 0x000000000223E208>

<__main__.Desc object at 0x000000000223E208> None

題外話:由于在很多時候描述符類中仍然需要知道調(diào)用該描述符的實例是誰碎节,所以在描述符類中存在第二個參數(shù)ins捧搞,用來表示調(diào)用它的類實例,所以t.x時可以看到第三行中的運行結(jié)果中第二項為

object at 0x0000000002A570B8>狮荔。而采用Test.x進行調(diào)用時胎撇,由于沒有實例,所以返回None殖氏。

從OO的本質(zhì)理解python中的self

舉個栗子晚树,假設我要對用戶的數(shù)據(jù)進行操作,用戶的數(shù)據(jù)包含name和age雅采。如果用面向過程的話爵憎,實現(xiàn)出來是下面這樣子的慨亲。

defuser_init(user,name,age):

user['name']=name

user['age']=age

defset_user_name(user, x):

user['name']=x

defset_user_age(user, x):

user['age']=x

defget_user_name(user):

returnuser['name']

defget_user_age(user):

returnuser['age']

myself={}

user_init(myself,'kzc',17)

printget_user_age(myself)

set_user_age(myself,20)

printget_user_age(myself)

可以看到,對用戶的各種操作宝鼓,都要傳user參數(shù)進去刑棵。

如果用面向?qū)ο蟮脑挘筒挥妹看伟製ser參數(shù)傳來傳去愚铡,把相關(guān)的數(shù)據(jù)和操作綁定在一個地方蛉签,在這個類的各個地方,可以方便的獲取數(shù)據(jù)沥寥。

之所以可以在類中的各個地方訪問數(shù)據(jù)碍舍,本質(zhì)就是綁定了self這個東西,它方法的第一個參數(shù)邑雅,當然可以不叫self乒验,叫其它名字,self只不過是個約定蒂阱。

下面是面向?qū)ο蟮膶崿F(xiàn)锻全,可以看到,結(jié)構(gòu)化多了录煤,清晰可讀鳄厌。

classUser(object):

def__init__(self,name,age):

self.name=name

self.age=age

defSetName(self,name):

self.name=name

defSetAge(self,age):

self.age=age

defGetName(self):

returnself.name

defGetAge(self):

returnself.age

u=User('kzc',17)

printu.GetName()

printu.GetAge()

從上面這個例子可以看出,其實面向?qū)ο笸τ杏玫穆栌唬徊贿^大多數(shù)人抽象的不好了嚎,封裝的不好,錯誤的運用廊营。

總結(jié)

self在定義時需要定義歪泳,但是在調(diào)用時會自動傳入。

self的名字并不是規(guī)定死的露筒,但是最好還是按照約定是用self

self總是指調(diào)用時的類的實例呐伞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市慎式,隨后出現(xiàn)的幾起案子伶氢,更是在濱河造成了極大的恐慌,老刑警劉巖瘪吏,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件癣防,死亡現(xiàn)場離奇詭異,居然都是意外死亡掌眠,警方通過查閱死者的電腦和手機蕾盯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蓝丙,“玉大人级遭,你說我怎么就攤上這事香嗓。” “怎么了装畅?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵靠娱,是天一觀的道長。 經(jīng)常有香客問我掠兄,道長像云,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任蚂夕,我火速辦了婚禮迅诬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘婿牍。我一直安慰自己侈贷,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布等脂。 她就那樣靜靜地躺著俏蛮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪上遥。 梳的紋絲不亂的頭發(fā)上搏屑,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音粉楚,去河邊找鬼辣恋。 笑死,一個胖子當著我的面吹牛模软,可吹牛的內(nèi)容都是我干的伟骨。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼燃异,長吁一口氣:“原來是場噩夢啊……” “哼携狭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起特铝,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤暑中,失蹤者是張志新(化名)和其女友劉穎壹瘟,沒想到半個月后鲫剿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡稻轨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年灵莲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片殴俱。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡政冻,死狀恐怖枚抵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情明场,我是刑警寧澤汽摹,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站苦锨,受9級特大地震影響逼泣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜舟舒,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一拉庶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧秃励,春花似錦氏仗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至币励,卻和暖如春床佳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背榄审。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工砌们, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搁进。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓浪感,卻偏偏與公主長得像,于是被迫代替她去往敵國和親饼问。 傳聞我的和親對象是個殘疾皇子影兽,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

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