一、面向對象編程概述
1、面向對象編程(OOP)
面向對象:以具體的事物(對象)為單位,考慮它的屬性(特征)及動作(行為),關注整體。java、c#也是面向對象編程。
-
例子解讀(把大象裝進冰箱):為了把大象裝進冰箱,需要做三個動作(行為)。每個動作有一個執(zhí)行者,它就是對象,這里對象是冰箱。
- 冰箱,你給我把門打開(冰箱.開門())
- 冰箱,你給我把大象裝進去(冰箱.裝大象())
- 冰箱,你給我把門關上(冰箱.關門())
依次做這些動作,就能把大象裝進冰箱。
-
三大特征
(1)封裝(信息隱蔽技術):類的封裝、函數(shù)封裝,方便調用。
#創(chuàng)建一個list1列表對象,我們不需知道列表對象里方法的具體實現(xiàn)過程,封裝好了,用方法名直接調用即可 >>>list1 = [1,5,2,6] >>>list1.append(10) >>>list1 [1,5,2,6,10] >>>list1.sort() [1,2,5,6,10](2)繼承:子類繼承父類的方法和屬性
#創(chuàng)建一個Mylist類,繼承l(wèi)ist類的屬性和方法 class Mylist(list): pass>>>list2 = Mylist() >>>list2.append(4) >>>list2.append(5) >>>list2.append(6) >>>list2 [4,5,6]類名后面緊接著是(object),表示該類是從哪個類繼承下來的。通常,如果沒有合適的繼承類,就使用object類,這是所有類最終都會繼承的類。
(3)多態(tài):不同對象對同一方法響應不同的行動,而無需明確知道這個對象是什么。即一個方法,多種形態(tài),就是多態(tài)。
class Person(Object): def func(self): print('我是人!') class Girl(Person): def func(self): print('我是妹子!') class Boy(Person): def func(self): print('我是漢子!') def func1(x): #涉及知識點:靜態(tài)/動態(tài)類型語言,file-like object,“鴨子類型”(duck typing) x.func()>>>a = Person() >>>b = Girl() >>>c = Boy() >>>a.func1() 我是人! >>>b.func1() 我是妹子! >>>c.func1() 我是漢子!
2、面向過程編程
面向過程:以一個具體的流程為單位,考慮它的實現(xiàn)方法,關心的是功能的實現(xiàn)(耦合性比較強)。C語言是面向過程編程。
-
例子解讀(把大象裝進冰箱):為了把大象裝進冰箱,需要3個過程。
- 把冰箱門打開(得到打開門的冰箱)
- 把大象裝進去(打開門后,得到里面裝著大象的冰箱)
- 把冰箱門關上(打開門、裝好大象后,獲得關好門的冰箱)
每個過程有一個階段性的目標,依次完成這些過程,就能把大象裝進冰箱。
3、類和對象
類是對一組具有相同特性(屬性)和相同行為(方法)的事物的概括,是抽象的模板;對象是客觀世界實際存在的事物都是一個對象,即“萬物萬事皆對象”。對象=屬性+方法
-
類是對象的模板,對象是類的實例
#定義一個人類Person,類名首字母要大寫 class Person: def __init__(self,name,sex,age): self.name=name #name,sex,age是類的屬性 self.sex=sex self.age=age #定義類的方法 def introduce(self): print('大家好,我叫%s,%s,今年%s歲'%(self.name,self.sex,self.age)) def eat(self): print('%s:好餓了,想吃大餐,畢竟吃飽了,才有力氣減肥,嘻嘻'%self.name) def run(self): print('%s:運動讓人快樂,跑步走起!'%self.name) def sleep(self): print('%s:不嗨了,早睡早起身體棒!'%self.name) #實例化,創(chuàng)建一個對象 >>>xiao_ming = Person('李小明','男','24') #調用Person類的方法 >>>xiao_ming.introduce() 大家好,我叫李小明,男,24歲 >>>xiao_ming.eat() 李小明:好餓了,想吃大餐,畢竟吃飽了,才有力氣減肥,嘻嘻 -
拓展
1、什么是類、類對象、實例對象?
#這是一個類,定義完之后也是一個類對象 class C: count=0 ----------------------------------------- >>>a=C() #a、b、c是實例對象 >>>b=C() >>>c=C() >>>a.count 0 >>>b.count 0 >>>c.count 0 --------------------------------------- >>>c.count+=10 #實例對象覆蓋了類對象里的屬性 >>>c.count 10 >>>a.count 0 >>>b.count 0 --------------------------------------- >>>C.count+=100 >>>C.count 100 >>>a.count 100 >>>b.count 100 >>>c.count 10graph TB task1("類定義 C")-->task2("類對象 C") task2-->task3("實例對象 a") task2-->task4("實例對象 b") task2-->task5("實例對象 c")
二、self是什么
類的定義里,self會出現(xiàn)在函數(shù)的第一個參數(shù)里(python的默認要求,必填參數(shù),這是與普通函數(shù)的一個區(qū)別),通過哪個對象調用的方法,則self就是哪個對象
-
例子解讀:(還是用上述Person類)
#實例化,創(chuàng)建xiao_ming對象 >>>xiao_ming = Person('李小明','男','24') #通過xiao_ming這個對象來調用introduce方法 >>>xiao_ming.introduce() 大家好,我叫李小明,男,今年24歲 #實例化,創(chuàng)建zhangli對象 >>>zhangli = Person('張麗','女','18') #通過zhangli這個對象來調用introduce方法 >>>zhangli.introduce() 大家好,我叫張麗,女,今年18歲def introduce(self):
? print('大家好,我叫%s,%s,今年%s歲'%(self.name,self.sex,self.age))
當對象xiao_ming調用introduce()方法時,self會調用xiao_ming的name,sex,age屬性作為參數(shù)輸入,然后print對應格式輸出自我介紹;而zhangli這個對象調用introduce()時,則傳入的是zhangli的name,sex,age。
三、訪問限制:公有與私有
-
C++中,用public和private標識公有變量與私有變量,而在python中,默認情況下,對象的屬性、方法都為公有的,用
.點操作符來訪問class Car: name = '本田' >>>c1 = Car() >>>c1.name #用.點操作符來訪問 '本田' >>>c1.name = '豐田' #外部可自由修改c1實例的name屬性 >>>c1.name '豐田' -
若要實現(xiàn)類似于私有變量的特征,python內(nèi)部采用了一種叫做name mangling名字改編的技術。在python中定義私有變量,只需在變量名或函數(shù)名前加上兩個下劃線"__",則該函數(shù)或變量就會變?yōu)樗接校挥袃?nèi)部可以訪問,外部不能訪問。
class Car: __name = '本田' #定義成私有變量 >>>c1 = Car() >>>c1.name #直接用點操作符訪問,會報錯,屬于外部調用 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Car' object has no attribute 'name' >>>c1.__name #也會報錯 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Car' object has no attribute '__name'在外部,私有變量”被隱藏“起來了,不能訪問。理論上,若要訪問私有變量,可通過在類中定義方法getname,內(nèi)部調用來訪問:
class Car: __name = '本田' def getname(self): return self.__name >>>c2 = Car() >>>c2.__name #仍會報錯 >>>c2.getname() #成功運行,此時的getname()是在內(nèi)部調用name屬性 '本田' #注意一下下面這種錯誤的修改私有變量方式 >>>c2.__name = '豐田' #表面上看,外部代碼“成功”地修改了__name變量,但實際上這個__name變量和class內(nèi)部的__name變量不是一個變量! >>>c2.__name '豐田' >>>c2.getname()#返回class內(nèi)部self.__name '本田'雖然上述代碼成功運行,而實際上,私有變量只是名字重整,被python改了名字,變?yōu)榱?em>類名_變量名而已。其實python是偽私有機制,python的類是無權限控制的,變量可被外部調用。
>>>c2._Car__name #還是用.操作符,對象._類名__變量名即可 '本田' -
注意:
1、不同版本的Python解釋器可能會把
__name改成不同的變量名,不一定是_Car__name!2、在Python中,變量名類似
__xxx__的,也就是以雙下劃線開頭,并且以雙下劃線結尾的,是特殊變量(魔法方法),特殊變量是可以直接訪問的,不是private變量。所以,不能用__name__、__score__這樣的變量名來定義私有變量。