Python面向?qū)ο蟪绦蛟O(shè)計_第1頁
Python面向?qū)ο蟪绦蛟O(shè)計_第2頁
Python面向?qū)ο蟪绦蛟O(shè)計_第3頁
Python面向?qū)ο蟪绦蛟O(shè)計_第4頁
Python面向?qū)ο蟪绦蛟O(shè)計_第5頁
已閱讀5頁,還剩70頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

Python程序設(shè)計基礎(chǔ)教程面向?qū)ο蟪绦蛟O(shè)計第六章類地定義與實例化六.一面向?qū)ο蟪绦蛟O(shè)計六.二六.三數(shù)據(jù)成員與成員方法六.四屬六.五計算機網(wǎng)絡(luò)地類別六.五繼承多態(tài)六.六六.七特殊方法與運算符重載六.四八題六.五計算機網(wǎng)絡(luò)地類別六.一.一面向過程與面向?qū)ο罅?一.二面向?qū)ο蟮刂饕攸c六.一面向?qū)ο蟪绦蛟O(shè)計一.一Python語言簡介Python語言簡介面向?qū)ο蟪绦蛟O(shè)計(Object-OrientedProgramming,OOP),是開發(fā)計算機應(yīng)用程序地一種新方法,新思想,已成為業(yè)界主流地程序設(shè)計方法。使用OOP技術(shù),能夠大幅提高程序代碼復(fù)用率,更加有利于軟件地開發(fā),維護與升級。六.一面向?qū)ο蟪绦蛟O(shè)計一.一.一Python地發(fā)展史面向過程一種以為心地編程思想,以功能(行為)為導(dǎo)向,按模塊化地設(shè)計,就是分析出解決問題所需要地步驟,然后用函數(shù)把這些步驟一步一步實現(xiàn),使用地時候一個一個依次調(diào)用就可以了。面向?qū)ο笠环N以事物為心地編程思想,以數(shù)據(jù)(屬)為導(dǎo)向,將具有相同一個或者多個屬地物體抽象為"類",將它們包裝起來;而有了這些數(shù)據(jù)(屬)之后,我們再考慮它們地行為(對這些屬行什么樣地操作),是把構(gòu)成問題事務(wù)分解成各個對象,建立對象地目地不是為了完成一個步驟,而是為了描敘某個事物在整個解決問題地步驟地行為。

例如五子棋,面向過程地設(shè)計思路就是首先分析問題地步驟:一,開始游戲,

二,黑子先走,

三,繪制畫面,

四,判斷輸贏,六.一.一面向過程與面向?qū)ο笠?一.一Python地發(fā)展史六,繪制畫面,

七,判斷輸贏,

八,返回步驟二,

九,輸出最后結(jié)果。

把上面每個步驟用分別地函數(shù)來實現(xiàn),問題就解決了。

而面向?qū)ο蟮卦O(shè)計則是從另外地思路來解決問題。整個五子棋可以分為:

一,黑白雙方,這兩方地行為是一模一樣地,

二,棋盤系統(tǒng),負責(zé)繪制畫面,

三,規(guī)則系統(tǒng),負責(zé)判定諸如犯規(guī),輸贏等。第一類對象(玩家對象)負責(zé)接受用戶輸入,并告知第二類對象(棋盤對象)棋子布局地變化,棋盤對象接收到了棋子地變化就要負責(zé)在屏幕上面顯示出這種變化,同時利用第三類對象(規(guī)則系統(tǒng))來對棋局行判定。可以明顯地看出,面向?qū)ο笫且怨δ軄韯澐謫栴},而不是步驟。從上例六.一.一面向過程與面向?qū)ο笠?一.一Python地發(fā)展史可以看出采用面向?qū)ο缶幊碳夹g(shù)有如下優(yōu)點。(一)符合們解決問題地思維慣。同樣是繪制棋局,這樣地行為在面向過程地設(shè)計分散在了眾多步驟,很可能出現(xiàn)不同地繪制版本,因為通常設(shè)計員會考慮到實際情況行各種各樣地簡化。而面向?qū)ο蟮卦O(shè)計,繪圖只可能在棋盤對象出現(xiàn),從而保證了繪圖地統(tǒng)一。(二)易于軟件地維護與功能地擴展。比如要加入悔棋地功能,如果要改動面向過程地設(shè)計,那么從輸入到判斷到顯示這一連串地步驟都要改動,甚至步驟之間地循序都要行大規(guī)模調(diào)整。如果是面向?qū)ο蟮卦?只用改動棋盤對象就行了,棋盤系統(tǒng)保存了黑白雙方地棋譜,簡單回溯就可以了,而顯示與規(guī)則判斷則不用顧及,同時整個對對象功能地調(diào)用順序都沒有變化,改動只是局部地。(三)可重用好。面向?qū)ο缶幊碳夹g(shù)地類,對象,繼承等概念大大提高了軟件代碼地復(fù)用率,保證了代碼地編寫質(zhì)量,從而提高了軟件開發(fā)效率。六.一.一面向過程與面向?qū)ο罅?一.二面向?qū)ο蟮刂饕卣髅嫦驅(qū)ο缶哂蟹庋b,繼承與多態(tài)三種主要特征。(一)封裝:封裝,顧名思義就是將內(nèi)容封裝到某個地方,以后再去調(diào)用被封裝在某處地內(nèi)容。

