《Python程序設(shè)計(jì)入門與實(shí)踐(第2版)》課件 第8章 面向?qū)ο蟪绦蛟O(shè)計(jì)_第1頁
《Python程序設(shè)計(jì)入門與實(shí)踐(第2版)》課件 第8章 面向?qū)ο蟪绦蛟O(shè)計(jì)_第2頁
《Python程序設(shè)計(jì)入門與實(shí)踐(第2版)》課件 第8章 面向?qū)ο蟪绦蛟O(shè)計(jì)_第3頁
《Python程序設(shè)計(jì)入門與實(shí)踐(第2版)》課件 第8章 面向?qū)ο蟪绦蛟O(shè)計(jì)_第4頁
《Python程序設(shè)計(jì)入門與實(shí)踐(第2版)》課件 第8章 面向?qū)ο蟪绦蛟O(shè)計(jì)_第5頁
已閱讀5頁,還剩37頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第8章面向?qū)ο蟪绦蛟O(shè)計(jì)1本章學(xué)習(xí)目標(biāo)掌握定義類的語法掌握創(chuàng)建對象的語法理解數(shù)據(jù)成員與成員方法的區(qū)別理解私有成員與公有成員的區(qū)別理解屬性的工作原理了解繼承的基本概念了解特殊方法的概念與工作原理2第8章面向?qū)ο蟪绦蛟O(shè)計(jì)在面向?qū)ο蟪绦蛟O(shè)計(jì)(ObjectOrientedProgramming)中,把數(shù)據(jù)以及對數(shù)據(jù)的操作封裝在一起,組成一個整體(對象),不同對象之間通過消息機(jī)制來通信或者同步。對于相同類型的對象進(jìn)行分類、抽象后,得出共同的特征而形成了類。創(chuàng)建類時用變量形式表示對象特征的成員稱為數(shù)據(jù)成員,用函數(shù)形式表示對象行為的成員稱為成員方法,數(shù)據(jù)成員和成員方法統(tǒng)稱為類的成員。以設(shè)計(jì)好的類為基類,可以繼承得到派生類,大幅度縮短開發(fā)周期,并且可以實(shí)現(xiàn)設(shè)計(jì)復(fù)用。在派生類中還可以對基類繼承而來的某些行為進(jìn)行重新實(shí)現(xiàn),從而使得基類的某個同名方法在不同派生類中的行為有可能會不同,體現(xiàn)出一定的多態(tài)性。封裝、繼承、多態(tài)是面向?qū)ο蟪绦蛟O(shè)計(jì)的三個要素。38.1類的定義與使用Python使用class關(guān)鍵字來定義類,class關(guān)鍵字之后是一個空格,接下來是類的名字,如果派生自其它基類的話則需要把所有基類放到一對圓括號中并使用逗號分隔,然后是一個冒號,最后換行并定義類的內(nèi)部實(shí)現(xiàn)。類名的首字母一般要大寫,當(dāng)然也可以按照自己的習(xí)慣定義類名,但是一般推薦參考慣例來命名,并在整個系統(tǒng)的設(shè)計(jì)和實(shí)現(xiàn)中保持風(fēng)格一致。classCar(object):#定義一個類,派生自object類defshowInfor(self):#定義成員方法print('Thisisacar')48.1類的定義與使用定義了類之后,就可以用來實(shí)例化對象,并通過“對象名.成員”的方式來訪問其中的數(shù)據(jù)成員或成員方法。car=Car()#實(shí)例化對象car.showInfor()#調(diào)用對象的成員方法58.2數(shù)據(jù)成員與成員方法創(chuàng)建類時用變量形式表示對象特征的成員稱為數(shù)據(jù)成員(attribute),用函數(shù)形式表示對象行為的成員稱為成員方法(method),數(shù)據(jù)成員和成員方法統(tǒng)稱為類的成員。68.2.1私有成員與公有成員私有成員在類的外部不能直接訪問,一般是在類的內(nèi)部進(jìn)行訪問和操作,或者在類的外部通過調(diào)用對象的公有成員方法來訪問。公有成員是可以公開使用的,既可以在類的內(nèi)部進(jìn)行訪問,也可以在外部程序中使用。從形式上看,在定義類的成員時,如果成員名以兩個下劃線開頭但是不以兩個下劃線結(jié)束則表示是私有成員。Python并沒有對私有成員提供嚴(yán)格的訪問保護(hù)機(jī)制,通過一種特殊方式“對象名._類名__xxx”也可以在外部程序中訪問私有成員,但這會破壞類的封裝性,不建議這樣做。78.2.1私有成員與公有成員>>>classA: def__init__(self,value1=0,value2=0): self._value1=value1 self.__value2=value2 defsetValue(self,value1,value2): self._value1=value1 self.__value2=value2 defshow(self): print(self._value1) print(self.__value2)>>>a=A()>>>a._value10>>>a._A__value2#在外部訪問對象的私有數(shù)據(jù)成員088.2.1私有成員與公有成員在Python中,以下劃線開頭的變量名和方法名有特殊的含義,尤其是在類的定義中。_xxx:受保護(hù)成員;__xxx__:系統(tǒng)定義的特殊成員;__xxx:私有成員,只有類對象自己能訪問,子類對象不能直接訪問到這個成員,但在類外部可以通過“對象名._類名__xxx”這樣的特殊方式來訪問。注意:Python中不存在嚴(yán)格意義上的私有成員。98.2.2數(shù)據(jù)成員數(shù)據(jù)成員可以大致分為兩類:屬于對象的數(shù)據(jù)成員和屬于類的數(shù)據(jù)成員。屬于對象的數(shù)據(jù)成員一般在構(gòu)造方法__init__()中定義,當(dāng)然也可以在其他成員方法中定義(不建議這樣做),在定義時和在實(shí)例方法中訪問數(shù)據(jù)成員時以self作為前綴,同一個類的不同對象(實(shí)例)的數(shù)據(jù)成員之間互不影響;屬于類的數(shù)據(jù)成員是該類所有對象共享的,不屬于任何一個對象,在定義類時這類數(shù)據(jù)成員一般不在任何一個成員方法的定義中。108.2.2數(shù)據(jù)成員利用類數(shù)據(jù)成員的共享性,可以實(shí)時獲得該類的對象數(shù)量,并且可以控制該類可以創(chuàng)建的對象最大數(shù)量。>>>classSingleInstance:num=0def__init__(self):ifSingleInstance.num>0:raiseException('只能創(chuàng)建一個對象')SingleInstance.num+=1

