Python使用類(lèi)(class)和對(duì)象(object),進(jìn)行面向?qū)ο?/a>(object-oriented programming,簡(jiǎn)稱(chēng)OOP)的編程。
下面是對(duì)面向?qū)ο蟮囊环N理解,基于分類(lèi)。
相近對(duì)象,歸為類(lèi)
在人類(lèi)認(rèn)知中,會(huì)根據(jù)屬性相近把東西歸類(lèi),并且給類(lèi)別命名。比如說(shuō),鳥(niǎo)類(lèi)的共同屬性是有羽毛,通過(guò)產(chǎn)卵生育后代。任何一只特別的鳥(niǎo)都在鳥(niǎo)類(lèi)的原型基礎(chǔ)上的。
面向?qū)ο缶褪悄M了以上人類(lèi)認(rèn)知過(guò)程。在Python語(yǔ)言,為了聽(tīng)起來(lái)酷,我們把上面說(shuō)的“東西”稱(chēng)為對(duì)象(object)。
先定義鳥(niǎo)類(lèi)
class Bird(object):
have_feather = True
way_of_reproduction = 'egg'
我們定義了一個(gè)類(lèi)別(class),就是鳥(niǎo)(Bird)。在隸屬于這個(gè)類(lèi)比的語(yǔ)句塊中,我們定義了兩個(gè)變量,一個(gè)是有羽毛(have_feather),一個(gè)是生殖方式(way_of_reproduction),這兩個(gè)變量對(duì)應(yīng)我們剛才說(shuō)的屬性(attribute)。我們暫時(shí)先不說(shuō)明括號(hào)以及其中的內(nèi)容,記為問(wèn)題1。
假設(shè)我養(yǎng)了一只小雞,叫summer。它是個(gè)對(duì)象,且屬于鳥(niǎo)類(lèi)。使用前面定義的類(lèi):
summer = Bird()
print summer.way_of_reproduction
通過(guò)第一句創(chuàng)建對(duì)象,并說(shuō)明summer是類(lèi)別鳥(niǎo)中的一個(gè)對(duì)象,summer就有了鳥(niǎo)的類(lèi)屬性,對(duì)屬性的引用是通過(guò) 對(duì)象.屬性(object.attribute) 的形式實(shí)現(xiàn)的。
可憐的summer,你就是個(gè)有毛產(chǎn)的蛋貨,好不精致。
動(dòng)作
日常認(rèn)知中,我們?cè)谕ㄟ^(guò)屬性識(shí)別類(lèi)別的時(shí)候,有時(shí)根據(jù)這個(gè)東西能做什么事情來(lái)區(qū)分類(lèi)別。比如說(shuō),鳥(niǎo)會(huì)移動(dòng)。這樣,鳥(niǎo)就和房屋的類(lèi)別區(qū)分開(kāi)了。這些動(dòng)作會(huì)帶來(lái)一定的結(jié)果,比如移動(dòng)導(dǎo)致位置的變化。
這樣的一些“行為”屬性為方法(method)。Python中通過(guò)在類(lèi)的內(nèi)部定義函數(shù),來(lái)說(shuō)明方法。
class Bird(object):
have_feather = True
way_of_reproduction = 'egg'
def move(self, dx, dy):
position = [0,0]
position[0] = position[0] + dx
position[1] = position[1] + dy
return position
summer = Bird()
print 'after move:',summer.move(5,8)
我們重新定義了鳥(niǎo)這個(gè)類(lèi)別。鳥(niǎo)新增一個(gè)方法屬性,就是表示移動(dòng)的方法move。(我承認(rèn)這個(gè)方法很傻,你可以在看過(guò)下一講之后定義個(gè)有趣些的方法)
(它的參數(shù)中有一個(gè)self,它是為了方便我們引用對(duì)象自身。方法的第一個(gè)參數(shù)必須是self,無(wú)論是否用到。有關(guān)self的內(nèi)容會(huì)在下一講展開(kāi))
另外兩個(gè)參數(shù),dx, dy表示在x、y兩個(gè)方向移動(dòng)的距離。move方法會(huì)最終返回運(yùn)算過(guò)的position。
在最后調(diào)用move方法的時(shí)候,我們只傳遞了dx和dy兩個(gè)參數(shù),不需要傳遞self參數(shù)(因?yàn)閟elf只是為了內(nèi)部使用)。
我的summer可以跑了。
子類(lèi)
類(lèi)別本身還可以進(jìn)一步細(xì)分成子類(lèi)
比如說(shuō),鳥(niǎo)類(lèi)可以進(jìn)一步分成雞,大雁,黃鸝。
在OOP中,我們通過(guò)繼承(inheritance)來(lái)表達(dá)上述概念。
class Chicken(Bird):
way_of_move = 'walk'
possible_in_KFC = True
class Oriole(Bird):
way_of_move = 'fly'
possible_in_KFC = False
summer = Chicken()
print summer.have_feather
print summer.move(5,8)
新定義的雞(Chicken)類(lèi)的,增加了兩個(gè)屬性:移動(dòng)方式(way_of_move),可能在KFC找到(possible_in_KFC)
在類(lèi)定義時(shí),括號(hào)里為了Bird。這說(shuō)明,Chicken是屬于鳥(niǎo)類(lèi)(Bird)的一個(gè)子類(lèi),即Chicken繼承自Bird。自然而然,Bird就是Chicken的父類(lèi)。Chicken將享有Bird的所有屬性。盡管我只聲明了summer是雞類(lèi),它通過(guò)繼承享有了父類(lèi)的屬性(無(wú)論是變量屬性have_feather還是方法屬性move)
新定義的黃鸝(Oriole)類(lèi),同樣繼承自鳥(niǎo)類(lèi)。在創(chuàng)建一個(gè)黃鸝對(duì)象時(shí),該對(duì)象自動(dòng)擁有鳥(niǎo)類(lèi)的屬性。
通過(guò)繼承制度,我們可以減少程序中的重復(fù)信息和重復(fù)語(yǔ)句。如果我們分別定義兩個(gè)類(lèi),而不繼承自鳥(niǎo)類(lèi),就必須把鳥(niǎo)類(lèi)的屬性分別輸入到雞類(lèi)和黃鸝類(lèi)的定義中。整個(gè)過(guò)程會(huì)變得繁瑣,因此,面向?qū)ο筇岣吡顺绦虻目芍貜?fù)使用性。
(回到問(wèn)題1, 括號(hào)中的object,當(dāng)括號(hào)中為object時(shí),說(shuō)明這個(gè)類(lèi)沒(méi)有父類(lèi)(到頭了))
將各種各樣的東西分類(lèi),從而了解世界,從人類(lèi)祖先開(kāi)始,我們就在練習(xí)了這個(gè)認(rèn)知過(guò)程,面向?qū)ο笫欠先祟?lèi)思維習(xí)慣的。所謂面向過(guò)程,也就是執(zhí)行完一個(gè)語(yǔ)句再執(zhí)行下一個(gè),更多的是機(jī)器思維。通過(guò)面向?qū)ο蟮木幊?,我們可以更方便的表達(dá)思維中的復(fù)雜想法。
總結(jié)
將東西根據(jù)屬性歸類(lèi) ( 將object歸為class )
方法是一種屬性,表示動(dòng)作
用繼承來(lái)說(shuō)明父類(lèi)-子類(lèi)關(guān)系。子類(lèi)自動(dòng)具有父類(lèi)的所有屬性。
self代表了根據(jù)類(lèi)定義而創(chuàng)建的對(duì)象。
建立對(duì)一個(gè)對(duì)象: 對(duì)象名 = 類(lèi)名()
引用對(duì)象的屬性: object.attribute