1. 程式人生 > >python全棧開發【第十六篇】面向對象三大特性——多臺和繼承補充

python全棧開發【第十六篇】面向對象三大特性——多臺和繼承補充

全棧 space 其他 到你 使用 方法名 調用父類 大眾 chat

一、回顧

面向對象

  1.類:具有相同屬性和方法 的一類事物

     類名可以實例化一個對象

     類名可以調用類屬性,(靜態屬性 和(方法)動態屬性)

  2.對象:也就是實例

     對象名:調用對象屬性

          調用方法

  3.什麽叫抽象?

    從小到大的過程

  4.組合-----什麽有什麽的關系(將一個類的對象當做另一個類的屬性)

  5.繼承-----什麽是什麽的關系

      從大範圍到小範圍的過程

      繼承的作用:減少代碼的重用性

      子類有的方法,就用子類的。不會調用父類的方法。

      如果要在子類中調用父類的方法:super().類名()

  6.派生:父類沒有的子類有了

     派生類:在父類的基礎上,又產生了子類,這個子類就叫做派生類

     派生屬性:父類裏沒有的屬性但子類中有了的屬性就叫做派生方法。

     派生方法:父類裏沒有的方法但子類中有了的方法就叫做派生方法。

  7.方法的重寫

     父類裏有子類裏也有的方法叫做方法的重寫

二、接口類與抽象類

1.接口類:(在抽象類的基礎上)

    在python中,默認是沒有接口類的

    接口類不能被實例化(如果實例化會報錯)

    接口類中的方法不能被實現

1.正常調用
class Applepay:
    def pay(self,money):
        print(‘apple pay 支付了%s‘ %money)

class Alipay:
    def pay(self,money):
        print(‘支付寶  支付了%s‘ %money)

def payment(pay_obj,money):  #實例化的另一種調用,這個方法讓實例化的時候按照payment調用:就像下面的payment(apple1,200)
        pay_obj.pay(money)

apple1 = Applepay()
# apple1.pay(200)
payment(apple1,200)
# 2.有時候寫的時候會把方法寫錯,自己定義一個主動報錯
# 接口初成:手動報異常:NotImplementedError來解決開發中遇到的問題
class Payment:
    def pay(self):
        raise NotImplementedError  #主動讓程序報錯

class Wechatpay(Payment): #微信支付
    def pay(self,money):
        print(‘微信支付了%s元‘,money)

class QQchatpay(Payment): #QQ支付
    def fuqian(self,money):
        print(‘QQ支付了%s元‘,money)

p = Wechatpay()
p.pay(200)   #不報錯
q = QQchatpay()   #不報錯
q.pay()  #報錯
# 3.借用abc模塊來實現接口
#接口類(就是為了提供標準,約束後面的子類)
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self,money):
        pass

class Wechatpay(Payment):
    def fuqian(self,money):
        ‘‘‘實現了pay的功能,但是方法名字不一樣‘‘‘
        print(‘微信支付了%s元‘%money)

class Alipay:
    def pay(self,money):
        print(‘支付寶  支付了%s‘ %money)

# p = Wechatpay() #報錯了(因為上面定義了一個接口類,接口類裏面
# 定義了一個pay方法,而在下面的Wechatpay方法裏沒有pay方法,不能
# 調用,在接口類裏面約束一下,接口類裏的pay方法裏面不能寫其他,直接pass)
a = Alipay()
a.pay(200)
p = Payment() #接口類不能被實例化
為何要用接口

接口提取了一群類共同的函數,可以把接口當做一個函數的集合。

然後讓子類去實現接口中的函數。

這麽做的意義在於歸一化,什麽叫歸一化,就是只要是基於同一個接口實現的類,那麽所有的這些類產生的對象在使用時,從用法上來說都一樣。

歸一化,讓使用者無需關心對象的類是什麽,只需要的知道這些對象都具備某些功能就可以了,這極大地降低了使用者的使用難度。

比如:我們定義一個動物接口,接口裏定義了有跑、吃、呼吸等接口函數,這樣老鼠的類去實現了該接口,松鼠的類也去實現了該接口,由二者分別產生一只老鼠和一只松鼠送到你面前,即便是你分別不到底哪只是什麽鼠你肯定知道他倆都會跑,都會吃,都能呼吸。

再比如:我們有一個汽車接口,裏面定義了汽車所有的功能,然後由本田汽車的類,奧迪汽車的類,大眾汽車的類,他們都實現了汽車接口,這樣就好辦了,大家只需要學會了怎麽開汽車,那麽無論是本田,還是奧迪,還是大眾我們都會開了,開的時候根本無需關心我開的是哪一類車,操作手法(函數調用)都一樣