>>>t1=SingleInstance()>>>t2=SingleInstance()Traceback(mostrecentcalllast):File"<pyshell#11>",line1,in<module>t2=SingleInstance()File"<pyshell#9>",line5,in__init__raiseException('只能創(chuàng)建一個對象')Exception:只能創(chuàng)建一個對象118.2.3成員方法Python類的成員方法大致可以分為公有方法、私有方法、靜態(tài)方法、類方法這幾種類型。私有方法的名字以兩個下畫線開始但不以兩個下畫線結(jié)束。每個對象都可以有自己的公有方法和私有方法,在這兩類方法中都可以訪問屬于類和對象的成員。公有方法通過對象名直接調(diào)用,私有方法不能通過對象名直接調(diào)用,只能在其他實(shí)例方法中通過前綴self進(jìn)行調(diào)用或在外部通過特殊的形式來調(diào)用。128.2.3成員方法所有實(shí)例方法都必須至少有一個名為self的參數(shù),并且必須是方法的第一個形參(如果有多個形參的話),self參數(shù)代表當(dāng)前對象。在實(shí)例方法中訪問實(shí)例成員時需要以self為前綴,但在外部通過對象名調(diào)用對象方法時并不需要傳遞這個參數(shù)。如果在外部通過類名調(diào)用屬于對象的公有方法,需要顯式為該方法的self參數(shù)傳遞一個對象名,用來明確指定訪問哪個對象的成員。138.2.3成員方法靜態(tài)方法和類方法都可以通過類名和對象名調(diào)用,但不能訪問屬于對象的成員,只能訪問屬于類的成員。靜態(tài)方法和類方法不屬于任何實(shí)例,不會綁定到任何實(shí)例,當(dāng)然也不依賴于任何實(shí)例的狀態(tài),與實(shí)例方法相比能夠減少很多開銷。類方法一般以cls作為類方法的第一個參數(shù)表示該類自身,在調(diào)用類方法時不需要為該參數(shù)傳遞值,靜態(tài)方法則可以不接收任何參數(shù)。148.2.3成員方法>>>classRoot:__total=0def__init__(self,v):#構(gòu)造方法self.__value=vRoot.__total+=1defshow(self):#普通實(shí)例方法print('self.__value:',self.__value)print('Root.__total:',Root.__total)@classmethod#修飾器,聲明類方法defclassShowTotal(cls):#類方法print(cls.__total)@staticmethod#修飾器,聲明靜態(tài)方法defstaticShowTotal():#靜態(tài)方法print(Root.__total)158.2.3成員方法>>>r=Root(3)>>>r.classShowTotal()#通過對象調(diào)用類方法1>>>r.staticShowTotal()#通過對象調(diào)用靜態(tài)方法1>>>r.show()self.__value:3Root.__total:1>>>rr=Root(5)>>>Root.classShowTotal()#通過類名調(diào)用類方法2>>>Root.staticShowTotal()#通過類名調(diào)用靜態(tài)方法2168.2.3成員方法>>>Root.show()#試圖通過類名直接調(diào)用實(shí)例方法,失敗TypeError:unboundmethodshow()mustbecalledwithRootinstanceasfirstargument(gotnothinginstead)>>>Root.show(r)#但是可以通過這種方法調(diào)用方法并訪問實(shí)例成員self.__value:3Root.__total:2>>>Root.show(rr)#通過類名調(diào)用實(shí)例方法時為self參數(shù)顯式傳遞對象名self.__value:5Root.__total:2178.2.4屬性只讀屬性>>>classTest: def__init__(self,value): self.__value=value @property defvalue(self):#只讀,無法修改和刪除

