Python面向?qū)ο缶幊蘝第1頁
Python面向?qū)ο缶幊蘝第2頁
Python面向?qū)ο缶幊蘝第3頁
Python面向?qū)ο缶幊蘝第4頁
Python面向?qū)ο缶幊蘝第5頁
已閱讀5頁,還剩65頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、Python面向?qū)ο缶幊蘌ython-面向?qū)ο缶幊堂嫦驅(qū)ο蟮囊恍┗靖拍詈吞卣黝愵悾河脕砻枋鼍哂邢嗤瑢傩院头椒ǖ膶ο蟮募希x該集合中每個對象所共有的屬性和方法,對象是類的實例。類變量類變量:類變量在整個實例化的對象中是公用的,類變量定義在類中且在函數(shù)體之外,類變量通常不作為實例變量使用。數(shù)據(jù)成員數(shù)據(jù)成員:類變量或者實例變量用于處理類及其實例對象的相關(guān)數(shù)據(jù)。方法重寫方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆蓋(override)。實例變量實例變量:定義在方法中的變量,只作用于當前實例的類。繼承繼承:即一個派生類(derived class)繼承基

2、類(base class)的字段和方法,繼承也允許把一個派生類的對象作為一個基類對象對待。實例化實例化:創(chuàng)建一個類的實例,類的具體對象。方法方法:類中定義的函數(shù)。對象對象:對象包括兩類數(shù)據(jù)成員(類變量和實例變量)和方法,通過類定義的數(shù)據(jù)結(jié)構(gòu)實例化。6.1 類的定義與使用 Python中的類是一個抽象的概念,比函數(shù)還要抽象。我們可以把它簡單看做是數(shù)據(jù)以及由存取、操作這些數(shù)據(jù)的方法所組成的一個集合。那為什么還要用類來取代函數(shù)呢?類有如下優(yōu)點: 類對象是多態(tài)的:也就是具有多種形態(tài),這意味著我們可以對不同的類對象使用同樣的操作方法,而不需要額外編寫代碼。 類的封裝:類封裝之后,可以直接調(diào)用類的對象來操

3、作內(nèi)部的一些類方法,不需要讓使用者看到代碼工作的細節(jié)。 類的繼承:類可以從其它類或者基類中繼承它們的方法,直接使用。6.1.1 類的定義 類是對現(xiàn)實世界中一些事物的封裝,所有類的開頭都要包括關(guān)鍵字class,緊接著的是類名和冒號,隨后是定義類的類體代碼。語法格式如下:class ClassName: documentation string . . . . . . object是“所有類之父”。如果你的類沒有繼承任何其他父類,object將作為默認的父類,它位于所有類繼承結(jié)構(gòu)的最上層(繼承的概念在本章稍后介紹),定義一個類可以采用下面的方式?!緦嵗?-1】類的定義。class people:

4、#定義基本屬性 name = age = 0 #定義私有屬性,私有屬性在類外部無法直接進行訪問 _weight = 0 #定義構(gòu)造方法 def _init_(self,n,a,w): = n self.age = a self._weight = w #定義類本身的方法 def speak(self): print(%s is speaking: I am %d years old %(,self.age)#類調(diào)用p = people(tom,10,30)p.speak三 注意:在上面的例子中,name和age是類的公有屬性。_weight使用兩個下劃線開

5、頭,表示聲明該屬性為私有屬性,它不能在類的外部被使用或直接訪問,但可以在類內(nèi)部使用self. _weight調(diào)用。 【實例6-2】接上例。print()print(p._weight) 出錯的原因在于,在類的外部使用了私有屬性。6.1.2 類屬性與方法 1.類的公有屬性public_attrs:符合正常的變量命名規(guī)則,開頭沒有下劃線,類外部可以直接進行訪問。如上例中的name、age等。 2.類的私有屬性_private_attrs:由兩個下劃線開頭,聲明該屬性為私有,不能在類的外部被使用或直接訪問。在類內(nèi)部的方法中使用時的格式為。【實例6-3】類的私有屬性。class Count

6、er: _privateCount = 1 # 私有屬性 publicCount = 1 # 公有屬性 def count(self): self._privateCount += 1 self.publicCount += 1 print (self._privateCount)counter_1 = Counter三counter_1.count三 # 打印數(shù)據(jù)print (counter_1.publicCount) # 打印數(shù)據(jù)print (counter_1._privateCount) # 報錯,實例不能訪問私有屬性出錯的原因在于,在類的外部使用了私有屬性。 3.類的構(gòu)造方法_in