接口也就是做約束,讓下面的類的方法都按照接口類中給出的方法去定義。如果接口類裏面有的方法類裏面沒有,那麽那個類就不能被實例化。(字面理解)

繼承的第二種含義非常重要。它又叫“接口繼承”。
接口繼承實質上是要求“做出一個良好的抽象,這個抽象規定了一個兼容接口,使得外部調用者無需關心具體細節,可一視同仁的處理實現了特定接口的所有對象”——這在程序設計上,叫做歸一化。

2.抽象類:

    在python中,默認是有的

    父類的方法,子類必須實現

    抽象類(父類)的方法可以被實現

# 抽象類
# 什麽叫做抽象?  從小範圍到大範圍
from abc import ABCMeta,abstractmethod
class Animal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):
        print(‘打開糧食的袋子‘)
        print(‘放一個吃飯的碗‘)
        print(‘吧糧食倒在碗裏‘)

    @abstractmethod
    def sleep(self):
        pass

class Dog(Animal):
    #實現吃喝睡的方法
    def eat(self):
        super().eat()
        # super(Dog, self).eat()
        print(‘dog is eating‘)
    def sleep(self):
        print(‘dog is sleeping‘)

# d = Dog()
# d.eat()
a = Animal()  #抽象類不能被實例化

3.抽象類和接口類的區別:接口類不能實現方法,抽象類可以實現方法裏面的內容

4.抽象類和接口類的相同點:都是用來做約束的,都不能被實例化

5.抽象類和接口類的使用:

  當幾個子類的父類有相同的功能需要被實現的時候就用抽象類

  當幾個子類有相同的功能,但是實現各不相同的時候就用接口類

6.python中的抽象類和接口類在Java裏面的區別

  接口類支持多繼承

  抽象類只支持單繼承

三、多繼承

在繼承抽象類的過程中,我們應該盡量避免多繼承;

而在繼承接口的時候,我們反而鼓勵你來多繼承接口

接口隔離原則:

使用多個專門的接口,而不是用單一的總接口。即客戶端不應該依賴那些不需要的接口
class A:
    def test(self):
        print(‘from A‘)
class B(A):
    def test(self):
        print(‘from B‘)
class C(A):
    def test(self):
        print(‘from C‘)
class D(A):
    def test(self):
        print(‘from D‘)
class E(B):pass
    # def test(self):
    #     print(‘from E‘)

class F(E,D,C):pass
    # def test(self):
        # print(‘from F‘)


# b= B()
# b.test()
# d = D()
# d.test() #一級一級往上找,自己沒有,就繼承爹的,爹沒有就找爺爺的
        # 再找不到就報錯了
f = F()
f.test()
print(F.mro()) #查看找父類的順序

 

四、鉆石繼承

新式類:廣度優先:橫著找(如鉆石繼承圖,誰先在前面就找誰)

經典類:深度優先:從上到下找

技術分享圖片

技術分享圖片

五、多態

多態指的是一類事物有多種形態(比如:老師.下課鈴響了(),學生.下課鈴響了(),老師執行的是下班操作,學生執行的是放學操作,雖然二者消息一樣,但是執行的效果不同)

例如:動物有多種形態:人,狗,豬

from abc import ABCMeta,abstractmethod
class Animal(metaclass=ABCMeta):
    @abstractmethod
    def eat(self):pass
class Cat(Animal):  #動物的形態之一:貓
    def eat(self):
        print(‘cat eat‘)
class Dog(Animal):  #動物的形態之二:狗
    def eat(self):
        print(‘dog eat‘)

class Pig(Animal):pass  #動物的形態之三:豬
def eat_fun(animal_obj): #定義一個函數讓這個函數名去調用
    animal_obj.eat()
c = Cat()
eat_fun(c)  #函數名(對象)

d = Dog() 
eat_fun(d)

c = Cat()
c.eat()

python自帶多態:

  多態:同一類事物的多種狀態

  python裏處處都是多態,只是我們一般發現不了

  操作的時候不需要關心這個對象的數據類型,你只要用就行了

靜態多態性(了解就好)

鴨子類型(如果兩個類裏面都有相同的方法,但是他們的類裏面沒有任何繼承)
序列(str,list,tuple):有順序的數據集合,這三個沒有任何繼承

python全棧開發【第十六篇】面向對象三大特性——多臺和繼承補充