returnself.__value188.2.4屬性>>>t=Test(3)>>>t.value3>>>t.value=5#只讀屬性不允許修改值A(chǔ)ttributeError:can'tsetattribute>>>t.v=5#動態(tài)增加新成員>>>t.v5>>>delt.v#動態(tài)刪除成員>>>delt.value#試圖刪除對象屬性,失敗AttributeError:can'tdeleteattribute>>>t.value3198.2.4屬性可讀、可寫屬性>>>classTest:def__init__(self,value):self.__value=value def__get(self):returnself.__valuedef__set(self,v):self.__value=vvalue=property(__get,__set)defshow(self):print(self.__value)208.2.4屬性>>>t=Test(3)>>>t.value#允許讀取屬性值3>>>t.value=5#允許修改屬性值>>>t.value5>>>t.show()#屬性對應(yīng)的私有變量也得到了相應(yīng)的修改5>>>delt.value#試圖刪除屬性,失敗AttributeError:can'tdeleteattribute218.2.4屬性可讀、可修改、可刪除的屬性。>>>classTest:def__init__(self,value):self.__value=valuedef__get(self):returnself.__valuedef__set(self,v):self.__value=vdef__del(self):delself.__valuevalue=property(__get,__set,__del)defshow(self):print(self.__value)228.2.4屬性>>>t=Test(3)>>>t.show()3>>>t.value3>>>t.value=5>>>t.show()5>>>t.value5238.2.4屬性>>>delt.value#刪除屬性>>>t.value#屬性對應(yīng)的私有數(shù)據(jù)成員已刪除AttributeError:'Test'objecthasnoattribute'_Test__value'>>>t.show()AttributeError:'Test'objecthasnoattribute'_Test__value'>>>t.value=1#為對象動態(tài)增加屬性和對應(yīng)的私有數(shù)據(jù)成員>>>t.show()1>>>t.value1248.2.4屬性下面的代碼定義了一個矩形類,支持設(shè)置矩形的寬度和高度以及獲取矩形的寬度、高度和面積,除了本節(jié)已經(jīng)介紹過的屬性定義方式,還演示了另一種定義屬性的方式。code\RectangleClass.py258.2.4屬性classRectangle:def__init__(self,w,h):