7、it_:叫作構(gòu)造函數(shù)或者構(gòu)造方法,它在生成一個對象時被自動調(diào)用。在上文的例子中p=people(tom,10,30)語句就是調(diào)用_init_方法將參數(shù)傳遞給、和。 4.類的公共方法public _method:在類的內(nèi)部,使用def關(guān)鍵字可以為類定義一個方法,與一般函數(shù)定義不同,類方法必須包含參數(shù)self,且為第一個參數(shù)。self在Python里不是關(guān)鍵字,self代表當前對象的地址,類似于Java語言中的this。 5.類的私有方法_private_method:由兩個下劃線開頭,聲明該方法為私有方法,不能在類的外部調(diào)用。在類的內(nèi)部調(diào)用時格式為?!緦嵗?-4】類的私有方法。class Sit

8、e: def _init_(self, name, url): = name # 公有屬性 self._url = url # 私有屬性 def printme(self): print(name : , ) print(url : , self._url) def _printme_1(self): # 私有方法 print(輸出私有方法) def printme_1(self): # 公共方法 print(輸出公共方法) self._printme_1三wz = Site(百度網(wǎng)址, baidu )wz.printme三 # 打印數(shù)據(jù)wz.printm

9、e_1三 # 打印數(shù)據(jù),調(diào)用私有方法_printme_1 三wz._printme_1三 # 報錯,實例不能訪問私有屬性 出錯的原因在于,實例不能訪問私有方法。 6.單下劃線(_)以單下劃線開始的成員變量叫做保護變量,意思是只有類對象和子類對象自己能訪問到這些變量,簡單的模塊級私有化只需要在屬性名前使用一個單下劃線字符。以單下劃線開頭(_ singlePrivate)的屬性代表不能直接訪問的類屬性,需通過類提供的接口進行訪問,這就防止模塊的屬性用“from mymodule import *”來加載,這是嚴格基于作用域的,所以這同樣適合于函數(shù)。 【實例6-5】下劃線的使用。class Test

10、三: def _init_(self): pass def public(self): print (這是公共方法) def _singlePrivate(self): print (這是單下劃線方法) def _doublePrivate(self): print (這是雙下劃線方法)t = Test三t.public三 # 可以調(diào)用t._singlePrivate三 # 可以調(diào)用t._doublePrivate三 # 出現(xiàn)錯誤 注意:f._ singlePrivate 三可以直接訪問,不過根據(jù)Python的約定,應該將其視作private,而不要在外部使用它們,良好的編程習慣是不要在外部使

11、用它。同時,根據(jù)Python docs的說明,_object和_object的作用域限制在本模塊內(nèi)。 7.類的專有方法下面是Python常用的一些專有方法,如表6-1所示。 表6-1 類的專有方法專有方法專有方法專有方法說明專有方法說明_init_構(gòu)造函數(shù),在生成對象時調(diào)用_del_ 析構(gòu)函數(shù),釋放對象時使用_repr_打印,轉(zhuǎn)換_setitem_按照索引賦值_getitem_按照索引獲取值_len_獲得長度_call_函數(shù)調(diào)用_add_加運算_sub_減運算_mul_乘運算_div_除運算_mod_求余運算_pow_乘方運算【例6-6】_del_和_repr_專有方法的使用。class Te

12、st: def _init_(self,name=None): = name def _del_(self): print (hello world!) def _repr_(self): return Study(Jacky) def say(self): print () Test(Tim) #自動調(diào)用_del_方法s= Test(Tim)s.say三print(s) #自動調(diào)用_repr_方法print (Test(Kitty) #先自動調(diào)用_repr_方法,然后自動調(diào)用_del_方法 【實例6-7】_str_專有方法的使用。class Test:

13、def _init_(self,number): self.a=number0:3 self.b=number3:6 def _str_(self): return “%s %s”%(self.a,self.b)def test三: num=Test(input(“請輸入數(shù)字: n”) print (輸入的數(shù)字是:,num)#執(zhí)行腳本test三6.1.3 關(guān)于Python的作用域和命名空間。 1.作用域與命名空間的解釋 作用域是指Python程序可以直接訪問到的命名空間?!爸苯釉L問”在這里意味著訪問命名空間中的命名時無需加入附加的修飾符。命名空間本質(zhì)上是一個字典,它的鍵就是變量名,它的值就是那

14、些變量的值。Python使用命名空間來記錄變量的軌跡。 在Python程序中的任何一個地方,都存在三個可用的命名空間: (1)每個函數(shù)都有自已的命名空間(稱作局部命名空間),它記錄了函數(shù)的變量,包括函數(shù)的參數(shù)和局部定義的變量。 (2)每個模塊都有自已的命名空間(稱作全局命名空間),它記錄了模塊的變量,包括函數(shù)、類、其它導入的模塊、模塊級的變量和常量。 (3)每個模塊都有可訪問的內(nèi)置命名空間,它存放著內(nèi)置函數(shù)和異常。 2.命名空間的查找順序 (1)局部命名空間特指當前函數(shù)或類的方法。如果函數(shù)中定義一個局部變量x,Python將使用這個變量,然后停止搜索。 (2)全局命名空間特指當前的模塊。如果模

15、塊中定義名為x的變量、函數(shù)或類,Python將使用這個變量,然后停止搜索。 (3)內(nèi)置命名空間對每個模塊都是全局的,作為最后的嘗試,Python將假設(shè)x是內(nèi)置函數(shù)或變量。 (4)如果Python在這些命名空間中都找不到x,它將放棄查找并引發(fā)一個NameError異常,同時傳遞“There is no variable named x”這樣一條信息。 當函數(shù)被調(diào)用時創(chuàng)建一個局部命名空間,我們可以通過globals三和locals三內(nèi)建函數(shù)判斷某一名字屬于哪個名稱空間。 locals三是只讀的,globals三不是。 【實例6-8】locals三函數(shù)示例。def foo(arg, a): x =

16、1 y = abc for i in range(5): j = 2 k = i print (locals三)#調(diào)用函數(shù)的打印結(jié)果foo(2,3) locals三實際上沒有返回局部命名空間,它返回的是一個拷貝。所以對它進行改變對局部命名空間中的變量值并無影響。 【實例6-9】globals三函數(shù)示例。print(當前的全局命名空間:)var=globals三print(var) globals三函數(shù)返回實際的全局命名空間,而不是一個拷貝。所以對globals三函數(shù)所返回的var的任何改動都會直接影響到全局變量。3.嵌套函數(shù)命名空間的查找步驟:(1)先在當前函數(shù)(嵌套的函數(shù)或lambda匿名函

17、數(shù))的命名空間中搜索。(2)然后在父函數(shù)的命名空間中搜索。(3)接著在模塊命名空間中搜索。(4)最后在內(nèi)建函數(shù)的命名空間中搜索。下面舉例說明?!緦嵗?-10】嵌套函數(shù)命名空間示例。address = 地址: def func_country(country): def func_part(part): city= 天津 #覆蓋父函數(shù)的part變量 print(address + country + city + part) city = 北京 #初始化city變量 #調(diào)用內(nèi)部函數(shù) func_part(西青) #初始化part變量#調(diào)用外部函數(shù)func_country(中國 ) #初始化coun

18、try變量 以上實例中,address在全局命名空間中,country在父函數(shù)的命名空間中,city、 part在子函數(shù)的命名空間中。6.2 Python類與對象 類對象 類對象支持兩種操作:屬性引用和實例化。類對象的屬性引用和Python中所有屬性的引用一樣,都使用標準的語法:。類對象創(chuàng)建之后,類命名空間中所有的命名都是有效屬性名。 在Python中,方法定義在類的定義中,但只能被類對象的實例所調(diào)用。調(diào)用一個方法的途徑分三步: 1.定義類和類中的方法。 2.創(chuàng)建一個或若干個實例,即將類實例化。 3.用所創(chuàng)建的實例調(diào)用方法。 【實例6-11】類的定義與實例化。class MyClass: 一個

19、簡單的類實例 i = 12 def f(self): return hello world# 實例化類MyClass = MyClass三# 訪問類的屬性和方法print(MyClass 類的屬性 i 為:, MyClass.i)print(MyClass 類的方法 f 輸出為:, MyClass.f三) 本例中,和MyClass.f三是有效的屬性引用,分別返回一個整數(shù)和一個方法對象。也可以對類屬性賦值,即可以通過給賦值來修改它。如:MyClass.i=56print(修改后MyClass 類的屬性 i 為:, MyClass.i) 類的實例化使用函數(shù)符號,只要將類對象看作是一個返回新的類實例

20、的無參數(shù)函數(shù)即可。例如(假設(shè)沿用前面的類):MyClass = MyClass三該語句創(chuàng)建了一個新的類實例(對象),并將該對象賦給局部變量MyClass。 通過實例化操作(“調(diào)用”一個類對象)來創(chuàng)建一個空的對象時,通常會把這個新建的實例賦給一個變量。賦值在語法上不是必須的,但如果不把這個實例保存到一個變量中,它就沒有用,會被垃圾收集器自動回收,因為沒有任何引用指向這個實例。 很多類都傾向于創(chuàng)建一個有初始化狀態(tài)的對象。因此類可能會定義一個名為 _init_三的特殊方法(構(gòu)造方法),像下面這樣:def _init_(self): self.data = 當類被調(diào)用時,實例化的第一步就是創(chuàng)建實例對象

