摘要:接下來(lái),一般都要編寫(xiě)構(gòu)造函數(shù),在寫(xiě)這個(gè)函數(shù)之前,先解釋一下什么是構(gòu)造函數(shù)。故這個(gè)函數(shù)稱為構(gòu)造函數(shù),擔(dān)負(fù)著對(duì)類進(jìn)行初始化的任務(wù)。
雖然已經(jīng)對(duì)類有了一點(diǎn)點(diǎn)模糊概念,但是,閱讀前面一講的內(nèi)容的確感到累呀,都是文字,連代碼都沒(méi)有。
本講就要簡(jiǎn)單多了,嘗試走一個(gè)類的流程。
說(shuō)明:關(guān)于類的這部分,我參考了《Learning Python》一書(shū)的講解。
創(chuàng)建類創(chuàng)建類的方法比較簡(jiǎn)單,如下:
class Person:
注意,類的名稱一般用大寫(xiě)字母開(kāi)頭,這是慣例。當(dāng)然,如果故意不遵循此慣例,也未嘗不可,但是,會(huì)給別人閱讀乃至于自己以后閱讀帶來(lái)麻煩。既然大家都是靠右走的,你就別非要在路中間睡覺(jué)了。
接下來(lái),一般都要編寫(xiě)構(gòu)造函數(shù),在寫(xiě)這個(gè)函數(shù)之前,先解釋一下什么是構(gòu)造函數(shù)。
class Person: def __init__(self, name, lang, website): self.name = name self.lang = lang self.website = website
上面的類中,首先呈現(xiàn)出來(lái)的是一個(gè)名為:__init__()的函數(shù),注意,這個(gè)函數(shù)是以兩個(gè)下劃線開(kāi)始,然后是init,最后以兩個(gè)下劃線結(jié)束。這是一個(gè)函數(shù),就跟我們此前學(xué)習(xí)過(guò)的函數(shù)一樣的函數(shù)。但是,這個(gè)函數(shù)又有點(diǎn)奇特,它的命名是用“__”開(kāi)始和結(jié)束。
請(qǐng)看官在這里要明確一個(gè)基本概念,類就是一種對(duì)象類型,和跟前面學(xué)習(xí)過(guò)的數(shù)值、字符串、列表等等類型一樣。比如這里構(gòu)建的類名字叫做Person,那么就是我們要試圖建立一種對(duì)象類型,這種類型被稱之為Person,就如同有一種對(duì)象類型是list一樣。
在構(gòu)建Person類的時(shí)候,首先要做的就是對(duì)這種類型進(jìn)行初始化,也就是要說(shuō)明這種類型的基本結(jié)構(gòu),一旦這個(gè)類型的對(duì)象被調(diào)用了,第一件事情就是要運(yùn)行這個(gè)類型的基本結(jié)構(gòu),也就是類Person的基本結(jié)構(gòu)。就好比我們每個(gè)人,在頭腦中都有關(guān)于“人”這樣一個(gè)對(duì)象類型(對(duì)應(yīng)著類),一旦遇到張三(張三是一個(gè)具體人),我們首先運(yùn)行“人”這個(gè)類的基本結(jié)構(gòu):一個(gè)鼻子兩只眼,鼻子下面一張嘴。如果張三符合這個(gè)基本機(jī)構(gòu),我們不會(huì)感到驚詫(不報(bào)錯(cuò)),如果張三不符合這個(gè)基本結(jié)構(gòu)(比如三只眼睛),我們就會(huì)感到驚詫(報(bào)錯(cuò)了)。
由于類是我們自己構(gòu)造的,那么基本結(jié)構(gòu)也是我們自己手動(dòng)構(gòu)造的。在類中,基本結(jié)構(gòu)是寫(xiě)在__init__()這個(gè)函數(shù)里面。故這個(gè)函數(shù)稱為構(gòu)造函數(shù),擔(dān)負(fù)著對(duì)類進(jìn)行初始化的任務(wù)。
還是回到Person這個(gè)類,如果按照上面的代碼,寫(xiě)好了,是不是__init__()就運(yùn)行起來(lái)了呢?不是!這時(shí)候還沒(méi)有看到張三呢,必須看到張三才能運(yùn)行。所謂看到張三,看到張三這樣一個(gè)具體的實(shí)實(shí)在在的人,此動(dòng)作,在python中有一個(gè)術(shù)語(yǔ),叫做實(shí)例化。當(dāng)類Person實(shí)例化后立刻運(yùn)行__init__()函數(shù)。
#!/usr/bin/env python #coding:utf-8 class Person: def __init__(self, name, lang, website): self.name = name self.lang = lang self.website = website info = Person("qiwsir","python","qiwsir.github.io") #實(shí)例化Person print "info.name=",info.name print "info.lang=",info.lang print "info.website=",info.website #上面代碼的運(yùn)行結(jié)果: info.name= qiwsir info.lang= python info.website= qiwsir.github.io
在上面的代碼中,建立的類Person,構(gòu)造函數(shù)申明了這個(gè)類的基本結(jié)構(gòu):name,lang,website。
注意觀察:info=Person("qiwsir","python","qiwsir.github.io"),這句話就是將類Person實(shí)例化了。也就是在內(nèi)存中創(chuàng)建了一個(gè)對(duì)象,這個(gè)對(duì)象的類型是Person類型,這個(gè)Person類型是什么樣子的呢?就是__init__()所構(gòu)造的那樣。在實(shí)例化時(shí),必須通過(guò)參數(shù)傳入具體的數(shù)據(jù):name="qiwsir",lang="python",website="qiwsir.github.io"。這樣在內(nèi)存中就存在了一個(gè)對(duì)象,這個(gè)對(duì)象的類型是Person,然后通過(guò)賦值語(yǔ)句,與變量info建立引用關(guān)系。請(qǐng)看官回憶以前已經(jīng)講述過(guò)的變量和對(duì)象的引用關(guān)系。
看官是不是有點(diǎn)暈乎了?類、實(shí)例,這兩個(gè)概念會(huì)一直伴隨著后續(xù)的學(xué)習(xí),并且,在很多的OOP模型中,都會(huì)遇到這兩個(gè)概念。為了讓看官不暈乎,這里將它們進(jìn)行比較(注意:比較的內(nèi)容,參考了《Learning Python》一書(shū))
類和實(shí)例“類提供默認(rèn)行為,是實(shí)例的工廠”,我覺(jué)得這句原話非常經(jīng)典,一下道破了類和實(shí)例的關(guān)系。看上面代碼,體會(huì)一下,是不是這個(gè)理?所謂工廠,就是可以用同一個(gè)模子做出很多具體的產(chǎn)品。類就是那個(gè)模子,實(shí)例就是具體的產(chǎn)品。所以,實(shí)例是程序處理的實(shí)際對(duì)象。
類是由一些語(yǔ)句組成,但是實(shí)例,是通過(guò)調(diào)用類生成,每次調(diào)用一個(gè)類,就得到這個(gè)類的新的實(shí)例。
對(duì)于類的:class Person,class是一個(gè)可執(zhí)行的語(yǔ)句。如果執(zhí)行,就得到了一個(gè)類對(duì)象,并且將這個(gè)類對(duì)象賦值給對(duì)象名(比如Person)。
也許上述比較還不足以讓看官理解類和實(shí)例,沒(méi)關(guān)系,繼續(xù)學(xué)習(xí),在前進(jìn)中排除疑惑。
self的作用細(xì)心的看官可能注意到了,在構(gòu)造函數(shù)中,第一個(gè)參數(shù)是self,但是在實(shí)例化的時(shí)候,似乎沒(méi)有這個(gè)參數(shù)什么事兒,那么self是干什么的呢?
self是一個(gè)很神奇的參數(shù)。
在Person實(shí)例化的過(guò)程中,數(shù)據(jù)"qiwsir","python","qiwsir.github.io"通過(guò)構(gòu)造函數(shù)(__init__())的參數(shù)已經(jīng)存入到內(nèi)存中,并且這些數(shù)據(jù)以Person類型的面貌存在組成一個(gè)對(duì)象,這個(gè)對(duì)象和變量info建立的引用關(guān)系。這個(gè)過(guò)程也可說(shuō)成這些數(shù)據(jù)附加到一個(gè)實(shí)例上。這樣就能夠以:object.attribute的形式,在程序中任何地方調(diào)用某個(gè)數(shù)據(jù),例如上面的程序中以info.name得到"qiwsir"這個(gè)數(shù)據(jù)。這種調(diào)用方式,在類和實(shí)例中經(jīng)常使用,點(diǎn)號(hào)“.”后面的稱之為類或者實(shí)例的屬性。
這是在程序中,并且是在類的外面。如果在類的里面,想在某個(gè)地方使用傳入的數(shù)據(jù),怎么辦?
隨著學(xué)習(xí)的深入,看官會(huì)發(fā)現(xiàn),在類內(nèi)部,我們會(huì)寫(xiě)很多不同功能的函數(shù),這些函數(shù)在類里面有另外一個(gè)名稱,曰:方法。那么,通過(guò)類的構(gòu)造函數(shù)中的參數(shù)傳入的這些數(shù)據(jù)也想在各個(gè)方法中被使用,就需要在類中長(zhǎng)久保存并能隨時(shí)調(diào)用這些數(shù)據(jù)。為了解決這個(gè)問(wèn)題,在類中,所有傳入的數(shù)據(jù)都賦給一個(gè)變量,通常這個(gè)變量的名字是self。注意,這是習(xí)慣,而且是共識(shí),所以,看官不要另外取別的名字了。
在構(gòu)造函數(shù)中的第一個(gè)參數(shù)self,就是起到了這個(gè)作用——接收實(shí)例化過(guò)程中傳入的所有數(shù)據(jù),這些數(shù)據(jù)是通過(guò)構(gòu)造函數(shù)后面的參數(shù)導(dǎo)入的。顯然,self應(yīng)該就是一個(gè)實(shí)例(準(zhǔn)確說(shuō)法是應(yīng)用實(shí)例),因?yàn)樗鶎?duì)應(yīng)的就是具體數(shù)據(jù)。
如果將上面的類增加兩句,看看效果:
#!/usr/bin/env python #coding:utf-8 class Person: def __init__(self, name, lang, website): self.name = name self.lang = lang self.website = website print self #打印,看看什么結(jié)果 print type(self) #運(yùn)行結(jié)果 <__main__.Person instance at 0xb74a45cc>
證實(shí)了推理。self就是一個(gè)實(shí)例(準(zhǔn)確說(shuō)是實(shí)例的引用變量)。
self這個(gè)實(shí)例跟前面說(shuō)的那個(gè)info所引用的實(shí)例對(duì)象一樣,也有屬性。那么,接下來(lái)就規(guī)定其屬性和屬性對(duì)應(yīng)的數(shù)據(jù)。上面代碼中:self.name = name,就是規(guī)定了self實(shí)例的一個(gè)屬性,這個(gè)屬性的名字也叫做name,這個(gè)屬性的數(shù)據(jù)等于構(gòu)造函數(shù)的參數(shù)name所導(dǎo)入的數(shù)據(jù)。注意,self.name中的name和構(gòu)造函數(shù)的參數(shù)name沒(méi)有任何關(guān)系,它們兩個(gè)一樣,只不過(guò)是一種起巧合(經(jīng)常巧合),或者說(shuō)是寫(xiě)代碼的人懶惰,不想另外取名字而已,無(wú)他。當(dāng)然,如果寫(xiě)成self.xxxooo = name,也是可以的。
其實(shí),從效果的角度來(lái)理解,可能更簡(jiǎn)單一些,那就是類的實(shí)例info對(duì)應(yīng)著self,info通過(guò)self導(dǎo)入實(shí)例屬性的所有數(shù)據(jù)。
當(dāng)然,self的屬性數(shù)據(jù),也不一定非得是由參數(shù)傳入的,也可以在構(gòu)造函數(shù)中自己設(shè)定。比如:
#!/usr/bin/env python #coding:utf-8 class Person: def __init__(self, name, lang, website): self.name = name self.lang = lang self.website = website self.email = "qiwsir@gmail.com" #這個(gè)屬性不是通過(guò)參數(shù)傳入的 info = Person("qiwsir","python","qiwsir.github.io") print "info.name=",info.name print "info.lang=",info.lang print "info.website=",info.website print "info.email=",info.email #info通過(guò)self建立實(shí)例,并導(dǎo)入實(shí)例屬性數(shù)據(jù) #運(yùn)行結(jié)果 info.name= qiwsir info.lang= python info.website= qiwsir.github.io info.email= qiwsir@gmail.com #打印結(jié)果
通過(guò)這個(gè)例子,其實(shí)讓我們拓展了對(duì)self的認(rèn)識(shí),也就是它不僅僅是為了在類內(nèi)部傳遞參數(shù)導(dǎo)入的數(shù)據(jù),還能在構(gòu)造函數(shù)中,通過(guò)self.attribute的方式,規(guī)定self實(shí)例對(duì)象的屬性,這個(gè)屬性也是類實(shí)例化對(duì)象的屬性,即做為類通過(guò)構(gòu)造函數(shù)初始化后所具有的屬性。所以在實(shí)例info中,通過(guò)info.email同樣能夠得到該屬性的數(shù)據(jù)。在這里,就可以把self形象地理解為“內(nèi)外兼修”了。或者按照前面所提到的,將info和self對(duì)應(yīng)起來(lái),self主內(nèi),info主外。
其實(shí),self的話題還沒(méi)有結(jié)束,后面的方法中還會(huì)出現(xiàn)它。它真的神奇呀。
構(gòu)造函數(shù)的參數(shù)前面已經(jīng)說(shuō)過(guò)了,構(gòu)造函數(shù)__init__就是一個(gè)函數(shù),只不過(guò)長(zhǎng)相有點(diǎn)古怪罷了。那么,函數(shù)中的操作在構(gòu)造函數(shù)中依然可行。比如:
def __init__(self,*args): pass
這種類型的參數(shù):*args和前面講述函數(shù)參數(shù)一樣,就不多說(shuō)了。忘了的看官,請(qǐng)去復(fù)習(xí)。但是,self這個(gè)參數(shù)是必須的,因?yàn)樗獊?lái)建立實(shí)例對(duì)象。
很多時(shí)候,并不是每次都要從外面?zhèn)魅霐?shù)據(jù),有時(shí)候會(huì)把構(gòu)造函數(shù)的某些參數(shù)設(shè)置默認(rèn)值,如果沒(méi)有新的數(shù)據(jù)傳入,就應(yīng)用這些默認(rèn)值。比如:
class Person: def __init__(self, name, lang="golang", website="www.google.com"): self.name = name self.lang = lang self.website = website self.email = "qiwsir@gmail.com" laoqi = Person("LaoQi") #導(dǎo)入一個(gè)數(shù)據(jù)name="LaoQi",其它默認(rèn)值 info = Person("qiwsir",lang="python",website="qiwsir.github.io") #全部重新導(dǎo)入數(shù)據(jù) print "laoqi.name=",laoqi.name print "info.name=",info.name print "-------" print "laoqi.lang=",laoqi.lang print "info.lang=",info.lang print "-------" print "laoqi.website=",laoqi.website print "info.website=",info.website #運(yùn)行結(jié)果 laoqi.name= LaoQi info.name= qiwsir ------- laoqi.lang= golang info.lang= python ------- laoqi.website= www.google.com info.website= qiwsir.github.io
在這段代碼中,看官首先要體會(huì)一下,“類是實(shí)例的工廠”這句話的含義,通過(guò)類Person生成了兩個(gè)實(shí)例:laoqi、info
此外,在看函數(shù)賦值的情況,允許設(shè)置默認(rèn)參數(shù)值。
至此,僅僅是初步構(gòu)建了一個(gè)類的基本結(jié)構(gòu),完成了類的初始化。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/37397.html
摘要:是一個(gè)具體的數(shù)據(jù),通過(guò)構(gòu)造函數(shù)中的參數(shù),傳給實(shí)例的屬性,在類中的另外一個(gè)方法的參數(shù)列表中第一個(gè)就是,表示要承接對(duì)象,,就是在類內(nèi)部通過(guò)對(duì)象,把它的屬性的數(shù)據(jù)傳導(dǎo)如。 上一講中創(chuàng)建了類,并且重點(diǎn)講述了構(gòu)造函數(shù)以及類實(shí)例,特別是對(duì)那個(gè)self,描述了不少。在講述構(gòu)造函數(shù)的時(shí)候特別提到,init()是一個(gè)函數(shù),只不過(guò)在類中有一點(diǎn)特殊的作用罷了,每個(gè)類,首先要運(yùn)行它,它規(guī)定了類的基本結(jié)構(gòu)。 ...
摘要:在對(duì)象接口后包裝其實(shí)現(xiàn)的細(xì)節(jié),從而隔離了代碼的修改對(duì)用戶產(chǎn)生的影響。類提供了一個(gè)新的本地作用域,最小化了變量名沖突。類其實(shí)并沒(méi)有結(jié)束,不過(guò)本講座到此對(duì)類暫告一段。 前面對(duì)類的有關(guān)內(nèi)容已經(jīng)描述不少了,其實(shí)話題遠(yuǎn)遠(yuǎn)沒(méi)有結(jié)束,不過(guò)對(duì)于初學(xué)者,掌握這些已經(jīng)算是入門(mén),在以后的實(shí)踐中,還需要進(jìn)行體會(huì)和感悟。 這幾天和幾個(gè)朋友以各種途徑討論過(guò)OOP的相關(guān)問(wèn)題,他們是:令狐蟲(chóng)、Frank、晉劍、小馮...
摘要:從運(yùn)行結(jié)果可以看出,當(dāng)子類繼承多個(gè)父類的時(shí)候,對(duì)于構(gòu)造函數(shù),只有第一個(gè)能夠被繼承,第二個(gè)就等掉了。重點(diǎn)看,類繼承了,同時(shí),在構(gòu)造函數(shù)中自己做了規(guī)定,也就是的構(gòu)造函數(shù)是按照的意愿執(zhí)行,不執(zhí)行的內(nèi)容,但是,還有一個(gè)方法,則繼承了這個(gè)方法。 在上一講代碼的基礎(chǔ)上,做進(jìn)一步修改,成為了如下程序,請(qǐng)看官研習(xí)這個(gè)程序: #!/usr/bin/env python #coding:utf-8 c...
摘要:反對(duì)者在某些領(lǐng)域?qū)Υ擞枰苑裾J(rèn)。下面再引用一段來(lái)自維基百科中關(guān)于的歷史。類的更嚴(yán)格的定義是由某種特定的元數(shù)據(jù)所組成的內(nèi)聚的包。類還可以有運(yùn)行時(shí)表示形式元對(duì)象,它為操作與類相關(guān)的元數(shù)據(jù)提供了運(yùn)行時(shí)支持。 在開(kāi)始部分,請(qǐng)看官非常非常耐心地閱讀下面幾個(gè)枯燥的術(shù)語(yǔ)解釋,本來(lái)這不符合本教程的風(fēng)格,但是,請(qǐng)看官諒解,因?yàn)榱形粚?lái)一定要閱讀枯燥的東西的。這些枯燥的屬于解釋,均來(lái)自維基百科。 1、問(wèn)題...
閱讀 1420·2021-11-24 09:39
閱讀 3699·2021-11-24 09:39
閱讀 1884·2021-11-16 11:54
閱讀 1473·2021-09-30 09:47
閱讀 1731·2021-09-26 10:16
閱讀 2355·2021-09-22 15:33
閱讀 1467·2021-09-14 18:01
閱讀 2455·2021-09-07 09:59