(第七集——第一章)python面向对象
程序設計分類
面向過程
面向過程好比精心設計好一條流水線,是一種機械式的思維方式。
# 優點: 復雜度的問題流程化,進而簡單化(一個復雜的問題,分成一個個小的步驟去實現,實現小的步驟將會非常簡單) # 缺點: 一套流水線或者流程就是用來解決一個問題,生產汽水的流水線無法生產汽車,即便是能,也得是大改,改一個組件,牽一發而動全身。# 應用場景: 一旦完成很少改變的場景,例子有Linux內核,git,以及Apache HTTP Server等面向對象
對象是特征與技能的結合體,面向對象更加注重對現實世界的模擬,
優點:
程序的擴展性強。對某一個對象單獨修改,會立刻反映到整個體系中,如對游戲中一個人物參數的特征和技能修改都很容易。
缺點:
編程的復雜度遠高于面向過程
無法像面向過程的程序設計流水線式的可以很精準的預測問題的處理流程與結果.
應用場景:需求經常變化的軟件,一般需求的變化都集中在用戶層,互聯網應用,企業內部軟件,游戲等都是面向對象的程序設計大顯身手的好地方.
類與對象
類即類別、種類,是面向對象設計最重要的概念,對象是特征與技能的結合體,類是一系列對象相似的特征與技能的結合體。
類就是將數據與操作數據的方法組合到一起,實現數據與功能是統一.
屬性查找
類的屬性
# 數據屬性:類的數據屬性是所有對象共享的 print(id(s1.school)) # 4377347328 print(id(s2.school)) # 4377347328# id是python的實現機制,并不能真實反映內存地址, 如果有內存地址,還是以內存地址為準 # 函數屬性:類的函數屬性是綁定給對象用的 print(OldboyStudent.learn) # <function OldboyStudent.learn at 0x1021329d8> print(s1.learn) # <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x1021466d8>> print(s2.learn) # <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x102146710>> # 類的函數屬性是綁定給對象使用的,obj.method稱為綁定方法,內存地址都不一樣,類的函數屬性是綁定給對象使用的備注:在obj.name會先從obj自己的名稱空間里找name,找不到則去類中找,類也找不到就找父類…最后都找不到就拋出異常
綁定到對象的方法的特殊之處
#改寫 class OldboyStudent:school='oldboy'def __init__(self,name,age,sex):self.name=nameself.age=ageself.sex=sexdef learn(self):print('%s is learning' %self.name) #新增self.namedef eat(self):print('%s is eating' %self.name)def sleep(self):print('%s is sleeping' %self.name)s1=OldboyStudent('李坦克','男',18) s2=OldboyStudent('王大炮','女',38) s3=OldboyStudent('牛榴彈','男',78) 類中定義的函數(沒有被任何裝飾器裝飾的)是類的函數屬性, 類可以使用,但必須遵循函數的參數規則,有幾個參數需要傳幾個參數: OldboyStudent.learn(s1) #李坦克 is learning OldboyStudent.learn(s2) #王大炮 is learning OldboyStudent.learn(s3) #牛榴彈 is learning 類中定義的函數(沒有被任何裝飾器裝飾的), 其實主要是給對象使用的,而且是綁定到對象的, 雖然所有對象指向的都是相同的功能,但是綁定到不同的對象就是不同的綁定方法強調:綁定到對象的方法的特殊之處在于,綁定給誰就由誰來調用, 誰來調用,就會將‘誰’本身當做第一個參數傳給方法,即自動傳值(方法__init__也是一樣的道理) s1.learn() #等同于OldboyStudent.learn(s1) s2.learn() #等同于OldboyStudent.learn(s2) s3.learn() #等同于OldboyStudent.learn(s3)注意:綁定到對象的方法的這種自動傳值的特征,決定了在類中定義的函數都要默認寫一個參數self,self可以是任意名字,但是約定俗成地寫出self 類即類型:提示:python的class術語與c++有一定區別,與 Modula-3更像。python中一切皆為對象,且python3中類與類型是一個概念,類型就是類.#類型dict就是類dict >>> list <class 'list'>#實例化的到3個對象l1,l2,l3 >>> l1=list() >>> l2=list() >>> l3=list()#三個對象都有綁定方法append,是相同的功能,但內存地址不同 >>> l1.append <built-in method append of list object at 0x10b482b48> >>> l2.append <built-in method append of list object at 0x10b482b88> >>> l3.append <built-in method append of list object at 0x10b482bc8>#操作綁定方法l1.append(3),就是在往l1添加3,絕對不會將3添加到l2或l3 >>> l1.append(3) >>> l1 [3] >>> l2 [] >>> l3 []#調用類list.append(l3,111)等同于l3.append(111) >>> list.append(l3,111) #l3.append(111) >>> l3 [111]
對象之間的交互
class Garen: #定義英雄蓋倫的類,不同的玩家可以用它實例出自己英雄;camp='Demacia' #所有玩家的英雄(蓋倫)的陣營都是Demacia;def __init__(self,nickname,aggressivity=58,life_value=455): #英雄的初始攻擊力58...;self.nickname=nickname #為自己的蓋倫起個別名;self.aggressivity=aggressivity #英雄都有自己的攻擊力;self.life_value=life_value #英雄都有自己的生命值;def attack(self,enemy): #普通攻擊技能,enemy是敵人;enemy.life_value-=self.aggressivity #根據自己的攻擊力,攻擊敵人就減掉敵人的生命值。 class Riven:camp='Noxus' #所有玩家的英雄(銳雯)的陣營都是Noxus;def __init__(self,nickname,aggressivity=54,life_value=414): #英雄的初始攻擊力54;self.nickname=nickname #為自己的銳雯起個別名;self.aggressivity=aggressivity #英雄都有自己的攻擊力;self.life_value=life_value #英雄都有自己的生命值;def attack(self,enemy): #普通攻擊技能,enemy是敵人;enemy.life_value-=self.aggressivity #根據自己的攻擊力,攻擊敵人就減掉敵人的生命值。
繼承與派生
繼承是一種創建新類的方式,新建的類可以繼承一個或多個父類(python支持多繼承),父類又可稱為基類或超類,新建的類稱為派生類或子類。子類會“”遺傳”父類的屬性,從而解決代碼重用問題。
python中類的繼承分為:單繼承和多繼承 class ParentClass1: #定義父類passclass ParentClass2: #定義父類passclass SubClass1(ParentClass1): #單繼承,基類是ParentClass1,派生類是SubClasspassclass SubClass2(ParentClass1,ParentClass2): #python支持多繼承,用逗號分隔開多個繼承的類pass 查看繼承: >>> SubClass1.__bases__ #__base__只查看從左到右繼承的第一個子類,__bases__則是查看所有繼承的父類 (<class '__main__.ParentClass1'>,) >>> SubClass2.__bases__ (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>) 經典類與新式類: 只有在python2中才分新式類和經典類,python3中統一都是新式類 在python2中,沒有顯式的繼承object類的類,以及該類的子類,都是經典類 在python2中,顯式地聲明繼承object的類,以及該類的子類,都是新式類 在python3中,無論是否繼承object,都默認繼承object,即python3中所有類均為新式類 如: >>> ParentClass1.__bases__ (<class 'object'>,) >>> ParentClass2.__bases__ (<class 'object'>,)繼承與抽象(先抽象再繼承)
抽象: 繼承描述的是子類與父類之間的關系,是一種什么是什么的關系。要找出這種關系,必須先抽象再繼承 抽象分成兩個層次:1.將奧巴馬和梅西這倆對象比較像的部分抽取成類; 2.將人,豬,狗這三個類比較像的部分抽取成父類。 (抽象最主要的作用是劃分類別) 繼承: 基于抽象的結果,通過編程語言去實現它,是先經歷抽象這個過程,才能通過繼承的方式去表達出抽象的結構。 抽象只是分析和設計的過程中,一個動作或者說一種技巧,通過抽象可以得到類。繼承與重用性
在開發程序的過程中,如果我們定義了一個類A,然后又新建立另外一個類B,但類B的大部分內容與類A的相同時,可以不用重新寫一個類B,采用類的繼承的概念。 通過繼承的方式新建類B,讓B繼承A,B會‘遺傳’A的所有屬性(數據屬性和函數屬性),實現代碼重用 class Hero:def __init__(self,nickname,aggressivity,life_value):self.nickname=nicknameself.aggressivity=aggressivityself.life_value=life_valuedef move_forward(self): print('%s move forward' %self.nickname)def move_backward(self):print('%s move backward' %self.nickname)def move_left(self):print('%s move forward' %self.nickname)def move_right(self):print('%s move forward' %self.nickname)def attack(self,enemy):enemy.life_value-=self.aggressivityclass Garen(Hero): # 繼承Hero類passclass Riven(Hero): # 繼承Hero類passg1=Garen('草叢倫',100,300) r1=Riven('銳雯雯',57,200)print(g1.life_value) r1.attack(g1) # 調用父類中的方法 print(g1.life_value)''' 運行結果 243 ''' class Foo:def f1(self):print('Foo.f1')def f2(self):print('Foo.f2')self.f1() # 因為self表示子類Bar的對象,所以會調用子類Bar類中的f1函數class Bar(Foo):def f1(self):print('Foo.f1')b=Bar() b.f2() ''' 打印結果: Foo.f2 Foo.f1 '''
派生
當然子類也可以添加自己新的屬性或者在自己這里重新定義這些屬性(不會影響到父類),需要注意的是,一旦重新定義了自己的屬性且與父類重名,那么調用新增的屬性時,就以自己為準了。 class Riven(Hero):camp='Noxus'def attack(self,enemy): #在子類中定義新的attack,不再使用父類的attack,不會影響父類print('from riven')def fly(self): #在子類中定義新的函數print('%s is flying' %self.nickname) 在子類中,新建的重名的函數屬性,在編輯函數內功能的時候,有可能需要重用父類中重名的那個函數功能, 應該是用調用普通函數的方式,即:類名.func(),此時就與調用普通函數無異了,因此即便是self參數也要為其傳值class Riven(Hero):camp='Noxus'def __init__(self,nickname,aggressivity,life_value,skin):Hero.__init__(self,nickname,aggressivity,life_value) #調用父類功能self.skin=skin #新屬性def attack(self,enemy): #在自己這里定義新的attack,不再使用父類的attack,且不會影響父類Hero.attack(self,enemy) #調用功能print('from riven')def fly(self): #在自己這里定義新的print('%s is flying' %self.nickname)r1=Riven('銳雯雯',57,200,'比基尼') r1.fly() print(r1.skin)''' 運行結果 銳雯雯 is flying 比基尼'''
組合與重用性
軟件重用除繼承外還有組合,指的是在一個類中以另外一個類的對象作為數據屬性,稱為類的組合:>>> class Equip: #武器裝備類 ... def fire(self): ... print('release Fire skill') ... >>> class Riven: #英雄Riven的類,一個英雄需要有裝備,因而需要組合Equip類 ... camp='Noxus' ... def __init__(self,nickname): ... self.nickname=nickname ... self.equip=Equip() #用Equip類產生一個裝備,賦值給實例的equip屬性 ... >>> r1=Riven('銳雯雯') >>> r1.equip.fire() #可以使用組合的類產生的對象所持有的方法 release Fire skill 組合與繼承都是有效地利用已有類的資源的方式。但是二者的概念和使用場景不同:1.繼承的方式: 通過繼承建立了派生類與基類之間的關系,它是一種'是'的關系,比如白馬是馬,人是動物。 當類之間有很多相同的功能,提取這些共同的功能做成基類,用繼承比較好,比如老師是人,學生是人2.組合的方式: 用組合的方式建立了類與組合的類之間的關系,它是一種‘有’的關系,比如教授有生日, 教授教python和linux課程,教授有學生s1、s2、s3...當類之間有顯著不同,并且較小的類是較大的類所需要的組件時,用組合比較好: class People:def __init__(self,name,age,sex):self.name=nameself.age=ageself.sex=sexclass Course:def __init__(self,name,period,price):self.name=nameself.period=periodself.price=pricedef tell_info(self):print('<%s %s %s>' %(self.name,self.period,self.price))class Teacher(People):def __init__(self,name,age,sex,job_title):People.__init__(self,name,age,sex)self.job_title=job_titleself.course=[]self.students=[]class Student(People):def __init__(self,name,age,sex):People.__init__(self,name,age,sex)self.course=[]t1=Teacher('egon',18,'male','沙河霸道金牌講師') s1=Student('牛榴彈',18,'female')python=Course('python','3mons',3000.0) linux=Course('linux','3mons',3000.0)#為老師egon和學生s1添加課程 t1.course.append(python) # 將python對象添加到老師 course列表屬性中 t1.course.append(linux) # 將linux對象添加到 老師course列表屬性中 s1.course.append(python) # 將python對象添加到 學生course列表屬性中#為老師egon添加學生s1 t1.students.append(s1)#使用 for obj in t1.course: # t1.course屬性保存的是Cource類的對象obj.tell_info() # obj此時代表的是Cource類的對象,"""結果:<python 3mons 3000.0><linux 3mons 3000.0>"""接口與歸一化設計
接口提取了一群類共同的函數,可以把接口當做一個函數的集合。然后讓子類去實現接口中的函數。
歸一化設計:
只要是基于同一個接口實現的類,所有這些類產生的對象在使用時,在用法上都一樣。好處:
1、讓使用者無需關心對象的類是什么,只要知道這些對象都具備某些功能,降低使用者的使用難度。
2、 歸一化使得高層的外部使用者可以不加區分的處理所有接口兼容的對象集合。
(如:有一個汽車接口,里面定義了汽車所有的功能,然后由本田汽車的類,奧迪汽車的類,大眾汽車的類,
他們都實現了汽車接口,這樣就好辦了,大家只需要學會了怎么開汽車,那么無論是本田,還是奧迪,
還是大眾我們都會開了,開的時候根本無需關心我開的是哪一類車,操作手法(函數調用)都一樣)模仿interface接口
抽象類
python模仿Interface代碼只是看起來像接口,并未起到接口的作用,子類完全可不實現接口 ,這就用到了抽象類
抽象類:
抽象類是一個特殊的類,只能被繼承,不能被實例化,采用內置模塊實現
類是從一堆對象中抽取相同的內容而來的,那么抽象類就是從一堆類中抽取相同的內容而來的,內容包括數據屬性和函數屬性。
從設計角度去看,如果類是從現實對象抽象而來的,抽象類就是基于類抽象而來的。
從實現角度來看,抽象類與普通類的不同之處在于:抽象類中只能有抽象方法(沒有實現功能),該類不能被實例化,只能被繼承,且子類必須實現抽象方法.
抽象類與接口:
抽象類的本質還是類,指的是一組類的相似性,包括數據屬性(如all_type)和函數屬性(如read、write),而接口只強調函數屬性的相似性。抽象類是一個介于類和接口之間的概念,同時具備類和接口的部分特性,可以用來實現歸一化設計.
繼承實現的原理
Python中子類可以同時繼承多個父類,如A(B,C,D),
如果繼承關系為菱形結構,那么屬性的查找方式有兩種,分別是:深度優先和廣度優先
python繼承原理
python對于自定義的每一個類,python會計算出一個方法解析順序(MRO)列表, MRO列表就是一個簡單的所有基類的線性順序列表:F.mro() # 等同于F.__mro_,查看繼承順序_ [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]實現繼承時,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類為止。 而這個MRO列表的構造是通過一個C3線性化算法實現,它實際就是合并所有父類的MRO列表,并遵循如下三條準則: 1.子類會先于父類被檢查 2.多個父類會根據它們在列表中的順序被檢查 3.如果對下一個類存在兩個合法的選擇,選擇第一個父類子類中調用父類的方法
方法一:指名道姓,即父類名.父類方法() #_*_coding:utf-8_*_ __author__ = 'Linhaifeng'class Vehicle: #定義交通工具類Country='China'def __init__(self,name,speed,load,power):self.name=nameself.speed=speedself.load=loadself.power=powerdef run(self):print('開動啦...')class Subway(Vehicle): #地鐵def __init__(self,name,speed,load,power,line):Vehicle.__init__(self,name,speed,load,power) # 初始化父類中的構造方法,為父類中的內存提供參數self.line=linedef run(self):print('地鐵%s號線歡迎您' %self.line)Vehicle.run(self) # 調用父類中的run方法,此時不會報錯,因為上面調用了父類中的構造方法,內存中有該類,傳入的參數為Subway對象line13=Subway('中國地鐵','180m/s','1000人/箱','電',13) line13.run() # 調用子類中的run方法,該方法中包含調用父類中的方法,所以最終會調用父類中的方法 方法二:super():class Vehicle: #定義交通工具類Country='China'def __init__(self,name,speed,load,power):self.name=nameself.speed=speedself.load=loadself.power=powerdef run(self):print('開動啦...')class Subway(Vehicle): #地鐵def __init__(self,name,speed,load,power,line):#super(Subway,self) 就相當于實例本身 在python3中super()等同于super(Subway,self)super().__init__(name,speed,load,power) # 初始化父類中的方法self.line=linedef run(self):print('地鐵%s號線歡迎您' %self.line)super(Subway,self).run() # 調用父類中的方法,將Subway的對象作為參數傳入class Mobike(Vehicle):#摩拜單車passline13=Subway('中國地鐵','180m/s','1000人/箱','電',13) line13.run() # 兩者區別: 強調:二者使用哪一種都可以,但最好不要混合使用 1、即使沒有直接繼承關系,super仍然會按照mro繼續往后查找 #指名道姓:父類名.父類方法() class A:def __init__(self):print('A的構造方法') class B(A):def __init__(self):print('B的構造方法')A.__init__(self)class C(A):def __init__(self):print('C的構造方法')A.__init__(self)class D(B,C):def __init__(self):print('D的構造方法')B.__init__(self)C.__init__(self)pass f1=D() #A.__init__被重復調用 ''' D的構造方法 B的構造方法 A的構造方法 C的構造方法 A的構造方法 '''#使用super() class A:def __init__(self):print('A的構造方法') class B(A):def __init__(self):print('B的構造方法')super(B,self).__init__()class C(A):def __init__(self):print('C的構造方法')super(C,self).__init__()class D(B,C):def __init__(self):print('D的構造方法')super(D,self).__init__()f1=D() #super()會基于mro列表,往后找 ''' D的構造方法 B的構造方法 C的構造方法 A的構造方法 '''總結: 當使用super()函數時,Python會在MRO列表上繼續搜索下一個類。 只要每個重定義的方法統一使用super()并只調用它一次,那么控制流最終會遍歷完整個MRO列表,每個方法也只會被調用一次 (注意注意注意:使用super調用的所有屬性,都是從MRO列表當前的位置往后找,千萬不要通過看代碼去找繼承關系,一定要看MRO列表)多態與多態性
多態指的是一類事物有多種形態
動物有多種形態:人,狗,豬:import abc class Animal(metaclass=abc.ABCMeta): #同一類事物:動物@abc.abstractmethoddef talk(self): # 抽象類方法定義passclass People(Animal): #動物的形態之一:人def talk(self):print('say hello')class Dog(Animal): #動物的形態之二:狗def talk(self):print('say wangwang')class Pig(Animal): #動物的形態之三:豬def talk(self):print('say aoao') 文件有多種形態:文本文件,可執行文件:import abc class File(metaclass=abc.ABCMeta): #同一類事物:文件@abc.abstractmethoddef click(self):passclass Text(File): #文件的形態之一:文本文件def click(self):print('open file')class ExeFile(File): #文件的形態之二:可執行文件def click(self):print('execute file')多態性是指在不考慮實例類型的情況下使用實例:
向不同的對象發送同一條消息,不同的對象在接收時會產生不同的行為(即方法)。
多態性分為靜態多態性和動態多態性:
靜態多態性:如任何類型都可以用運算符+進行運算
動態多態性:如下
封裝
python中用雙下劃線開頭的方式將屬性隱藏起來(設置成私有的):#其實這僅僅這是一種變形操作且僅僅只在類定義階段發生變形 #類中所有雙下劃線開頭的名稱如__x都會在類定義時自動變形成:_類名__x的形式:class A:__N=0 #類的數據屬性就應該是共享的,但是語法上是可以把類的數據屬性設置成私有的如__N,會變形為_A__Ndef __init__(self):self.__X=10 #變形為self._A__Xdef __foo(self): #變形為_A__fooprint('from A')def bar(self):self.__foo() #只有在類內部才可以通過__foo的形式訪問到.# A._A__N是可以訪問到的, # 但是在外部是無法通過__x這個名字訪問到。 注意:1.這種機制也并沒有真正意義上限制我們從外部直接訪問屬性,知道了類名和屬性名就可以拼出名字:_類名__屬性,然后就可以訪問了,如a._A__N,即這種操作并不是嚴格意義上的限制外部訪問,僅僅只是一種語法意義上的變形,主要用來限制外部的直接訪問。 2.變形的過程只在類的定義時發生一次,在定義后的賦值操作,不會變形注意:1.python的封裝機制并沒有真正限制從外部直接訪問屬性, 當知道類名和屬性名就可拼出名字:_類名__屬性進行訪問, 如a._A__N,該操作并非嚴格意義上的限制外部訪問,只是一種語法意義上的變形,主要用來限制外部的直接訪問。 2.變形的過程只在類的定義時發生1次,在定義后的賦值操作,不會變形 3.在繼承中,父類如果不想讓子類重寫自己的方法,可將方法定義為私有#正常情況 >>> class A: ... def fa(self): ... print('from A') ... def test(self): ... self.fa() ... >>> class B(A): ... def fa(self): ... print('from B') ... >>> b=B() >>> b.test() from B#把fa定義成私有的,即__fa>>> class A: ... def __fa(self): #在定義時就變形為_A__fa ... print('from A') ... def test(self): ... self.__fa() #只有通過在自己類中對__fa()方法進行調用,即調用_A__fa ... >>> class B(A): ... def __fa(self): ... print('from B') ... >>> b=B() >>> b.test() # 調用父類中的test方法中封裝的__fa()方法,傳入的參數為b對象 from A
封裝不是單純意義的隱藏
1:封裝數據:將數據隱藏不是目的。隱藏后對外提供操作該數據的接口,可在接口附加上對該數據操作的限制, 以此完成對數據屬性操作的嚴格控制: class Teacher:def __init__(self,name,age):# self.__name=name # 封裝屬性# self.__age=age # 封裝屬性self.set_info(name,age)def tell_info(self):print('姓名:%s,年齡:%s' %(self.__name,self.__age))def set_info(self,name,age): # 對傳入的參數進行驗證if not isinstance(name,str): # 類型判斷raise TypeError('姓名必須是字符串類型') # 拋出異常if not isinstance(age,int):raise TypeError('年齡必須是整型')self.__name=name # 驗證通過,對封裝的屬性進行賦值self.__age=aget=Teacher('egon',18) t.tell_info()t.set_info('egon',19) t.tell_info() # 2:封裝方法:目的是隔離復雜度封裝方法舉例: 1. 電視機本身是一個黑盒子,隱藏了所有細節,但是一定會對外提供了一堆按鈕,這些按鈕也正是接口的概念,所以說,封裝并不是單純意義的隱藏!!!2. 快門就是傻瓜相機為傻瓜們提供的方法,該方法將內部復雜的照相功能都隱藏起來了提示:在編程語言里,對外提供的接口(接口可理解為了一個入口),可以是函數,稱為接口函數,這與接口的概念還不一樣,接口代表一組接口函數的集合體。#取款是功能,而這個功能有很多功能組成:插卡、密碼認證、輸入金額、打印賬單、取錢 #對使用者來說,只需要知道取款這個功能即可,其余功能我們都可以隱藏起來,很明顯這么做 #隔離了復雜度,同時也提升了安全性class ATM:def __card(self):print('插卡')def __auth(self):print('用戶認證')def __input(self):print('輸入取款金額')def __print_bill(self):print('打印賬單')def __take_money(self):print('取款')def withdraw(self):self.__card() # 調用在同一類中封裝的方法self.__auth()self.__input()self.__print_bill()self.__take_money()a=ATM() a.withdraw() 3: 了解 python并不會真的阻止訪問私有屬性,模塊也遵循這種約定, 如果模塊名以單下劃線開頭,那from module import *時不能被導入, 但采用from module import _private_module依然可以導入。 調用一個模塊的功能時會遇到單下劃線開頭的(socket._socket,sys._home,sys._clear_type_cache), 這都是私有,原則上是供內部調用的,作為外部調用時也可以用。python要像與其他編程語言一樣,嚴格控制屬性的訪問權限, 需借助內置方法如__getattr__封裝與擴展性
封裝在于明確區分內外,使得類實現者可以修改封裝內的東西而不影響外部調用者的代碼;而外部使用用者只知道一個接口(函數),只要接口(函數)名、參數不變,使用者的代碼永遠無需改變。
這就提供一個良好的合作基礎——或者說,只要接口這個基礎約定不變,則代碼改變不足為慮。
總結
以上是生活随笔為你收集整理的(第七集——第一章)python面向对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电大计算机应用基础形考任务4答案,最新国
- 下一篇: 【ZedBoard实验随笔】OV7670