21、,一旦對象創(chuàng)建,Python就檢查是否已經(jīng)實現(xiàn)_init_三方法。默認情況下,如果沒有定義(或覆蓋)特殊方法_init_三,對實例不會施加任何特別的操作。 任何所需的特定操作,都需要程序員實現(xiàn)_init_三方法,覆蓋它的默認行為。所以在下例中,可以這樣創(chuàng)建一個新的實例:MyClass_1 = MyClass三 _init_三方法可以有參數(shù)。事實上,正是通過_init_三方法,參數(shù)被傳遞到類的實例上。 【實例6-12】使用帶參數(shù)的_init_三方法初始化。class Complex: def _init_(self, realpart, imagpart): self.r = realpart

22、self.i = imagpartx = Complex(2.4, -4.6)print(x.r, x.i) 類的屬性 有兩種有效的屬性名:數(shù)據(jù)屬性和特殊類屬性。 1.數(shù)據(jù)屬性這相當于Smalltalk中的“實例變量”或C+中的“數(shù)據(jù)成員”。和局部變量一樣,數(shù)據(jù)屬性不需要聲明,第一次使用時它們就會生成。 【實例6-13】數(shù)據(jù)屬性說明。class foo(object): f = 100print (foo.f)print (foo.f+1) 2.特殊類屬性對任何類foo,類foo的部分特殊屬性如表6-2所示。 表6-2 特殊類屬性類屬性類屬性類屬性說明類屬性說明foo._name_類foo的名

23、字(字符串)foo._doc_類foo的文檔字符串foo._bases_類foo的所有父類構(gòu)成的元組foo._dict_類foo的屬性foo._module_類foo定義所在的模塊foo._class_實例foo對應的類 【實例6-14】類屬性說明。class MyClass(object): MyClass 類定義 myVer = 3.4 def showMyVer (self): print (MyClass.myVer)print (dir(MyClass)print (MyClass._dict_) 根據(jù)上面定義的類,我們使用dir三和特殊類屬性_dict_來查看一下類的屬性: 從上面

24、可以看到,dir三返回的僅是對象的屬性的一個名字列表,而_dict_返回的是一個字典,它的鍵是屬性名,值是相應的屬性對象的數(shù)據(jù)值。結(jié)果還顯示MyClass類中兩個熟悉的屬性,showMyVer和myVer,以及一些新的屬性。 實例屬性內(nèi)建函數(shù)dir三可以顯示類屬性,同樣還可以打印所有實例屬性。 【實例6-15】實例屬性說明。class foo(object): passfoo_1 = foo三print (dir(foo_1) 實例有兩個特殊屬性,如表6-3所示。 表6-3 特殊實例屬性實例屬性實例屬性實例屬性說明實例屬性說明foo_1._class_實例化foo_1 的類foo_1._dic

25、t_ foo_1 的屬性 現(xiàn)在使用類foo及其實例foo_1來看看這些特殊實例屬性。 【實例6-16】查看實例屬性_dict_和_class_。class foo(object): passfoo_1 = foo三print (foo_1._dict_)print (foo_1._class_) foo_1現(xiàn)在還沒有數(shù)據(jù)屬性,但我們可以添加一些再來檢查_dict_屬性。 【實例6-17】查看類的數(shù)據(jù)屬性。class foo(object): passfoo_1 = foo三foo_1.f = 100foo_1.b = helloprint (foo_1._dict_)print (foo_1.

26、_class_) 注意:_dict_屬性由一個字典組成,包含一個實例的所有屬性。鍵是屬性名,值是屬性相應的數(shù)據(jù)值。字典中僅有實例屬性,沒有類屬性或特殊屬性。 6.2.4 一些說明 同名的數(shù)據(jù)屬性會覆蓋方法屬性,最好以某種命名約定來避免沖突,因為這在大型程序中可能會導致難以發(fā)現(xiàn)的bug??蛇x的約定包括: (1)類名由大寫字母書寫。 (2)方法的首字母大寫。 (3)數(shù)據(jù)屬性名前綴小寫(可能只是一個下劃線)。 (4)方法使用動詞而數(shù)據(jù)屬性使用名詞。 數(shù)據(jù)屬性可以由方法引用,也可以由普通用戶調(diào)用。 程序員應該小心使用數(shù)據(jù)屬性,程序員可能會因為隨意修改數(shù)據(jù)屬性而破壞本來由方法維護的數(shù)據(jù)一致性。需要注意的

27、是,程序員只要注意避免命名沖突,就可以隨意向?qū)嵗刑砑訑?shù)據(jù)屬性而不會影響方法的有效性再次強調(diào),命名約定可以省去很多麻煩。對Python而言,self絕對沒有任何特殊含義。通過使用self參數(shù)的方法屬性,方法可以調(diào)用其它的方法?!緦嵗?-18】self參數(shù)的使用。class Bag: def _init_(self): self.data = def add(self, x): self.data.append(x) print(self.data) def addtwice(self, x): self.add(x) print(self.data)bag_1 = Bag三bag_1.add(

28、5)bag_1.addtwice(6)6.3 繼承 單繼承Python同樣支持類的繼承,如果一種語言不支持繼承,類就沒有什么意義,類還允許派生,用戶可以創(chuàng)建一個子類,它也是類,而且繼承父類所有的特征和屬性。派生類的定義如下所示:class DerivedClassName(BaseClassName):命名BaseClassName(示例中的基類名)必須與派生類定義在一個作用域內(nèi)。基類可以定義在另一個模塊中,這一點非常有用,格式如下:class DerivedClassName(modname.BaseClassName):【實例6-19】單繼承實例。#類定義class people: #定義

