简明python教程 --C++程序员的视角(五):面向对象的编程
面向?qū)ο蟮木幊?/h2>
在大多數(shù)時(shí)候你可以使用過(guò)程性編程,但是有些時(shí)候當(dāng)你想要編寫(xiě)大型程序或是尋求一個(gè)更加合適的解決方案的時(shí)候,你就得使用面向?qū)ο蟮木幊碳夹g(shù)。
- 對(duì)象可以使用普通的屬于對(duì)象的變量存儲(chǔ)數(shù)據(jù)。屬于一個(gè)對(duì)象或類(lèi)的變量被稱(chēng)為域。
域有兩種類(lèi)型——屬于每個(gè)實(shí)例/類(lèi)的對(duì)象或?qū)儆陬?lèi)本身。它們分別被稱(chēng)為實(shí)例變量和類(lèi)變量。 - 對(duì)象也可以使用屬于類(lèi)的函數(shù)來(lái)具有功能。這樣的函數(shù)被稱(chēng)為類(lèi)的方法。
這些術(shù)語(yǔ)幫助我們把它們與孤立的函數(shù)和變量區(qū)分開(kāi)來(lái)。域和方法可以合稱(chēng)為類(lèi)的屬性。類(lèi)使用class關(guān)鍵字創(chuàng)建。類(lèi)的域和方法被列在一個(gè)縮進(jìn)塊中。
?
self
類(lèi)的方法與普通的函數(shù)只有一個(gè)特別的區(qū)別——它們必須有一個(gè)額外的第一個(gè)參數(shù)名稱(chēng),但是在調(diào)用這個(gè)方法的時(shí)候你不為這個(gè)參數(shù)賦值,Python會(huì)提供這個(gè)值。這個(gè)特別的變量指對(duì)象本身,按照慣例它的名稱(chēng)是self。
雖然你可以給這個(gè)參數(shù)任何名稱(chēng),但是?強(qiáng)烈建議?你使用self這個(gè)名稱(chēng)——其他名稱(chēng)都是不贊成你使用的。使用一個(gè)標(biāo)準(zhǔn)的名稱(chēng)有很多優(yōu)點(diǎn)——你的程序讀者可以迅速識(shí)別它,如果使用self的話,還有些IDE(集成開(kāi)發(fā)環(huán)境)也可以幫助你。
假如你有一個(gè)類(lèi)稱(chēng)為MyClass和這個(gè)類(lèi)的一個(gè)實(shí)例MyObject。當(dāng)你調(diào)用這個(gè)對(duì)象的方法MyObject.method(arg1, arg2)的時(shí)候,這會(huì)由Python自動(dòng)轉(zhuǎn)為MyClass.method(MyObject, arg1, arg2)——這就是self的原理了。
這也意味著如果你有一個(gè)不需要參數(shù)的方法,你還是得給這個(gè)方法定義一個(gè)self參數(shù)。
?
類(lèi)
我們使用class語(yǔ)句后跟類(lèi)名,創(chuàng)建了一個(gè)新的類(lèi)。這后面跟著一個(gè)縮進(jìn)的語(yǔ)句塊形成類(lèi)體。在這個(gè)例子中,我們使用了一個(gè)空白塊,它由pass語(yǔ)句表示。
接下來(lái),我們使用類(lèi)名后跟一對(duì)圓括號(hào)來(lái)創(chuàng)建一個(gè)對(duì)象/實(shí)例。(我們將在下面的章節(jié)中學(xué)習(xí)更多的如何創(chuàng)建實(shí)例的方法)。
為了驗(yàn)證,我們簡(jiǎn)單地打印了這個(gè)變量的類(lèi)型。它告訴我們我們已經(jīng)在__main__模塊中有了一個(gè)Person類(lèi)的實(shí)例。可以注意到存儲(chǔ)對(duì)象的計(jì)算機(jī)內(nèi)存地址也打印了出來(lái)。這個(gè)地址在你的計(jì)算機(jī)上會(huì)是另外一個(gè)值,因?yàn)镻ython可以在任何空位存儲(chǔ)對(duì)象。
?
對(duì)象的方法
我們已經(jīng)討論了類(lèi)/對(duì)象可以擁有像函數(shù)一樣的方法,這些方法與函數(shù)的區(qū)別只是一個(gè)額外的self變量。現(xiàn)在我們來(lái)學(xué)習(xí)一個(gè)例子,sayHi方法沒(méi)有任何參數(shù),但仍然在函數(shù)定義時(shí)有self。
?
__init__方法
在Python的類(lèi)中有很多方法的名字有特殊的重要意義。現(xiàn)在我們將學(xué)習(xí)__init__方法的意義。
__init__方法在類(lèi)的一個(gè)對(duì)象被建立時(shí),馬上運(yùn)行。這個(gè)方法可以用來(lái)對(duì)你的對(duì)象做一些你希望的?初始化。注意,這個(gè)名稱(chēng)的開(kāi)始和結(jié)尾都是雙下劃線。
?
這里,我們把__init__方法定義為取一個(gè)參數(shù)name(以及普通的參數(shù)self)。在這個(gè)__init__里,我們只是創(chuàng)建一個(gè)新的域,也稱(chēng)為name。注意它們是兩個(gè)不同的變量,盡管它們有相同的名字。點(diǎn)號(hào)使我們能夠區(qū)分它們。
最重要的是,我們沒(méi)有專(zhuān)門(mén)調(diào)用__init__方法,只是在創(chuàng)建一個(gè)類(lèi)的新實(shí)例的時(shí)候,把參數(shù)包括在圓括號(hào)內(nèi)跟在類(lèi)名后面,從而傳遞給__init__方法。這是這種方法的重要之處。
現(xiàn)在,我們能夠在我們的方法中使用self.name域。這在sayHi方法中得到了驗(yàn)證。
?
類(lèi)與對(duì)象的變量
類(lèi)與對(duì)象的數(shù)據(jù)部分,事實(shí)上,只是與類(lèi)和對(duì)象的名稱(chēng)空間?綁定?的普通變量,即這些名稱(chēng)只在這些類(lèi)與對(duì)象的前提下有效。有兩種類(lèi)型的?域——類(lèi)的變量和對(duì)象的變量。
這是一個(gè)很長(zhǎng)的例子,但是它有助于說(shuō)明類(lèi)與對(duì)象的變量的本質(zhì)。這里,population屬于Person類(lèi),因此是一個(gè)類(lèi)的變量。name變量屬于對(duì)象(它使用self賦值)因此是對(duì)象的變量。
觀察可以發(fā)現(xiàn)__init__方法用一個(gè)名字來(lái)初始化Person實(shí)例。在這個(gè)方法中,我們讓population增加1,這是因?yàn)槲覀冊(cè)黾恿艘粋€(gè)人。同樣可以發(fā)現(xiàn),self.name的值根據(jù)每個(gè)對(duì)象指定,這表明了它作為對(duì)象的變量的本質(zhì)。
記住,你只能使用self變量來(lái)參考同一個(gè)對(duì)象的變量和方法。這被稱(chēng)為?屬性參考。
在這個(gè)程序中,我們還看到docstring對(duì)于類(lèi)和方法同樣有用。我們可以在運(yùn)行時(shí)使用Person.__doc__和Person.sayHi.__doc__來(lái)分別訪問(wèn)類(lèi)與方法的文檔字符串。
就如同__init__方法一樣,還有一個(gè)特殊的方法__del__,它在對(duì)象消逝的時(shí)候被調(diào)用。對(duì)象消逝即對(duì)象不再被使用,它所占用的內(nèi)存將返回給系統(tǒng)作它用。在這個(gè)方法里面,我們只是簡(jiǎn)單地把Person.population減1。
當(dāng)對(duì)象不再被使用時(shí),__del__方法運(yùn)行,但是很難保證這個(gè)方法究竟在?什么時(shí)候?運(yùn)行。如果你想要指明它的運(yùn)行,你就得使用del語(yǔ)句,就如同我們?cè)谝郧暗睦又惺褂玫哪菢印?/strong>
?
?
?
繼承
面向?qū)ο蟮木幊處?lái)的主要好處之一是代碼的重用,實(shí)現(xiàn)這種重用的方法之一是通過(guò)?繼承?機(jī)制。繼承完全可以理解成類(lèi)之間的?類(lèi)型和子類(lèi)型關(guān)系。
繼承有很多優(yōu)點(diǎn)。
- 如果我們?cè)黾?改變了SchoolMember中的任何功能,它會(huì)自動(dòng)地反映到子類(lèi)型之中。例如,你要為教師和學(xué)生都增加一個(gè)新的身份證域,那么你只需簡(jiǎn)單地把它加到SchoolMember類(lèi)中。然而,在一個(gè)子類(lèi)型之中做的改動(dòng)不會(huì)影響到別的子類(lèi)型。
- 另外一個(gè)優(yōu)點(diǎn)是你可以把教師和學(xué)生對(duì)象都作為SchoolMember對(duì)象來(lái)使用,這在某些場(chǎng)合特別有用,比如統(tǒng)計(jì)學(xué)校成員的人數(shù)。一個(gè)子類(lèi)型在任何需要父類(lèi)型的場(chǎng)合可以被替換成父類(lèi)型,即對(duì)象可以被視作是父類(lèi)的實(shí)例,這種現(xiàn)象被稱(chēng)為多態(tài)現(xiàn)象。
另外,我們會(huì)發(fā)現(xiàn)在?重用父類(lèi)的代碼的時(shí)候,我們無(wú)需在不同的類(lèi)中重復(fù)它。而如果我們使用獨(dú)立的類(lèi)的話,我們就不得不這么做了。
為了使用繼承,我們把基本類(lèi)的名稱(chēng)作為一個(gè)元組跟在定義類(lèi)時(shí)的類(lèi)名稱(chēng)之后。
然后,我們注意到基本類(lèi)的__init__方法專(zhuān)門(mén)使用self變量調(diào)用,這樣我們就可以初始化對(duì)象的基本類(lèi)部分。這一點(diǎn)十分重要——Python不會(huì)自動(dòng)調(diào)用基本類(lèi)的constructor,你得親自專(zhuān)門(mén)調(diào)用它。
我們還觀察到我們?cè)诜椒ㄕ{(diào)用之前加上類(lèi)名稱(chēng)前綴,然后把self變量及其他參數(shù)傳遞給它。
注意,在我們使用SchoolMember類(lèi)的tell方法的時(shí)候,我們把Teacher和Student的實(shí)例僅僅作為SchoolMember的實(shí)例。
另外,在這個(gè)例子中,我們調(diào)用了子類(lèi)型的tell方法,而不是SchoolMember類(lèi)的tell方法。可以這樣來(lái)理解,Python總是首先查找對(duì)應(yīng)類(lèi)型的方法,在這個(gè)例子中就是如此。如果它不能在導(dǎo)出類(lèi)中找到對(duì)應(yīng)的方法,它才開(kāi)始到基本類(lèi)中逐個(gè)查找。
一個(gè)術(shù)語(yǔ)的注釋——如果在繼承元組中列了一個(gè)以上的類(lèi),那么它就被稱(chēng)作?多重繼承。
Python是一個(gè)高度面向?qū)ο蟮恼Z(yǔ)言,理解這些概念會(huì)在將來(lái)有助于你進(jìn)一步深入學(xué)習(xí)Python。
?
from:?http://www.cnblogs.com/wei-li/archive/2012/03/26/2417308.html
總結(jié)
以上是生活随笔為你收集整理的简明python教程 --C++程序员的视角(五):面向对象的编程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 简明python教程 --C++程序员的
- 下一篇: 简明python教程 --C++程序员的