type 和 class
type 一個物件的時候,結果總是這個物件所屬的類
那麼類是什麼型別?
所有的類的型別都是type
type 是所有型別的鼻祖
type( 類名 ) = type
類也是被創造出來的 可以由python直譯器創造 也可以由特殊的方法創造
常規創造的類 總是有幾個特性
能夠例項化 能有屬性 能有方法一些有特殊需求的類
所有的用class常規語法創造出來的類 都是type型別
元類
能幫你創造出不同尋常的類
可以實現特殊的需求 例如 不能例項化 只能有一個例項
抽象類
類的約束
不同的類,要使用的方法相同,但如果有一個類的方法名字寫錯了 呼叫方法的時候會很麻煩
class Wechatpay: def __init__(self,name,money): self.name = name self.money = money def pay(self): print('%s通過微信支付了%s元'%(self.name,self.money)) class Alipay: def __init__(self,name,money): self.name = name self.money = money def pay(self): print('%s通過支付寶支付了%s元'%(self.name,self.money)) class ApplePay: def __init__(self,name,money): self.name = name self.money = money def fuqian(self): print('%s通過apple pay支付了%s元' % (self.name, self.money)) # 歸一化設計 def pay(person): person.pay() wcp = Wechatpay('alex',2000000) pay(wcp) ali = Alipay('alex',2000000) app = ApplePay('alex',2000000) pay(app) 程式碼的規範沒有建立起來
所以此時我們要用到對類的約束,對類的約束有兩種:
1. 提取⽗類. 然後在⽗類中定義好⽅法. 在這個⽅法中什麼都不⽤⼲. 就拋⼀個異常就可以了. 這樣所有的⼦類都必須重寫這個⽅法. 否則. 訪問的時候就會報錯.
2. 使⽤元類來描述⽗類. 在元類中給出⼀個抽象⽅法. 這樣⼦類就不得不給出抽象⽅法的具體實現. 也可以起到約束的效果.
先用第一種方式解決:
class Payment: """ 此類什麼都不做,就是制定一個標準,誰繼承我,必須定義我裡面的方法。 """ def pay(self,money): raise Exception("你沒有實現pay方法") class QQpay(Payment): def pay(self,money): print('使用qq支付%s元' % money) class Alipay(Payment): def pay(self,money): print('使用阿里支付%s元' % money) class Wechatpay(Payment): def fuqian(self,money): print('使用微信支付%s元' % 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,abstractmethod class Payment(metaclass=ABCMeta): # 抽象類 @abstractmethod # 如果我必須要實現pay方法,那麼我需要給pay加一個裝飾器 def pay(self): pass # 建立的這個pay並沒有內容, # 之所以寫一個pay是為了提醒所有子類你一定要實現一個pay方法 # 如果子類沒有使用這兩個方法,就會報錯 @abstractmethod def back(self): pass class Wechatpay(Payment): def __init__(self,name,money): self.name = name self.money = money def pay(self): print('%s通過微信支付了%s元'%(self.name,self.money)) def back(self): print('退款') class Alipay(Payment): def __init__(self,name,money): self.name = name self.money = money def pay(self): print('%s通過支付寶支付了%s元'%(self.name,self.money)) def back(self): print('退款') class ApplePay(Payment): def __init__(self, name, money): self.name = name self.money = money def pay(self): print('%s通過apple pay支付了%s元' % (self.name, self.money)) def back(self): print('退款') w = Wechatpay('alex',200) w.pay()
from abc import ABCMeta,abstractmethod class Payment(metaclass=ABCMeta): # 抽象類 介面類 規範和約束 metaclass指定的是一個元類 @abstractmethod def pay(self):pass # 抽象方法 class Alipay(Payment): def pay(self,money): print('使用支付寶支付了%s元'%money) class QQpay(Payment): def pay(self,money): print('使用qq支付了%s元'%money) class Wechatpay(Payment): # def pay(self,money): # print('使用微信支付了%s元'%money) def recharge(self):pass def pay(a,money): a.pay(money) a = Alipay() a.pay(100) pay(a,100) # 歸一化設計:不管是哪一個類的物件,都呼叫同一個函式去完成相似的功能 q = QQpay() q.pay(100) pay(q,100) w = Wechatpay() pay(w,100) # 到用的時候才會報錯 # 抽象類和介面類做的事情 :建立規範 # 制定一個類的metaclass是ABCMeta, # 那麼這個類就變成了一個抽象類(介面類) # 這個類的主要功能就是建立一個規範
總結
約束. 其實就是⽗類對⼦類進⾏約束. ⼦類必須要寫xxx⽅法. 在python中約束的⽅式和⽅法有兩種:
1. 使⽤抽象類和抽象⽅法, 由於該⽅案來源是java和c#. 所以使⽤頻率還是很少的
2. 使⽤⼈為丟擲異常的⽅案. 並且儘量丟擲的是NotImplementError. 這樣比較專業, ⽽且錯誤比較明確.(推薦)
介面類
java中沒有多繼承的類
所以抽象類 只能是所有的子類只有一個規範
於是發明了介面 介面可以多繼承
在python中沒有介面專用語法
只是通過類的多繼承 模仿介面效果
抽象類是單繼承的規範 介面類是多繼承的規範
from abc import ABCMeta,abstractmethod class NormalAnnimal(metaclass=ABCMeta): @abstractmethod def eat(self):pass @abstractmethod def drink(self):pass class FlyAnimal(metaclass=ABCMeta): @abstractmethod def fly(self):pass class SwimAnimal(metaclass=ABCMeta): @abstractmethod def swim(self):pass class WalkAnimal(metaclass=ABCMeta): @abstractmethod def walk(self):pass class Frog(NormalAnnimal,SwimAnimal,WalkAnimal): def eat(self): pass class Tiger(NormalAnnimal,SwimAnimal,WalkAnimal):pass class Swan(NormalAnnimal,FlyAnimal,SwimAnimal,WalkAnimal):pass class Parrot(NormalAnnimal,FlyAnimal,WalkAnimal): def talk(self): pass