編程方式:java
面向過程: 根據代碼在腳本的堆疊順序,從上到下依次執行python
函數式編程:將相同功能的代碼封裝到函數中,直接調用便可,減小代碼重複性c++
面向對象:對函數進行分類和封裝,將同類的函數放到一個類中,使調用更簡單sql
爲嘛要面向對象編程
應用需求
要的對系統的cpu、內存、硬盤等進行監控,超過閾值則告警服務器
while True: if cpu利用率 > 90%: #發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接 if 硬盤使用空間 > 90%: #發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接 if 內存佔用 > 80%: #發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接
隨着python的學習,開始使用函數式編程多線程
def 發送郵件(內容) #發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接while True: if cpu利用率 > 90%: 發送郵件('CPU報警') if 硬盤使用空間 > 90%: 發送郵件('硬盤報警') if 內存佔用 > 80%: 發送郵件('內存報警')
函數式編程增長了代碼的可讀性和重用性,可是,這僅僅是單臺機器的監控,若是我要監控多臺呢,可能須要須要這樣寫:編程語言
def 發送郵件(內容) #發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接while True:for host in host-list: #經過遍歷host列表來進行監控 if cpu利用率 > 90%: 發送郵件('CPU報警') if 硬盤使用空間 > 90%: 發送郵件('硬盤報警') if 內存佔用 > 80%: 發送郵件('內存報警')
這樣貌似實現了,可是若是是1000臺機器呢,可能當循環到999臺的時候,第100臺已經出現問題了。形成告警延誤。而若是使用面向對象呢?將很好的解決此問題ide
class host:def 發送郵件(內容) #發送郵件提醒 鏈接郵箱服務器 發送郵件 關閉鏈接def judge(self):while True: if cpu利用率 > 90%: 發送郵件('CPU報警') if 硬盤使用空間 > 90%: 發送郵件('硬盤報警') if 內存佔用 > 80%: 發送郵件('內存報警')
我將每一個機器建立爲一個對象,對象中有上面判斷的方法,這樣我就能夠多線程的監控函數式編程
類和對象
類就是一個模板,模板裏能夠包含多個方法(即函數),方法裏實現一些功能,對象則是根據模板建立的實例,經過實例對象能夠執行類中的函數
建立類和對象
#建立類 class+類名class foo: #class是關鍵字,表示類,foo是類的名字def f1(self): #類的方法1passdef f2(self): #類的方法2pass#建立對象 對象 = 類名()bar = foo() #建立一個bar對象 ,此對象中有類中全部的方法 ,建立對象,類名稱後加括號便可#調用對象的方法 對象.方法名()bar.f1()bar.f2()
舉例:
#建立類class SQL: def create(self,sql): print(sql) def modify(self, sql): print(sql) def remove(self,sql): print(sql) def fetch(self,sql): print(sql)#建立對象obj1 = SQL()obj2 =SQL()#調用對象裏的方法res1 = obj1.modify('修改')res2 = obj2.fetch('查看')print('obj1:'res1)print('obj2:'res2)運行結果:obj1: 修改obj2: 查看
應用場景
面向對象:【建立對象】【經過對象執行方法】,適用於當某一些函數中具備相同參數時,可使用面向對象的方式,將參數值一次性封裝到對象裏,函數直接調用便可
函數編程:【執行函數】 各個函數之間是獨立且無共用的數據
類中的self是什麼鬼
self是python自動傳值的一個形式參數,那個對象調用方法,就會自動執行self,在一個類中,self就是對象自己
還用上面的例子,若是我須要在執行方法的時候,驗證用戶名、密碼傳,驗證經過以後才能執行裏面的方法,那我須要建立對象以後,進行賦值用戶密碼
class SQL:def modify(self, sql): print(sql) print(self.name) print(self.passwd) def remove(self,sql): print(sql) print(self.name) print(self.passwd) def fetch(self,sql): print(sql) print(self.name) print(self.passwd)#建立對象obj1 = SQL()obj1.user = 'user'obj1.passwd = 'passwd'res1 = obj1.modify('修改')res2 = obj2.fetch('結果')print(res1)print(res2)輸出結果:修改userpasswd結果userpasswd
咱們使用self來定義user和passwd變量,這樣user和passwd對整個對象是生效的,因此在每一個方法都均可以調用到
類的構造方法
上例發現每次對象調用方法都要進行對user 和password進行賦值。很是麻煩。
python類中使用init自動構造方法,當建立對象的時候自動執行該方法。以下使用init,這樣我只須要定義一次便可
class SQL:def __init__(self,user,password): self.user = user self.password = password def create(self,sql): print(sql) print(self.name) print(self.passwd) def modify(self, sql): print(sql) print(self.name) print(self.passwd) def remove(self,sql): print(sql) print(self.name) print(self.passwd) def fetch(self,sql): print(sql) print(self.name) print(self.passwd)obj1 = SQL('username','password')obj1.remove()obj2 = SQL('username1','password1')obj2.remove()
封裝
封裝,顧名思義就是將內容封裝到某個地方,之後再去調用被封裝在某處的內容。因此,在使用面向對象的封裝特性時,須要:
將內容封裝到某處
class SQL: def __init__(self,name,passwd): #類的構造方法,自動執行 self.name = name self.passwd = passwd def create(self,sql): #類的一個方法 print(sql,self.name,self.passwd)#建立類SQL的obj對象obj1 = SQL('fuzj','123') #自動fuzj和123分別封裝到對象obj1的name和asswd屬性中obj2 = SQL('jie','311') #自動jie和311分別封裝到對象obj2的name和asswd屬性中
從某處調用被封裝的內容
方式1 經過對象直接調用
res = obj1.name #直接調用obj的user屬性res2 = obj1.passwd #直接調用obj的passwd屬性print(res,res2)輸出結果:fuzj 12313
方式2 經過self間接調用
res3 = obj1.create('fasdasda')print(res3)輸出結果:fasdasda fuzj 12313
多重封裝
類不只能夠將普通字符串封裝到類中,還能夠將一個對象封裝到類中,看下面代碼
#建立類class SQL: def __init__(self,name,passwd): self.name = name self.passwd = passwd def create(self,sql): print(sql)class test: def __init__(self,name,obj): self.name = name self.obj = obj def add(self,arg): print(arg)class test2: def __init__(self,obj): self.obj = obj def iner(slef,arg): print(arg)#建立對象c1 = SQL('fuzj','12313')c2 = test('aaa',c1) #把c1對象封裝到c2對象裏,c2對象會有c1對象的全部方法c3 = test2(c2) #把c2對象封裝到c3對象中,c3對象會有c2對象的全部方法,同時也就有了c1對象的全部方法#調用c1.create("c1調用自身create方法")c2.obj.create('c2調用c1的create方法')c3.obj.add('c3調用c2的add方法')c3.obj.obj.create('c3調用c1的create方法')結果:c1調用自身create方法c2調用c1的create方法c3調用c2的add方法c3調用c1的create方法
能夠看出,將a對象封裝到b對象中,b對象也就有了a對象的全部方法,
其關係如圖:
因此c3若是要使用c1的create的方法,須要以下調用
c3.obj.obj.create()
繼承
類的繼承是子類繼承父類的全部方法,或者說基類繼承派生類的全部方法
class 父類: def 方法1(slef): passclass 子類(父類): pass那麼子類中就會有父類的方法1
* 單繼承 一個子類只繼承一個父類 以下:
class c1: def __init__(self): self.name = 'c1' self.user = 'c1uer' def test(self): print("c1_test") def test1(self): print("c1_test1") def test3(self): self.test()class c2(c1): def __init__(self): self.passwd = 'c2' def test(self): print("c2_test") def test2(self): self.test3()obj = c2()obj.test()obj.test1()obj.test2()執行結果:c2_testc1_test1c2_test
繼承規則:
1) 調用子類的某個方法時,若是這個方法在子類中存在,則執行子類的方法,若是子類方法不存在,再去找父類的方法。因此執行obj.test()時,子類中有該方法,就直接執行該方法,再也不父類中找,所以返回結果是c2_test;執行obj.test1()時,子類中沒有改方法,就找到父類的方法,再執行,所以返回的結果是c1_test1
2) 子類的方法優先於父類的方法,當父類的方法中有調取其餘方法時,會優先查找子類的方法,因此執行c2_test2()時,發現該方法調用的時是test3(),因而開始從本身方法中查找test3(),而後再去找父類中的方法,找到父類的test3()方法,發現該方法調用了test()方法,因而會再次查找test()方法,發現本身有,因此就直接調用本身的test()方法,返回c2_test
3) 子類繼承父類,其實就是將父類中的方法子類中沒有的所有挪到子類下
* 多繼承 * python的子類能夠繼承多個父類,這是比java、c++等開發語言最大的優點 單父繼承,即沒有共同的父類,規則爲一條道走到黑
class 父類1:passclass 父類2:passclass 子類(父類1,父類2)pass那麼,子類中就會有父類1,父類2的全部方法
#c4繼承了c2,c3兩個父類,c2繼承了c1父類,c3和c1中都有test()的方法class c1: def test1(self): print("c1_test") def test(self): print("c1_test")class c2(c1): def test2(self): print('c2_test')class c3: def test3(self): print("c3_test") def test(self): print("c3_test")class c4(c2,c3): def test4(self): print('c4_test')obj = c4()obj.test()obj.test3()運行結果:c1_testc3_test從結果能夠看出:obj.test()執行順序爲:首先去c4類中查找,若是c4類中沒有,則繼續去c2類中找,若是c2類中沒有,則繼續去父類c1類中找,因此test()打印的結果爲c1_testobj.test3()執行順序爲:首先去c4類中查找,若是c4類中沒有,則繼續去c2類中找,若是c2類中沒有,則繼續去父類c1類中找,c1沒有,則返回繼續去另外一個c4的父類c3中找,因此test3()打印的結果爲c3_test
繼承規則:
1)子類中有兩個父類,會從左到右依次查找父類的方法
2)子類的父類若是還有繼承,優先查找當前父類的父類
3)多繼承的每次查找父類仍然遵循單繼承的原則
即
同父繼承,最上邊有繼承的是一個父類,狀況則不同了
#c4繼承c2和c3兩個父類,c2繼承c1父類,c3繼承c0父類,c0和c1繼承c父類class c: def test(self): print("c_test")class c0(c): def test(self): print("c0_test")class c1(c): def test1(self): print("c1_test")class c2(c1): def test2(self): print('c2_test')class c3(c0): def test3(self): print("c3_test")class c4(c2,c3): def test4(self): print('c4_test')obj = c4()obj.test()運行結果:c0_test查找順序爲:1.查找c4中是否有test()方法,若是沒有則查找c2中,c2中沒有則查找c1中,c1中沒有,不會繼續查找父類了,會反回來查找c3類,c3類沒有則找c0類,最後返回結果
該規則一樣適用下面狀況
多態
Pyhon不支持多態而且也用不到多態,多態的概念是應用於Java和C#這一類強類型語言中,而Python崇尚「鴨子類型」
多態中python和其餘編程語言最大的區別是傳參問題。python的函數傳參,參數能夠是列表,字典,字符串,數字等,而java、c++等語言傳遞參數時,參數須要指定類型,一旦參數類型被指定,就只能處理此中類型的數據
舉例:
python:
def func(arg):passarg 能夠是字符串、數字、列表、字典等
java或c++
def func(int,arg)passarg 只能處理int類型的數據def func(str,arg)passarg只能處理字符串類型的數據,若是數據類型不符合的話。直接報錯
java如何支持多態
class A:passclass B(A):passclass C(A)passdef func(B,arg):pass此時arg指定類型爲B,那麼只能爲B的對象類型def func(A,arg)pass此時指定arg類型爲A類型,而B和C都繼承A,因此ABC類型均可以使用了因此相似java的編程語言,都是利用類的繼承關係來實現多態