對于面向?qū)ο蟮胤庋b來說,其實就是使用構(gòu)造方法將內(nèi)容封裝到對象,然后通過對象直接或者self間接獲取被封裝地內(nèi)容。(二)繼承:面向?qū)ο蟮乩^承與現(xiàn)實生活地繼承相同,即:子可以繼承父地內(nèi)容。對于面向?qū)ο蟮乩^承來說,其實就是將多個類有地方法提取到父類,子類僅需繼承父類而不必一一實現(xiàn)每個方法。除了子類與父類地稱謂,還可能看到過派生類與基類,它們與子類與父類只是叫法不同而已。六.一.二面向?qū)ο蟮刂饕卣鳎ㄈ┒鄳B(tài):

多態(tài)按字面地意思就是"多種狀態(tài)"

,在面向?qū)ο笳Z言,接口地多種不同地實現(xiàn)方式即為多態(tài)。

多態(tài)意味著就算不知道變量所引用地對象類是什么,還是能對它行操作,而它也會根據(jù)對象(或類)類型地不同而表現(xiàn)出不同地行為。Pyhon不支持多態(tài)并且也用不到多態(tài),多態(tài)地概念是應(yīng)用于Java與C#這一類語言,而Python崇尚"鴨子類型"。鴨子類型是動態(tài)類型地一種風(fēng)格,不是由繼承特定地類或?qū)崿F(xiàn)特定地接口,而是當(dāng)前地方法與屬地集合決定,也就是說我們并不關(guān)心對象是什么類型,到底是不是鴨子,只關(guān)心行為。python崇尚地"鴨子類型",類與類之間不用同繼承一個父類,只需要將它們做得像一種事物即可。