#構(gòu)造方法,名字是固定的self.width=w

#調(diào)用屬性的setter方法進(jìn)行賦值self.height=h@propertydefwidth(self):#讀取屬性的值時,自動調(diào)用這個方法returnself.__width@width.setterdefwidth(self,w):#修改屬性的值時,自動調(diào)用這個方法assertisinstance(w,(int,float))andw>0,'矩形寬度必須大于0'self.__width=w@width.deleterdefwidth(self):#刪除屬性時,自動調(diào)用這個方法delself.__width268.2.4屬性def__get_height(self):returnself.__heightdef__set_height(self,h):assertisinstance(h,(int,float))andh>0,'矩形寬度必須大于0'self.__height=hdef__del_height(self):delself.__height#使用property()函數(shù)定義屬性#分別設(shè)置讀取、修改、刪除時調(diào)用的方法height=property(__get_height,__set_height,__del_height)@propertydefarea(self):returnself.__width

*

self.__height278.2.4屬性r1=Rectangle(3,5)print(r1.area)r2=Rectangle(4,6)r2.width=5r2.height=7print(r2.area)288.3繼承繼承是用來實(shí)現(xiàn)代碼復(fù)用和設(shè)計(jì)復(fù)用的機(jī)制,是面向?qū)ο蟪绦蛟O(shè)計(jì)的重要特性之一。設(shè)計(jì)一個新類時,如果可以繼承一個已有的設(shè)計(jì)良好的類然后進(jìn)行二次開發(fā),無疑會大幅度減少開發(fā)工作量。在繼承關(guān)系中,已有的、設(shè)計(jì)好的類稱為父類或基類,新設(shè)計(jì)的類稱為子類或派生類。派生類可以繼承父類的公有成員,但是不能繼承其私有成員。如果需要在派生類中調(diào)用基類的方法,可以使用內(nèi)置函數(shù)super()或者通過“基類名.方法名()”的方式來實(shí)現(xiàn)這一目的。Python支持多繼承,如果父類中有相同的方法名,而在子類中使用時沒有指定父類名,則Python解釋器將從左向右按順序進(jìn)行搜索。298.3繼承例8.1

