面向對象三大特性、類的約束、print帶顏色輸出及super補充
簡述:
python面向對象的三大特性:
1.繼承是一種創建新類的方式,在python中,新建的類可以繼承一個或多個父類,父類又可稱為基類或超類,新建的類稱為派生類或子類,繼承:是基于抽象的結果,通過編程語言去實現它,肯定是先經歷抽象這個過程,才能通過繼承的方式去表達出抽象的結構。抽象只是分析和設計的過程中,一個動作或者說一種技巧,通過抽象可以得到類
2.封裝,顧名思義就是將內容封裝到某個地方,以后再去調用被封裝在某處的內容。
3.多態指的是一類事物有多種形態
繼承
上篇博客已做闡述
封裝
在使用面向對象封裝特性時,大致分兩個步驟:
1.將內容封裝到某處;
class Foo:def __init__(self,name,age): # 稱為構造方法,根據類創建對象自動執行self.name = nameself.age = age
obj1 = Foo("alex",18) # 將alex 和18 分別封裝到obj1的name和age屬性中
obj2 = Foo("taibai",30) # 將taibai 和30分別封裝到obj2的name和age屬性中
self為一個形式參數,接收obj1和obj2對象內存地址,當實例化對象時,對象屬性內容被封裝到obj1和obj2中,每個對象中都有name和age屬性
2.從某處調用被封裝的內容
調用封裝內容時,有兩種情況:
1.通過對象直接調用
class Foo:def __init__(self,name,age):self.name = nameself.age = age
obj1 = Foo("alex",18)
print(obj1.name)
print(obj1.age)obj2 = Foo("taibai",20)
print(obj2.name)
print(obj2.age)
# 通過對象直接調用被封裝的內容
2.通過self間接調用
執行類中的方法時,需要self間接調用被封裝的內容
class Foo:sef __init__(self,name,age):self.name =nameself.age = agedef detail(self):print(self.name)print(self.age)
obj1 = Foo("alex",18)
obj1.detail() # python默認會將obj1傳給self參數,此時detail中的self為obj1
obj2 = Foo("taibai",30)
obj1.detail() # python默認會將obj1傳給self參數,此時detail中的self為obj2
綜上所述,對于面向對象的封裝來說,其實就是使用構造方法將內容封裝到 對象 中,然后通過對象直接或者self間接獲取被封裝的內容。
多態
多態,同一個對象,多種形態。python默認支持多態。
# 在java或者c#定義變量或者給函數傳值必須定義數據類型,否則就報錯。def func(int a):print('a必須是數字')# 而類似于python這種弱定義類語言,a可以是任意形態(str,int,object等等)。
def func(a):print('a是什么都可以')# 再比如:
class F1:passclass S1(F1):def show(self):print 'S1.show'class S2(F1):def show(self):print 'S2.show'# 由于在Java或C#中定義函數參數時,必須指定參數的類型
# 為了讓Func函數既可以執行S1對象的show方法,又可以執行S2對象的show方法,所以,定義了一個S1和S2類的父類
# 而實際傳入的參數是:S1對象和S2對象def Func(F1 obj):
"""Func函數需要接收一個F1類型或者F1子類的類型"""print obj.show()s1_obj = S1()
Func(s1_obj) # 在Func函數中傳入S1類的對象 s1_obj,執行 S1 的show方法,結果:S1.shows2_obj = S2()
Func(s2_obj) # 在Func函數中傳入Ss類的對象 ss_obj,執行 Ss 的show方法,結果:S2.showPython偽代碼實現Java或C # 的多態
鴨子類型
class A:def f1(self):print('in A f1')def f2(self):print('in A f2')class B:def f1(self):print('in A f1')def f2(self):print('in A f2')obj = A()
obj.f1()
obj.f2()obj2 = B()
obj2.f1()
obj2.f2()
A和B兩個類完全沒有耦合性,但在某種意義上卻統一了一個標準
相同的功能設定了相同的名字,這樣便于開發,這兩個方法就互為鴨子類型
類的約束
這里所指的約束是對類的約束
對類的約束的兩種方法:
- 提取?類. 然后在?類中定義好?法. 在這個?法中什么都不??. 就拋?個異常就可以了. 這樣所有的?類都必須重寫這個?法. 否則. 訪問的時候就會報錯.
- 使?元類來描述?類. 在元類中給出?個抽象?法. 這樣?類就不得不給出抽象?法的具體實現. 也可以起到約束的效果.
第一種方法:
class Payment:def pay(self,money):raise Exception("你沒有實現pay方法") # 下面幾個類的父類,指定標準,繼承該基類的子類中必須定義pay方法,否則繼承此基類pay方法主動拋出異常
class QQpay(Payment):def pay(self,money):print(f"使用QQ支付{money}元")
class Alipay(Payment):def pay(self,money):print(f"使用阿里支付{money}元")
class Wechat(Payment):def fuqian(self,money):print(f"使用微信支付{money}元")
def pay(obj,money):obj.pay(money)
a = Alipay()
b = QQpay()
c = Wechatpay()
pay(a,100)
pay(b,200)
pay(c,300)
第二種方法:引入抽象類的概念進行處理
from abc import ABCMeta,abstractmeethod
class Payment(metaclass = ABCMeta): # 抽象類 接口類 規范和約束 metaclass指定的是一個元類@abstractmethoddef pay(self):pass # 抽象方法
class QQpay(Payment):def pay(self,money):print(f"使用QQ支付{money}元")
class Alipay(Payment):def pay(self,money):print(f"使用阿里支付{money}元")
class Wechat(Payment):def fuqian(self,money):print(f"使用微信支付{money}元")
def pay(obj,money):obj.pay(money)
w = Wechatpay()
pay(w,100)
super補充
class A: # 1def f1(self): # 2print('in A f1')def f2(self): # 3print('in A f2') # 9class Foo(A): # 4def f1(self): # 5super().f2() # 8 super(Foo,self).f2() obj對象內無f2 方法,在其父類A中查找print('in A Foo') # 10obj = Foo() # 6 實例化對象obj,并將obj的內存地址傳給self
obj.f1() # 7
# 結果:
'in A f2'
'in A Foo'
class A: # 1def f1(self): # 2print('in A')class Foo(A): # 3def f1(self): # 4super().f1() # 12 super(Foo,self).f1()print('in Foo') # 14class Bar(A): # 5def f1(self): # 6print('in Bar') # 13class Info(Foo,Bar): # 7def f1(self): # 8super().f1() # 11 self為Info,對象空間f1方法,按照mro算法執行Info下一個Foo super(Info,self).f1()print('in Info f1') # 15obj = Info() # 9 實例化對象
obj.f1() # 10
# 結果:
'in Bar'
'in Foo'
'in Info f1'
class A: # 1def f1(self): # 2print('in A')class Foo(A): # 3def f1(self): # 4super().f1()print('in Foo')class Bar(A): # 5def f1(self): # 6print('in Bar') # 12class Info(Foo,Bar): # 7def f1(self): # 8super(Foo,self).f1() # 11 按照mro算法執行Foo下一個Bar.f1()print('in Info f1') # 13obj = Info() # 9
obj.f1() # 10
# 結果:
'in Bar'
'in Info f1'
print帶顏色輸出
書寫格式: 開頭部分:\033[顯示方式;前景色;背景色m + 結尾部分:\033[0m
開頭部分的三個參數:顯示方式,前景色,背景色是可選參數,可以只寫其中的某一個;另外由于表示三個參數不同含義
的數值都是唯一的沒有重復的,所以三個參數的書寫先后順序沒有固定要求,系統都能識別;但是,建議按照默認的格式
規范書寫。對于結尾部分,其實也可以省略,但是為了書寫規范,建議\033[***開頭,\033[0m結尾。
字體色 | 背景色 | 顏色描述 |
---|---|---|
30 | 40 | 黑色 |
31 | 41 | 紅色 |
32 | 42 | 綠色 |
33 | 43 | 黃色 |
34 | 44 | 藍色 |
35 | 45 | 紫紅色 |
36 | 46 | 青藍色 |
37 | 47 | 白色 |
顯示方式 | 效果 |
---|---|
0 | 終端默認設置 |
1 | 高亮顯示 |
4 | 使用下劃線 |
5 | 閃爍 |
7 | 反白顯示 |
8 | 不可見 |
22 | 非粗體 |
24 | 非下劃線 |
25 | 非閃爍 |
27 | 非反顯 |
常見開頭格式:
\033[0m 默認字體正常顯示,不高亮
\033[32;0m 紅色字體正常顯示
\033[1;32;40m 顯示方式: 高亮 字體前景色:綠色 背景色:黑色
\033[0;31;46m 顯示方式: 正常 字體前景色:紅色 背景色:青色