Python 面向對象
記住一句話:類是模板,而實例則是根據類創建的對象。
初學時對類的理解是從類的字面上,可以片面的認爲它是一個種類,它是相似特徵的抽像,也就是相似的東西,可以把相似特徵的事務抽象成一個類。(事務可以是具體的物體或行爲)
以圓爲例,圓是具有圓周率(pi)和半徑(r)兩個相似特徵的屬性。根據相似特徵抽象出圓類,每個圓的半徑可以不同,那麼半徑可以作爲圓的實例屬性;而每個圓的圓周率pi是相同的,那麼圓周率pi就可以作爲類屬性,這樣就定義出了一個圓類。而我們要知道圓的面積,周長等可以通過類方法計算出來。
(看完整篇文章,還是對類不理解,回過頭在來看這部分,對照列子多理解。)
類的應用場景:
零散代碼(代碼塊)-->函數(方法)-->類-->模塊(文件)
類:表示抽象(模糊)的事物
對象:表示具體(清晰)的事物
1、面向對象技術簡介
- 類(Class): 用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例。
- 類變量:類變量在整個實例化的對象中是公用的。類變量定義在類中且在函數體之外。類變量通常不作爲實例變量使用。
- 數據成員:類變量或者實例變量, 用於處理類及其實例對象的相關的數據。
- 方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆蓋(override),也稱爲方法的重寫。
- 局部變量:定義在方法中的變量,只作用於當前實例的類。
- 實例變量:在類的聲明中,屬性是用變量來表示的。這種變量就稱爲實例變量,是在類聲明的內部但是在類的其他成員方法之外聲明的。
- 繼承:即一個派生類(derived class)繼承基類(base class)的字段和方法。繼承也允許把一個派生類的對象作爲一個基類對象對待。例如,有這樣一個設計:一個Dog類型的對象派生自Animal類,這是模擬"是一個(is-a)"關係(例圖,Dog是一個Animal)。
- 實例化:創建一個類的實例,類的具體對象。
- 方法:類中定義的函數。
- 對象:通過類定義的數據結構實例。對象包括兩個數據成員(類變量和實例變量)和方法。
2、創建類
使用 class 語句來創建一個新類,class 之後爲類的名稱並以冒號結尾:
class ClassName:
'類的幫助信息' #類文檔字符串
class_suite #類體
類的幫助信息可以通過ClassName.doc查看。
class_suite 由類成員,方法,數據屬性組成。
(1)例子
描述人類的文件
類的結構:
1、動態的行爲(動詞):speak、sing
2、靜態的屬性(名詞):gender、user_name
(1)全局:在類中的任何地方都能使用
(2)局部:只能夠在方法內部使用
使用類:
實例化對象:對象名 = 類名 ( 參數【可選的】)
class Human():
"""模擬人類"""
def __init__(self, sex, name):
"""初始化屬性:gender和user_name"""
self.gender = sex
self.user_name = name
def speak(self):
"""模擬人類說話"""
print(self.user_name.title() + "正在說話。")
def sing(self):
"""模擬人類唱歌"""
print(self.user_name.title() + "正在唱歌。")
empCount
變量是一個類變量,它的值將在這個類的所有實例之間共享。你可以在內部類或外部類使用Employee.empCount
訪問。- 第一種方法
__init__()
方法是一種特殊的方法,被稱爲類的構造函數或初始化方法,當創建了這個類的實例時就會調用該方法 self
代表類的實例,self
在定義類的方法時是必須有的,雖然在調用時不必傳入相應的參數。
輸出結果如下:
# 使用類 man = Human('男','xgp') man.speak() lz = Human('男','kk') lz.sing()
(2)修改初始值
class Pet():
def __init__(self,sex,strain):
"""給屬性賦初始值(默認值)"""
self.nick_name = '咪咪'
self.gender = sex
self.stain = strain
cat = Pet('公','土貓')
# 修改初始值
cat.nick_name = '妙妙'
print(cat.nick_name)
輸出結果如下:
妙妙
3、self代表類的實例,而非類
類的方法與普通的函數只有一個特別的區別——它們必須有一個額外的第一個參數名稱
, 按照慣例它的名稱是 self。
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
輸出結果如下:
<__main__.Test instance at 0x10d066878> __main__.Test
從執行結果可以很明顯的看出,self 代表的是類的實例,代表當前對象的地址,而 self.__class__
則指向類。
self 不是 python 關鍵字,我們把他換成 runoob
也是可以正常執行的:
class Test:
def prt(runoob):
print(runoob)
print(runoob.__class__)
t = Test()
t.prt()
輸出結果如下:
<__main__.Test instance at 0x10d066878> __main__.Test
4、創建實例對象
實例化類其他編程語言中一般用關鍵字 new,但是在 Python 中並沒有這個關鍵字,類的實例化類似函數調用方式。
以下使用類的名稱 Dn
來實例化,並通過 __init__
方法接收參數。
"""
小名和小紅各自買了一臺筆記本電腦,
其中小名的電腦品牌是聯想, CPU8核, 512G固態硬盤,雙飛燕鼠標
省紅的電腦品牌是機械師, CPU4核, 256G固態硬盤+1T普通硬盤,機械師鼠標
使用面向對象的思維,編寫代碼完成以 上描述。
"""
class Dn():
def __init__(self,name,brand,cpu,disk,mouse):
self.nice_name = name
self.nice_pp = brand
self.nice_cpu = cpu
self.nice_disk = disk
self.nice_mouse = mouse
def xgp(self):
print(self.nice_name + '的電腦配置:“'
+ '品牌:' + self.nice_pp + ','
+ 'cpu:' +self.nice_cpu + ','
+ '硬盤:' +self.nice_disk + ','
+ '鼠標:' + self.nice_mouse + ','
+ '”。')
# 可以使用點號 . 來訪問對象的屬性。使用如下類的名稱訪問類變量
Dn1 = Dn('小名','聯想','8核','512固態硬盤','雙飛燕')
Dn1.xgp()
Dn2 = Dn('小米','機械師','4核','256G固態硬盤+1T普通硬盤','機械師鼠標')
Dn2.xgp()
輸出結果如下:
小名的電腦配置:“品牌:聯想,cpu:8核,固態硬盤:512固態硬盤,鼠標:雙飛燕”。 小名的電腦配置:“品牌:機械師,cpu:4核,固態硬盤:256G固態硬盤,機械硬盤1T普通硬盤,鼠標:機械師鼠標”。
5、類的繼承
面向對象的編程帶來的主要好處之一是代碼的重用,實現這種重用的方法之一是通過繼承機制。
通過繼承創建的新類稱爲子類
或派生類,被繼承的類稱爲基類
、父類
或超類
。
繼承語法
class 派生類名(基類名)
...
在python中繼承中的一些特點:
- 1、如果在子類中需要父類的構造方法就需要顯示的調用父類的構造方法,或者不重寫父類的構造方法。詳細說明可查看:python 子類繼承父類構造函數說明。
- 2、在調用基類的方法時,需要加上基類的類名前綴,且需要帶上 self 參數變量。區別在於類中調用普通函數時並不需要帶上 self 參數
- 3、Python 總是首先查找對應類型的方法,如果它不能在派生類中找到對應的方法,它纔開始到基類中逐個查找。(先在本類中查找調用的方法,找不到纔去基類中找)。
如果在繼承元組中列了一個以上的類,那麼它就被稱作"多重繼承" 。
語法:
派生類的聲明,與他們的父類類似,繼承的基類列表跟在類名之後,如下所示:
class SubClassName (ParentClass1[, ParentClass2, ...]):
...
(1)例子
class Parent: # 定義父類
parentAttr = 100
def __init__(self):
print ("調用父類構造函數")
def parentMethod(self):
print('調用父類方法')
def setAttr(self, attr):
Parent.parentAttr = attr
def getAttr(self):
print ("父類屬性 :", Parent.parentAttr)
class Child(Parent): # 定義子類
def __init__(self):
print ("調用子類構造方法")
def childMethod(self):
print ('調用子類方法')
c = Child() # 實例化子類
c.childMethod() # 調用子類的方法
c.parentMethod() # 調用父類方法
c.setAttr(200) # 再次調用父類的方法 - 設置屬性值
c.getAttr() # 再次調用父類的方法 - 獲取屬性值
輸出結果如下:
調用子類構造方法 調用子類方法 調用父類方法 父類屬性 : 200
(2)例子
"""
小名和小紅各自買了一臺筆記本電腦,
其中小名的電腦品牌是聯想, CPU8核, 512G固態硬盤,雙飛燕鼠標
省紅的電腦品牌是機械師, CPU4核, 256G固態硬盤+1T普通硬盤,機械師鼠標
使用面向對象的思維,編寫代碼完成以 上描述。
"""
class Dn():
def __init__(self,brand,cpu,disk,mouse):
self.nice_pp = brand
self.nice_cpu = cpu
self.nice_disk = disk
self.nice_mouse = mouse
# 繼承:共享某個類的代碼
class XiaoMing(Dn):
def __init__(self,brand,cpu,disk,mouse):
super().__init__(brand,cpu,disk,mouse)
def xgp(self,name):
print(name + '的電腦配置:“'
+ '品牌:' + self.nice_pp + ','
+ 'cpu:' +self.nice_cpu + ','
+ '固態硬盤:' +self.nice_disk + ','
+ '鼠標:' + self.nice_mouse
+ '”。')
class XiaoHong(Dn):
def __init__(self,brand,cpu,disk,sim_disk,mouse):
self.sim_disk = sim_disk
super() . __init__(brand,cpu,disk,mouse)
def wsd(self,name):
print(name + '的電腦配置:“'
+ '品牌:' + self.nice_pp + ','
+ 'cpu:' + self.nice_cpu + ','
+ '固態硬盤:' + self.nice_disk + ','
+ '機械硬盤' + self.sim_disk + ','
+ '鼠標:' + self.nice_mouse
+ '”。')
xiaoming = XiaoMing('聯想','8核','512固態硬盤','雙飛燕')
xiaoming.xgp('小名')
xiaohong = XiaoHong('機械師','4核','256G固態硬盤','1T普通硬盤','機械師鼠標')
xiaohong.wsd('小名')
輸出結果如下:
小名的電腦配置:“品牌:聯想,cpu:8核,固態硬盤:512固態硬盤,鼠標:雙飛燕”。 小名的電腦配置:“品牌:機械師,cpu:4核,固態硬盤:256G固態硬盤,機械硬盤1T普通硬盤,鼠標:機械師鼠標”。
6、總結
參數的傳遞圖,翻譯與pythoncentral網
- In 1 and 2, the arguments are passed to the method.
- 1和2參數傳遞給init方法中的data參數。
- On 3, the self argument refers to the instance.
- 3**self 參數指向當前實例自身,self代表創建的實例變量 ik1 或者 Kls('arun')。**
- At 4, we do not need to provide the instance to the method, as it is handled by the interpretor itself.
- 4 我們不需要傳遞實例自身給方法,Python解釋器自己會做這些操作的;ik14 會自動作爲第一個實例參數(self)傳入方法中。