設(shè)計(jì)Person類,根據(jù)Person類派生Teacher類,然后分別創(chuàng)建兩個類的對象。classPerson(object):def__init__(self,name='',age=20,sex='man'):#通過調(diào)用方法進(jìn)行初始化,這樣可以對參數(shù)進(jìn)行更好地控制self.setName(name)self.setAge(age)self.setSex(sex)defsetName(self,name):ifnotisinstance(name,str):raiseException('namemustbestring.')self.__name=namedefsetAge(self,age):iftype(age)!=int:raiseException('agemustbeinteger.')self.__age=agedefsetSex(self,sex):ifsexnotin('man','woman'):raiseException('sexmustbe"man"or"woman"')self.__sex=sexdefshow(self):print(self.__name,self.__age,self.__sex,sep='\n')308.3繼承#派生類classTeacher(Person):def__init__(self,name='',age=30,sex='man',department='Computer'):#調(diào)用基類構(gòu)造方法初始化基類的私有數(shù)據(jù)成員super(Teacher,self).__init__(name,age,sex)#也可以這樣初始化基類的私有數(shù)據(jù)成員#Person.__init__(self,name,age,sex)#調(diào)用自己的方法初始化派生類的數(shù)據(jù)成員self.setDepartment(department)#在派生類中新增加的方法defsetDepartment(self,department):iftype(department)!=str:raiseException('departmentmustbeastring.')self.__department=department#覆蓋了從父類中繼承來的方法defshow(self):#先調(diào)用父類的同名方法,顯示從父類中繼承來的數(shù)據(jù)成員super(Teacher,self).show()#再顯示派生類中的私有數(shù)據(jù)成員print(self.__department)318.3繼承if__name__=='__main__':#創(chuàng)建基類對象zhangsan=Person('ZhangSan',19,'man')zhangsan.show()print('='*30)#創(chuàng)建派生類對象lisi=Teacher('Lisi',32,'man','Math')lisi.show()#調(diào)用繼承的方法修改年齡lisi.setAge(40)lisi.show()328.4特殊方法Python類有大量的特殊方法,其中比較常見的是構(gòu)造函數(shù)和析構(gòu)方法,除此之外,Python還支持大量的特殊方法,運(yùn)算符重載就是通過重寫特殊方法實(shí)現(xiàn)的。Python中類的構(gòu)造方法是__init__(),一般用來為數(shù)據(jù)成員設(shè)置初值或進(jìn)行其他必要的初始化工作,在創(chuàng)建對象時被自動調(diào)用和執(zhí)行,建議所有的數(shù)據(jù)成員都在構(gòu)造方法中定義和初始化。如果用戶沒有設(shè)計(jì)構(gòu)造方法,Python將提供一個默認(rèn)的構(gòu)造方法用來進(jìn)行必要的初始化工作。Python中類的析構(gòu)方法是__del__(),一般用來釋放對象占用的資源,在Python刪除對象和收回對象空間時被自動調(diào)用和執(zhí)行。如果用戶沒有編寫析構(gòu)方法,Python將提供一個默認(rèn)的析構(gòu)方法進(jìn)行必要的清理工作。338.4特殊方法34方法功能說明__new__()類的靜態(tài)方法,用于確定是否要創(chuàng)建對象__init__()構(gòu)造方法,創(chuàng)建對象時自動調(diào)用__del__()析構(gòu)方法,釋放對象時自動調(diào)用__add__()+__sub__()-__mul__()*__truediv__()/__floordiv__()//__mod__()%__pow__()**__eq__()、__ne__()、__lt__()、__le__()、__gt__()、__ge__()==、!=、<、<=、>、>=__lshift__()、__rshift__()<<、>>__and__()、__or__()、__invert__()、__xor__()&、|、~、^8.4特殊方法35方法功能說明__iadd__()、__isub__()+=、-=,很多其他運(yùn)算符也有與之對應(yīng)的復(fù)合賦值運(yùn)算符__pos__()一元運(yùn)算符+,正號__neg__()一元運(yùn)算符-,負(fù)號__contains__()與成員測試運(yùn)算符in對應(yīng)__radd__()、__rsub__反射加法、反射減法,一般與普通加法和減法具有相同的功能,但操作數(shù)的位置或順序相反,很多其他運(yùn)算符也有與之對應(yīng)的反射運(yùn)算符__abs__()與內(nèi)置函數(shù)abs()對應(yīng)__bool__()與內(nèi)置函數(shù)bool()對應(yīng),要求該方法必須返回True或False__bytes__()與內(nèi)置函數(shù)bytes()對應(yīng)__complex__()與內(nèi)置函數(shù)complex()對應(yīng),要求該方法必須返回復(fù)數(shù)__dir__()與內(nèi)置函數(shù)dir()對應(yīng)__divmod__()與內(nèi)置函數(shù)divmod()對應(yīng)__float__()與內(nèi)置函數(shù)float()對應(yīng),要求該該方法必須返回實(shí)數(shù)__hash__()與內(nèi)置函數(shù)hash()對應(yīng)__int__()與內(nèi)置函數(shù)int()對應(yīng),要求該方法必須返回整數(shù)8.4特殊方法36方法功能說明__len__()與內(nèi)置函數(shù)len()對應(yīng)__next__()與內(nèi)置函數(shù)next()對應(yīng)__reduce__()提供對reduce()函數(shù)的支持__reversed__()與內(nèi)置函數(shù)reversed()對應(yīng)__round__()對內(nèi)置函數(shù)round()對應(yīng)__str__()與內(nèi)置函數(shù)str()對應(yīng),要求該方法必須返回str類型的數(shù)據(jù)__repr__()打印、轉(zhuǎn)換,要求該方法必須返回str類型的數(shù)據(jù)__getitem__()按照索引獲取值__setitem__()按照索引賦值__de

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論