使用Python有一段時(shí)間了怀樟,感覺小蟒蛇是門在很多方面很給力的語言开皿,不光是它強(qiáng)大的函數(shù)式編程,還有他它的可以不創(chuàng)建類和對(duì)象來實(shí)現(xiàn)面向?qū)ο竽J降拇蟛糠止δ堋康氖撬鼜?qiáng)大的數(shù)據(jù)類型畅铭,列表和字典譬重。
用字典的鍵來代表對(duì)象的屬性,直接賦值簿训,方法所有人公用咱娶。對(duì)于我這樣的新手來說,這招可說是屢試不爽强品,簡(jiǎn)單的小功能小游戲輕松搞定膘侮,有效減少了代碼編寫量與思考時(shí)間,甚至很多時(shí)候我忘了它是們面向?qū)ο蟮恼Z言了的榛。然而喻喳,有些情況下(雖然我還沒遇到),python中類和對(duì)象可能還是要的困曙。本著技多不壓身的原則表伦,今天我就現(xiàn)學(xué)現(xiàn)賣,給大家介紹一下Python中的類與對(duì)象的使用慷丽。同時(shí)蹦哼,也替小蟒蛇證明一下,咱真的是面向?qū)ο蟮恼Z言要糊!
一纲熏、python中的類
簡(jiǎn)單介紹下python中的類,首先是類的定義格式:
classstudent(object):
......
怎么樣锄俄,夠簡(jiǎn)潔吧局劲?去掉了一切多余的東西,Python中的類定義被縮到了最簡(jiǎn)——只要一個(gè)class關(guān)鍵字奶赠,一個(gè)類名即可鱼填,當(dāng)然,你也可以加個(gè)括號(hào)指定繼的父類毅戈。
創(chuàng)建對(duì)象的方法同樣也很簡(jiǎn)潔:
s?=?student()
與java不同苹丸,這里連new關(guān)鍵字都去掉了愤惰,自我猜測(cè)與python內(nèi)部架構(gòu)不同有關(guān),后面有機(jī)會(huì)再研究赘理。
然后宦言,是類的初始化函數(shù),創(chuàng)建對(duì)象時(shí)自動(dòng)調(diào)用:
def__init__(self)?:
#要執(zhí)行的初始化操作
你可以同時(shí)為自己的類設(shè)定屬性并賦初值商模,實(shí)現(xiàn)構(gòu)造方法的功能:
def__init__(self,?age?=20,?school?=?‘HNU’?):
self.age?=?age
selfschool?=?school
這里注意兩點(diǎn):
1 init 函數(shù)名的兩側(cè)分別要有兩個(gè)下劃線 _? (注意是兩個(gè)哦)
2 init 方法須有參數(shù)且的第一個(gè)參數(shù)必須為self(其實(shí)也不是死規(guī)定奠旺,這個(gè)后面會(huì)講)
這樣的限定似乎和python自由的原則稍有違背,但為了更大的自由施流,這點(diǎn)犧牲也是迫不得已啊响疚,因?yàn)檫@樣系統(tǒng)可以”認(rèn)出”這個(gè)函數(shù),至于self后面會(huì)講嫂沉。
最后,你可以向java里那樣給你的類賦予其他的屬性和方法
defset_name(self,name):
self.name?=?name
defcodeing(self,?language?=?‘Python’):
printself.name?+?‘在寫’?+?language
二?扮碧、解秘self
看了前面幾個(gè)例子趟章,你大概發(fā)現(xiàn)了:凡是python類中的所有方法都要有一個(gè)self參數(shù),而且這個(gè)self似乎和java中的this關(guān)鍵字很像慎王。
沒錯(cuò)蚓土,這個(gè)self確實(shí)和this很像,但是這二者還是有蠻大區(qū)別的赖淤,為了更好地理解self蜀漆,我們不妨多問幾個(gè)為什么:
1? self是什么?
想知道這個(gè)self本質(zhì)是什么咱旱,最直接的方法就是打印了确丢。為此,我們建立一個(gè)簡(jiǎn)單的類people吐限,實(shí)例化時(shí)會(huì)打印self:
classpeople:
def__init__(self):
printself
按F5運(yùn)行鲜侥,輸入測(cè)試代碼:
p?=?people()
得到打印的結(jié)果:
<__main__.people?instance?at0x0206D5F8>
不管__main__是啥,我們至少知道了诸典,self是people在內(nèi)存地址0x0206D5F8處的實(shí)例描函。因此,self在這里與java中的this一樣狐粱,代表的都是當(dāng)前對(duì)象的地址舀寓,可以用來調(diào)用當(dāng)前類中的屬性和方法,實(shí)例見上肌蜻。
2 self與this有什么不同互墓?
首先,與多數(shù)時(shí)候可以省略的this不同蒋搜,self在任何情況下絕不能省略轰豆。對(duì)于這點(diǎn)胰伍,我是這樣理解的:與java中的class不同,python中的class本質(zhì)上是一個(gè)變量酸休,只不過它里面的函數(shù)和屬性我們可以自定義骂租,所有的方法調(diào)用都要由類本身來執(zhí)行,而對(duì)象名反而成為了參數(shù)斑司,看起來就python在和我們玩一個(gè)文字游戲渗饮,舉個(gè)例子:
s?=?student()
這是條創(chuàng)建對(duì)象的語句,python在執(zhí)行時(shí)做了一個(gè)變換:
student.__init__(s)
同樣的,
s.coding('python')
在執(zhí)行時(shí)換成了:
student.coding(s,'python')
所以宿刮,我們很容易理解為什么類中的方法必須要帶self參數(shù)了互站。是python與java中class的不同決定了this和self本質(zhì)的不同。
2 self一定非得是self嗎僵缺?
你也許感覺到了胡桃,self其實(shí)就是一個(gè)普通參數(shù),所以磕潮,self在python中不能算是關(guān)鍵字翠胰,因?yàn)槟憧梢越o他任意起名——myself、yourself啥都沒問題自脯,甚至abc這種腦殘名字都可以的之景,所以,你大可這樣做:
defmust_self(not_self):
Print?not_self
執(zhí)行這個(gè)函數(shù)
p.must_self()
最后還是可以得到打印的結(jié)果:
<__main__.people?instance?at0x0206D5F8>
因此膏潮,self在python中不算是關(guān)鍵字锻狗,它只是當(dāng)前對(duì)象的地址的一個(gè)象征,我們可以任意命名焕参,只不過為了交流方便轻纪,python社區(qū)中約定俗成地把它叫做self,你也完全不必墨守成規(guī)叠纷。
3 self還有什么用?
好了桐磁,到此為止我們探討了self的本質(zhì),并且知道讲岁,self可以實(shí)現(xiàn)java中this的全部功能我擂,但是,你或許想問缓艳,它難道就沒有更多的用途了嗎校摩?
其實(shí)是有的,那就是區(qū)分全局變量函數(shù)和類中的變量函數(shù)阶淘。(有篇博客作者把這叫做“防止非限定調(diào)用引起的全局變量”衙吩,一開始搞得我一頭霧水,不知道他怎么想的)
Python中溪窒,類之外可以定義很多全局變量和函數(shù)坤塞,這是它與java明顯的不同冯勉。為了解釋器準(zhǔn)確的找到函數(shù)或變量,需要使用self來限定方法變量的區(qū)域摹芙,這樣解釋器就能快速知道你調(diào)用的是類中的變量還是全局的變量了灼狰。例子如下:
a?=1
defsay():
print'調(diào)用了全局方法'
classpeople:
a?=100
defsay(self):
print'調(diào)用了類的方法'
defdo(self):
say()
print'a?=?',a
這里我們定義了兩對(duì)同名的變量和函數(shù),a和say浮禾,看一看do方法會(huì)執(zhí)行哪一個(gè)
p?=?people()
p.do()
運(yùn)行結(jié)果:
調(diào)用了全局方法
a?=1
顯然交胚,變量重名并不影響調(diào)用,而在不用self限定時(shí)盈电,系統(tǒng)會(huì)默認(rèn)調(diào)用全局變量和方法蝴簇,只有用self才能調(diào)用類自己的方法和變量 :
a?=1
defsay():
print'調(diào)用了全局方法'
classpeople:
a?=100
defsay(self):
print'調(diào)用了類的方法'
defdo(self):
say()
self.say()
print'a?=?',?a
print'self.a?=?',self.a
p?=?people()
p.do()
運(yùn)行結(jié)果:
調(diào)用了全局方法
調(diào)用了類的方法
a?=1
self.a?=100
好了,關(guān)于類的使用與self大概就介紹這些匆帚,但不知道你們有沒有這種感覺熬词,那就是python中使用類有點(diǎn)怪怪的,當(dāng)然吸重,很大一部分原因和那無所不在的self有關(guān)互拾。不過,我的觀點(diǎn)是晤锹,python的創(chuàng)始者也不支持你在程序中使用類摩幔。因?yàn)閺?qiáng)大的字典和列表已經(jīng)可以輕松實(shí)現(xiàn)類的很多功能彤委,所以類存在的必要性并不是特別大鞭铆。而且,想要把java的開發(fā)模式硬搬到python里也無疑是個(gè)愚蠢的決定焦影,因?yàn)樵谖已壑谐邓欤琾ython是門比java高級(jí)的多,也靈活得多的語言斯辰,它有自己的Coding
style舶担,不要盲從他人。