29、基本屬性 name = age = 0 #定義私有屬性,私有屬性在類外部無法直接進行訪問 _weight = 0 #定義構(gòu)造方法 def _init_(self,n,a,w): = n self.age = a self._weight = w def speak(self): print(%s says: I am %d years old %(,self.age)#單繼承class student(people): grade = def _init_(self,n,a,w,g): #調(diào)用父類的構(gòu)造函數(shù) people._init_(self,n,a,w

30、) self.grade = g #重寫父類的方法 def speak(self): print(%s says: I am %d years old,I am in Grade %d. %(,self.age,self.grade) s = student(Tom,10,90,3) s.speak三提示: 派生類定義的執(zhí)行過程和基類是一樣的。構(gòu)造派生類對象時,就繼承基類。這在解析屬性引用的時候尤其有用:如果在類中找不到請求調(diào)用的屬性,就搜索基類。如果基類是由別的類派生而來,這個規(guī)則會遞歸地應用上去。6.3.2 多繼承Python同樣有限地支持多繼承形式,多繼承的類定義的一般

31、形式如下:class DerivedClassName(Base1, Base2, Base3):這里唯一需要解釋的語義是解析類屬性的規(guī)則。順序是深度優(yōu)先,從左到右。因此,如果在DerivedClassName(示例中的派生類)中沒有找到某個屬性,就會搜索Base1,然后遞歸地搜索其基類,如果最終沒有找到,就搜索Base2,依此類推。深度優(yōu)先不區(qū)分屬性繼承自基類還是直接定義。【實例6-20】多繼承實例。#類定義class people: #定義基本屬性 name = age = 0 #定義私有屬性,私有屬性在類外部無法直接進行訪問 _weight = 0 #定義構(gòu)造方法 def _init_(

32、self,n,a,w): = n self.age = a self._weight = w def speak(self): print(%s says: I am %d years old %(,self.age)#單繼承示例class student(people): grade = def _init_(self,n,a,w,g): #調(diào)用父類的構(gòu)函 people._init_(self,n,a,w) self.grade = g #覆寫父類的方法 def speak(self): print(“%s says: I am %d years old

33、,I am in Grade %d.” %(,self.age,self.grade)#另一個類,多重繼承之前的準備class speaker三: topic = name = def _init_(self,n,t): = n self.topic = t def speak(self): print(“I am %s,I am a speaker,my topic is %s”%(,self.topic) #多重繼承class sle(speaker,student): a = def _init_(self,n,a,w,g,t):

34、student._init_(self,n,a,w,g) speaker._init_(self,n,t) test_1 = sle(Tom,12,90,3,One World One Dream)test_1.speak三 #方法名同,默認調(diào)用的是在括號中排前的父類的方法,即speaker類里面的方法。 注意:不加限制地使用多繼承會帶來維護上的噩夢,因為Python中只依靠約定來避免命名沖突。多繼承一個很有名的問題是派生繼承的兩個基類都是從同一個基類繼承而來。目前還不清楚這在語義上有什么意義,然而這會造成意料之外的后果。 6.3.3 方法重寫如果父類方法的功能不能滿足需求,可以在子類里面重寫父類的方法。 【實例6-21】方法重寫。class Parent: # 定義父類 def myMethod(self): print (調(diào)用父類方法)class Child(Parent): # 定義子類 def myMethod(self): print (調(diào)用子類方法)Child_1

溫馨提示

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

評論

0/150

提交評論