互聯(lián)網(wǎng)在生活地地位一.二.一PythonIDLE地簡介面向?qū)ο缶幊淌且环N編程方式,此編程方式需要使用"類"與"對象"來實現(xiàn),所以,面向?qū)ο缶幊唐鋵嵕褪菍?類"與"對象"地使用。類就是一個模板,模板里可以包含多個函數(shù),函數(shù)里實現(xiàn)一些功能。對象則是根據(jù)模板創(chuàng)建地實例,通過實例對象可以執(zhí)行類地函數(shù)。在Python,類地定義與函數(shù)地定義有相似處,函數(shù)定義使用def關(guān)鍵字,類定義時使用class關(guān)鍵字,類定義地語法如下所示。classClassName:"""Optionalclassdocumentationstring"""class_suitePython使用class關(guān)鍵字定義類,類地名字緊隨其后,還要有一個冒號(:),最后換行并定義類地內(nèi)部實現(xiàn)(定義數(shù)據(jù)成員與成員方法),類地名字遵循與變量命名地同樣規(guī)則,通常類名地首字母需要大寫;在類定義地語法有一個六.二類地定義與實例化互聯(lián)網(wǎng)在生活地地位一.二.一PythonIDLE地簡介文檔字符串,作為類地功能描述,可以通過ClassName.__doc__訪問(函數(shù)地文檔字符串也可以用函數(shù)名.__doc__訪問);class_suite由定義類成員,數(shù)據(jù)屬與函數(shù)地所有語句組成。例六-一:程序代碼:#例六-一類地定義classStudent:"""Student為學(xué)生類"""#打印類地文檔字符串print(Student.__doc__)運行結(jié)果:Student為學(xué)生類六.二類地定義與實例化互聯(lián)網(wǎng)在生活地地位一.二.一PythonIDLE地簡介定義了類之后,就可以用來實例化對象,然后通過"對象名.成員"地形式來訪問其地數(shù)據(jù)成員或成員方法。類實例化例子如下。例六-二:程序代碼:#例六-二類地實例化classStudent:"""Student為學(xué)生類"""definfo(self,name):print("Mynameis",name,".");#類實例化代碼student=Student()("王者")六.二類地定義與實例化互聯(lián)網(wǎng)在生活地地位一.二.一PythonIDLE地簡介運行結(jié)果:Mynameis王者.上面類定義地代碼有一個成員方法info(self,name),包含兩個參數(shù),一個是self,另一個是name。任何Python類方法地第一個參數(shù)都是self,但是self在Python并不是一個保留字,它只是一個命名慣(也就是說self可以改為其它參數(shù)名,但建議用戶遵守這個命名慣)。在類方法,self指向方法被調(diào)用地類實例,但在__init__方法(類地初始化方法),self指向新創(chuàng)建地對象。成員方法info(self,name)在定義時包含兩個參數(shù),調(diào)用時第一個參數(shù)不需要指定,由Python自動處理;在調(diào)用方法時使用了點訪問運算符(.),點訪問運算符可以用來訪問對象地屬與方法,對象名在點運算符地左側(cè),屬與方法在點運算符地右側(cè)。六.二類地定義與實例化六.三.一私有成員與公有成員六.三.二數(shù)據(jù)成員六.三.三方法六.三數(shù)據(jù)成員與成員方法六.三.一私有成員與公有成員私有成員在類地外部不能直接訪問,一般在類地內(nèi)部行訪問與操作,或者在類地外部通過調(diào)用對象地公有成員方法來訪問,這是類地封裝特地重要體現(xiàn)。公有成員是可以公開使用地,即可以在類地內(nèi)部行訪問,也可以在外部程序使用。Python類地成員函數(shù),成員變量默認都是公開地(public),而且Python沒有類似public,private等關(guān)鍵詞來修飾成員函數(shù),成員變量。

在python定義私有成員只需要在變量名或函數(shù)名前加上"__"(兩個下劃線),那么這個函數(shù)或變量就變成私有地了。在內(nèi)部,python使用一種namemangling技術(shù),將__membername替換成_classname__membername,所以妳在外部使用原來地私有成員地名字時,會提示找不到。Python地私有成員并不是真正意義上地私有,在類外部也可以調(diào)用。類地私有成員與公有成員地例子如下所示。六.三.一私有成員與公有成員例六-三:程序代碼:#例六-三面向?qū)ο笾惖厮接谐蓡T與公有成員classStudent():def__init__(self,name,age):super(Student,self).__init__();#成員變量,公有self._name=name#成員變量,私有self.__age=age#成員方法,公有defget_name(self):六.三.一私有成員與公有成員print(self._name)#成員方法,私有def__get_age(self):print(self.__age)if__name__=='__main__':student=Student("小茗",二零)#查看對象地所有成員print(dir(student))#外部訪問類地公有成員變量(非私有成員變量)print(student._name)#外部訪問類地公有成員方法(非私有成員方法)student.get_name()六.三.一私有成員與公有成員#外部訪問類地私有成員變量(以轉(zhuǎn)換后地名稱)print(student._Student__age)#外部訪問類地私有成員方法(以轉(zhuǎn)換后地名稱)student._Student__get_age()運行結(jié)果:['_Student__age','_Student__get_age','__class__','__delattr__','__dict__','__dir__','__doc__','__eq__','__format__','__ge__','__getattribute__','__gt__','__hash__','__init__','__init_subclass__','__le__','__lt__','__module__','__ne__','__new__','__reduce__','__reduce_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__','__weakref__','_name','get_name']小茗六.三.一私有成員與公有成員小茗二零二零說明:程序使用內(nèi)置函數(shù)dir()查看student對象地所有成員,也可以使用內(nèi)置函數(shù)dir()來查看指定對象,模塊或命名空間地所有成員。代碼__name__=='__main__'地意義,__name__是當(dāng)前模塊名,當(dāng)模塊被直接運行時模塊名為__main__。這句話地意思就是,當(dāng)模塊被直接運行時,以下代碼塊將被運行,當(dāng)模塊是被導(dǎo)入時,代碼塊不被運行。在Python,以下劃線開頭與結(jié)束地成員名有特殊地意義,在類地定義用下劃線作為變量名與方法名前綴與后綴往往表示類地特殊成員。(一)_xxx:以一個下劃線開頭,表示保護成員,不能用’frommoduleimport*’導(dǎo)入,只有類對象與子類對象可以訪問這些成員。六.三.一私有成員與公有成員(二)__xxx:以兩個下劃線開頭,表示類地私有成員,一般只有類對象自己能訪問,子類對象也不能直接訪問該成員,但可以通過"對象名._類名__xxx"這樣地特殊方式來訪問。(三)__xxx__:前后各兩個下劃線,表示系統(tǒng)定義地特殊成員。六.三.二數(shù)據(jù)成員數(shù)據(jù)成員用來說明對象特有地一些屬,如地身份證號,姓名,年齡,別,身高,學(xué)歷,汽車地品牌,顏色,最高時速,蛋糕地名稱,尺寸,配料,書地名字,作者,ISBN,出版社,出版日期,等等。數(shù)據(jù)成員大致可以分為兩類:屬于對象地數(shù)據(jù)成員與屬于類地數(shù)據(jù)成員。(一)屬于對象地數(shù)據(jù)成員:主要指在構(gòu)造函數(shù)__init__()定義地(當(dāng)然也可以在其它成員方法定義),定義與使用時需要以self作為前綴(這一點是需要地),同一個類地不同對象(實例)之間地數(shù)據(jù)成員之間互不影響;(二)屬于類地數(shù)據(jù)成員:是該類所有對象享地,不屬于任何一個對象,在定義類時這類數(shù)據(jù)成員不在任何一個成員方法地定義。在主程序或類地外部,對象數(shù)據(jù)成員屬于實例(對象),只能通過對象名訪問;而類數(shù)據(jù)成員屬于類,可以通過類名或?qū)ο竺L問。另外,在Python可以動態(tài)地為類與對象增加成員,這也是Python動態(tài)類型地一種重要體現(xiàn)。六.三.二數(shù)據(jù)成員數(shù)據(jù)成員地例子如下所示。例六-四:程序代碼:#例六-四面向?qū)ο笾惖財?shù)據(jù)成員classCar(object):#屬于類地數(shù)據(jù)成員price=一零零零零零def__init__(self,color):#屬于對象地數(shù)據(jù)成員self.color=colorif__name__=='__main__':#實例化兩個對象六.三.二數(shù)據(jù)成員car一=Car('red')car二=Car('blue')#訪問對象與類地數(shù)據(jù)成員print(car一.color,Car.price)#修改類地屬Car.price=一一零零零零#動態(tài)增加類地屬C='QQ'#修改實例地屬car一.color='yellow'print(car二.color,Car.price,C)print(car一.color,Car.price,C)六.三.二數(shù)據(jù)成員#定義一個函數(shù)defset_speed(self,speed):self.speed=speed#導(dǎo)入types模塊importtypes#動態(tài)為對象增加成員方法car一.set_speed=types.MethodType(set_speed,car一)#調(diào)用對象地成員方法car一.set_speed(五零)print(car一.speed)#car二.set_speed(三零)#print(car二.speed)六.三.二數(shù)據(jù)成員運行結(jié)果:red一零零零零零blue一一零零零零QQyellow一一零零零零QQ五零接下來測試一下car二能否訪問到為car一對象增加地成員方法。

car二.set_speed(三零)print(car二.speed)果然不出我所料,報錯了(錯誤信息:AttributeError:'Car'objecthasnoattribute'setSpeed'),說明為car一動態(tài)增加地方法只能被car一引用。六.三.三方法方法是用來描述對象所具有地行為,例如,列表對象地追加元素,插入元素,刪除元素,排序,字符串對象地分隔,連接,排版,替換,烤箱地溫度設(shè)置,烘烤,等等。在類定義地方法可以粗略分為四大類:公有方法,私有方法,靜態(tài)方法與類方法。(一)實例方法公有方法,私有方法一般是指屬于對象地實例方法,可以統(tǒng)稱為實例方法,這樣地話在一個類內(nèi)可以出現(xiàn)實例方法,類方法與靜態(tài)方法三種。其私有方法地名字以兩個下劃線(__)開始。每個對象都有自己地公有方法與私有方法,在這兩類都可以訪問屬于類與對象地成員;公有方法通過對象名直接調(diào)用,私有方法不能通過對象名直接調(diào)用,只能在實例方法通過self調(diào)用或在外部通過Python支持地特殊方式來調(diào)用。六.三.三方法類地所有實例方法都需要至少有一個名為self地參數(shù),并且需要是方法地第一個形參(如果有多個形參地話),self參數(shù)代表對象本身。在類地實例方法訪問實例屬時需要以self為前綴,但在外部通過對象名調(diào)用對象方法時并不需要傳遞這個參數(shù),如果在外部通過類名調(diào)用屬于對象地公有方法,需要顯式為該方法地self參數(shù)傳遞一個對象名,用來明確指定訪問那個對象地數(shù)據(jù)成員。例六-五:程序代碼:#例六-五面向?qū)ο笾畬嵗椒╟lassTest(object):"""docstringforTest"""def__init__(self,arg=None):super(Test,self).__init__()六.三.三方法self.arg=argdefsay_hello(self):print("公有方法say_hello():",'hellowrold')#類內(nèi)調(diào)用私用方法self.__say_hello()def__say_hello(self):print("私有方法__say_hello():",'hellowrold')defmain():#一.首先實例化test類test=Test()#二.再調(diào)用實例方法(公有方法),公有方法調(diào)用了私有方法test.say_hello()六.三.三方法#以_Test__sayHello()方式調(diào)用私有方法test._Test__say_hello()if__name__=='__main__':main()運行結(jié)果:公有方法say_hello():hellowrold私有方法__say_hello():hellowrold私有方法__say_hello():helloworld(二)類方法類方法以cls作為第一個參數(shù),cls表示類本身,定義時使用@classmethod裝飾器,表明該方法可以直接用類名來調(diào)用,當(dāng)然也可以通過實例訪問。在類方法內(nèi)通過cls可以訪問類地數(shù)據(jù)成員與類方法,也可以訪問靜態(tài)方法。六.三.三方法例六-六:程序代碼:#例六-六面向?qū)ο笾惙椒╟lassTest(object):"""docstringforTest"""hello_world="HelloWorld!"def__init__(self,arg=None):super(Test,self).__init__()self.arg=argdefsay_hello(self):print("hellowrold")@statiethod六.三.三方法defsay_bad():print("saybad")@classmethoddefsay_good(cls):print("saygood")print(cls.hello_world)#cls.say_hello()cls.say_bad()defmain():test=Test()test.say_hello()#直接類名.方法名()來調(diào)用Test.say_bad()六.三.三方法#直接類名.方法名()來調(diào)用Test.say_good()#對象名.方法名()來調(diào)用test.say_bad()#對象名.方法名()來調(diào)用test.say_good()if__name__=='__main__':main()運行結(jié)果:hellowroldsaybadsaygoodHelloWorld!六.三.三方法saybadsaybadsaygoodHelloWorld!saybad注意:當(dāng)把類方法say_good(cls)地#cls.say_hello()代碼去掉注釋,也就是在類方法內(nèi)視圖訪問實例方法,此時運行程序會出錯,錯誤提示大致如下"TypeError:say_hello()missing一requiredpositionalargument:'self'",錯誤提示已經(jīng)明確了say_hello()是實例方法。(三)靜態(tài)方法靜態(tài)方法與類方法不同,靜態(tài)方法沒有參數(shù)限制,既不需要實例參數(shù),也不需要類參數(shù),定義地時候使用@statiethod裝飾器,同@classmethod裝飾六.三.三方法器一樣,表明該方法可以直接用類名來調(diào)用,也可以通過實例訪問。在靜態(tài)方法內(nèi)可以用類名方法類地成員變量與成員方法,也可以訪問靜態(tài)方法,但不可以直接訪問實例方法。例六-七:程序代碼:#例六-七面向?qū)ο笾o態(tài)方法classTest(object):"""docstringforTest"""hello_world="HelloWorld!"def__init__(self,arg=None):super(Test,self).__init__()self.arg=arg六.三.三方法defsay_hello(self):print("hellowrold")@statiethoddefsay_bad():print("saybad")Test.say_nothing()Test.say_good()print(Test.hello_world)@statiethoddefsay_nothing():print("saynothing")@classmethod六.三.三方法defsay_good(cls):print("saygood")defmain():test=Test()#調(diào)用靜態(tài)方法:類名.方法名()Test.say_bad()#調(diào)用靜態(tài)方法:實例.方法名()test.say_bad()if__name__=='__main__':main()六.三.三方法運行結(jié)果:saybadsaynothingsaygoodHelloWorld!saybadsaynothingsaygoodHelloWorld!六.四屬公開地數(shù)據(jù)成員可以在外部隨意訪問與修改,很難控制用戶修改時新數(shù)據(jù)地合法。解決這一問題地常用方法是定義私有數(shù)據(jù)成員,然后設(shè)計公開地成員方法來提供對私有數(shù)據(jù)成員地讀取與修改操作,修改私有數(shù)據(jù)成員時可以對值行合法檢查,提高了程序地健壯,保證了數(shù)據(jù)地完整。屬結(jié)合了公開數(shù)據(jù)成員與成員方法地優(yōu)點,既可以像成員方法那樣對值行必要地檢查,又可以像數(shù)據(jù)成員一樣靈活地訪問。屬又可以分為類數(shù)據(jù)屬與實例數(shù)據(jù)屬。類數(shù)據(jù)屬通常都用來保存與類有關(guān)聯(lián)地值,不依賴于任何類實例。實例數(shù)據(jù)屬是與某個類地實例有關(guān)聯(lián)地數(shù)據(jù)值,這些值獨立于其它實例或類。當(dāng)一個實例被釋放后,它地屬同時也被清除。在大多是情況下,實例數(shù)據(jù)屬要比類數(shù)據(jù)屬用得更多一些。對于類數(shù)據(jù)屬與實例數(shù)據(jù)屬,使用方法如下。(一)類數(shù)據(jù)屬屬于類本身,可以通過類名行訪問與修改。(二)類數(shù)據(jù)屬于也可以被類地所有實例訪問與修改。六.四屬(三)在類定義之后,可以通過類名動態(tài)添加類數(shù)據(jù)屬,新增地類數(shù)據(jù)屬也被類與所有實例公有。(四)實例數(shù)據(jù)屬只能通過實例訪問。(五)在實例生成后,還可以通過類名動態(tài)添加類數(shù)據(jù)屬,但是這些實例數(shù)據(jù)屬只屬于該實例。例六-八:程序代碼:#例六-八面向?qū)ο笾畬伲▽嵗龑倥c類屬)classAnimal(object):#類屬:動物數(shù)量count=零def__init__(self,name,age):Animal.count=Animal.count+一

六.四屬#實例屬:動物名稱=name#實例屬:動物年齡self.age=ageif__name__=='__main__':dog=Animal('blackdog',三)print("動物數(shù)量:",Animal.count)print("Name:",)print("Age:",dog.age)dog.color='Black'print("Color:",dog.color)#實例屬:是否有baby(動態(tài)添加)六.四屬dog.hasChildren=Trueprint("hasChildren:",dog.hasChildren)cat=Animal('whitecat',四)print("動物數(shù)量:",Animal.count)#此行代碼會出錯#print("hasChildren:",cat.hasChildren)defanimal_type(self,type):self.type=self.typeimporttypes#動態(tài)為對象增加成員方法Animal.animal_type=types.MethodType(animal_type,Animal)六.四屬blackCat=Animal('blackcat',四)blackCat.animal_type="波斯貓"print("動物數(shù)量:",Animal.count)print("動物類型:",blackCat.animal_type)whiteCat=Animal('whitecat',四)print("動物數(shù)量:",Animal.count)print("動物類型:",whiteCat.animal_type)運行結(jié)果:動物數(shù)量:一Name:blackdogAge:三Color:Black六.四屬hasChildren:True動物數(shù)量:二動物數(shù)量:三動物類型:波斯貓動物數(shù)量:四動物類型:<boundmethodanimal_typeof<class'__main__.Animal'>>上例直接在__init__定義實例公有屬,從封裝來說,它是不好地寫法。為了屬定義規(guī)范與訪問安全,可以對屬加以訪問控制,可以使用@propery關(guān)鍵字行屬定義,這樣就起到屬定義地規(guī)范與訪問限定作用。用此關(guān)鍵字其獲取,設(shè)置函數(shù)時,須與屬名一致。@property可以把一個實例方法變成其同名屬,以支持.號訪問,它亦可標記設(shè)置限制,加以規(guī)范,代碼如下所示。六.四屬例六-九:程序代碼:#例六-九面向?qū)ο笾畬伲ˊproperty)classAnimal(object):def__init__(self,name,age):self._name=nameself._age=ageself._color='Black'@propertydefname(self):returnself._name@name.setter六.三屬defname(self,value):ifisinstance(value,str):self._name=valueelse:self._name='Noname'@propertydefage(self):returnself._age@age.setterdefage(self,value):ifvalue>零andvalue<一零零:self._age=value六.四屬else:self._age=零#print("invalidagevalue.")@propertydefcolor(self):returnself._color@color.setterdefcolor(self,value):self._color=value;dog=Animal('blackdog',三)print("Name:",)print("Age:",dog.age)六.四屬='whitedog'dog.age=五print("Name:",)print("Age:",dog.age)運行結(jié)果:Name:blackdogAge:三Name:whitedogAge:五為了屬定義規(guī)范與訪問安全,除了使用關(guān)鍵字@property對屬加行定義與訪問控制外,還可以使用property()函數(shù),它是以一個函數(shù)地方式定義屬,使用property()定義屬地語法如下。六.四屬屬名=property(fget=None,fset=None,fdel=None,doc=None)例六-一零:程序代碼:#例六-一零面向?qū)ο笾畬伲╬roperty())classAnimal(object):'使用property()定義屬'def__init__(self,name,age):self._name=nameself._age=ageself._color='Black'defget_name(self):returnself._namedefset_name(self,value):六.四屬ifisinstance(value,str):self._name=valueelse:self._name='Noname'defdel_name(self):delself._namename=property(fget=get_name,fset=set_name,fdel=del_name,doc="nameofananimal")defget_age(self):returnself._agedefset_age(self,value):ifvalue>零andvalue<一零零:六.四屬self._age=valueelse:self._age=零#print("invalidagevalue.")age=property(fget=get_age,fset=set_age,fdel=None,doc="ageofananimal")dog=Animal('blackdog',三)print("Name:",)print(A.__doc__)print("Age:",dog.age)='whitedog'dog.age=三六.四屬print("Name:",)print(A.__doc__)print("Age:",dog.age)運行結(jié)果:Name:blackdognameofananimalAge:三Name:whitedognameofananimalAge:三從以上使用property()定義屬地例子看出,可以更加全面地對屬行保護,可以設(shè)置屬地只讀屬(fset=None),可讀寫屬(為fget與fset參六.四屬數(shù)賦值),也可以對屬行刪除操作。在上例最后增加刪除name屬代碼并在之后訪問該屬,程序會報錯。delprint('Name:',)錯誤提示為"AttributeError:'Animal'objecthasnoattribute'_name'"。對于所有地類,還有著一組特殊地屬,如表六-一所示,通過這些屬可以查看類地一些信息。六.四屬序號類屬意義一__name__類地名字(字符串)二__doc__類地文檔字符串三__bases__類地所有父類組成地元素四__dict__類地屬組成地字典五__module__類所屬地模塊六__class__類對象地類型表六-一類特殊地屬六.五.一類地簡單繼承六.五.二類地多重繼承六.五繼承六.五.一類地簡單繼承面向?qū)ο蟮鼐幊處淼刂饕锰幹皇谴a地重用,實現(xiàn)這種重用地方法之一是通過繼承機制。繼承用于指定一個類將從其父類獲取其大部分或全部功能。它是面向?qū)ο缶幊痰匾粋€特征。這是一個非常強大地功能,方便用戶對現(xiàn)有類行幾個或多個修改來創(chuàng)建一個新地類。新類稱為子類或派生類,從其繼承屬地主類稱為基類或父類。子類或派生類繼承父類地功能,向其添加新功能。它有助于代碼地可重用。繼承地語法如下所示。class派生類(基類):派生類類內(nèi)語句假如我需要定義幾個類,而類與類之間有一些公地屬與方法,這時就可以把相同地屬與方法作為基類地成員,而特殊地方法及屬則在本類定義六.五.一類地簡單繼承,這樣只需要繼承基類這個動作,就可以訪問到基類地屬與方法了,它提高了代碼地可擴展。在python繼承地一些特點:(一)在繼承基類地構(gòu)造(__init__()方法)不會被自動調(diào)用,它需要在其派生類地構(gòu)造專門調(diào)用。(二)在調(diào)用基類地方法時,需要加上基類地類名前綴,且需要帶上self參數(shù)變量,也可以使用內(nèi)置函數(shù)super()代替基類名。區(qū)別于在類調(diào)用普通函數(shù)時并不需要帶上self參數(shù)。(三)Python總是首先查找對應(yīng)類型地方法,如果它不能在派生類找到對應(yīng)地方法,它才開始到基類逐個查找。例六-一一:程序代碼:六.五.一類地簡單繼承#例六-一一面向?qū)ο笾^承classPerson(object):def__init__(self,name,gender):=nameself.gender=genderprint("Person類__ini__()。","姓名:",)classStudent(Person):def__init__(self,name,gender,score):super(Student,self).__init__(name,gender)self.score=scoreprint("Student類__ini__()。","姓名:",)if__name__=="__main__":六.五.一類地簡單繼承person=Person("PersonName","男")student=Student("StudentName","男",一零零)運行結(jié)果:Person類__ini__()。姓名:PersonNamePerson類__ini__()。姓名:StudentNameStudent類__ini__()。姓名:StudentName任何事情都有利有弊:繼承地一個弱點就是,可能特殊地本類又有其它特殊地地方,又會定義一個類,其下也可能再定義類,這樣就會造成繼承地那條線越來越長,使用繼承地話,任何一點小地變化也需要重新定義一個類,很容易引起類地爆炸式增長,產(chǎn)生一大堆有著細微不同地子類.所以有個"多用組合少用繼承"地原則。六.五.二類地多重繼承Python子類可以繼承一個基類,也可以繼承多個基類,這就是多重繼承。類地多重繼承地語法如下。class派生類(基類一,基類二,...):派生類類內(nèi)語句Python地類如果繼承了多個類,在Python二.二版本其尋找方法地方式有兩種,分別是深度優(yōu)先與廣度優(yōu)先。至于是深度優(yōu)先還是廣度優(yōu)先地繼承,需要先了解經(jīng)典類與新式類,如果當(dāng)前類或者父類繼承了Object類,那么該類就是新式類,否則便是經(jīng)典類。(一)深度優(yōu)先:當(dāng)類是經(jīng)典類時,多重繼承情況下,會按照深度優(yōu)先方式查找。(二)廣度優(yōu)先:當(dāng)類是新式類時,多重繼承情況下,會按照廣度優(yōu)先地方式查找。六.五.二類地多重繼承Python地類如果繼承了多個類,在Python三.x版本其尋找方法遵循MRO原則,可以通過類地__mro__屬輸出對應(yīng)地方法尋找順序。注意:__mro__屬顯示指定類地所有繼承脈絡(luò)與繼承順序,假如這個指定地類不具有某些方法與屬,但與其有血統(tǒng)關(guān)系地類具有這些屬與方法,則在訪問這個類本身不具有地這些方法與屬時,會按照__mro__顯示出來地順序一層一層向后查找,直到找到為止。例六-一二:程序代碼:#例六-一二面向?qū)ο笾嘀乩^承(經(jīng)典類)classP一():deffoo(self):print("p一-foo")六.五.二類地多重繼承classP二():deffoo(self):print("p二-foo")defbar(self):print("p二-bar")classC一(P一,P二):passclassC二(P一,P二):defbar(self):print("C二-bar")classD(C一,C二):pass六.五.二類地多重繼承if__name__=='__main__':#只有新式類有__mro__屬,列出查找順序print(D.__mro__)d=D()d.foo()d.bar()運行結(jié)果:(<class'__main__.D'>,<class'__main__.C一'>,<class'__main__.C二'>,<class'__main__.P一'>,<class'__main__.P二'>,<class'object'>)p一-fooC二-bar六.五.二類地多重繼承注意:在例六-一二定義類時,把沒有基類地類指定object為基類,這些類就成為了新式類,運行結(jié)果如下。(<class'__main__.D'>,<class'__main__.C一'>,<class'__main__.C二'>,<class'__main__.P一'>,<class'__main__.P二'>,<class'object'>)p一-fooC二-bar通過對比經(jīng)典類與新式類關(guān)于方法地查找順序可知,在Python三.七.零版本已經(jīng)采用同樣地查找順序,就是類地__mro__屬列出地查找順序。六.六多態(tài)多態(tài)是指基類地同一方法在不同派生類對象具有不同地變現(xiàn)與行為。不同地派生類對象調(diào)用相同地基類方法,產(chǎn)生了不同地執(zhí)行結(jié)果,這樣可以增加代碼地外部調(diào)用靈活度,多態(tài)以繼承與重寫父類方法為前提條件,多態(tài)只是調(diào)用方法地技巧,不會影響到類地內(nèi)部設(shè)計。首先看一下沒有使用多態(tài)地示例。例六-一三:程序代碼:#例六-一三面向?qū)ο笾鄳B(tài)(沒有使用多態(tài))classArmyDog(object):defbite_enemy(self):print("追擊敵。")classDrugDog(object):六.六多態(tài)deftrack_drug(self):print("追查毒品。")classPerson(object):defwork_with_army(self,dog):dog.bite_enemy()defwork_with_drug(self,dog):dog.track_drug()person=Person()person.work_with_army(ArmyD

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論