1. 程式人生 > >Day21 抽象、接口、多太、鴨子類型

Day21 抽象、接口、多太、鴨子類型

只有一個 如果 代碼 面試題 c++ 抽象類 apply 不同的 耦合

面向對象復習:

派生方法和派生屬性:

  super只有在子父類擁有同名方法的時候

  想使用子類的對象調用父類的方法時,才使用super

  super在類內:super().方法名(args1,..)

多繼承 鉆石繼承

  經典類 python2 不繼承object

    查找名字遵循深度優先遍歷算法

  新式類 python3中都是新式類 在py2中繼承object

    查找名字遵循廣度優先遍歷算法

      每一個節點可以在深度廣度上都有機會被訪問到的時候,只有一次

      優先從廣度上查找

    類名.mro()方法可以查看廣度優先的順序

    super()的作用:在廣度優先中查看當前這個類的上一個節點

      在py2中super必須傳參,super(子類名,self).方法名(args1,...)

# 抽象類和接口類
  java 編程原則和設計模式
  設計模式 程序設計 具有裏程碑意義的設計方式 從java中演變出來的

    單例模式:

    一個類只有一個實例

# 編程原則
  # python
  # 開放封閉原則
    # 開放 對擴展是開放的
    # 封閉 對修改是封閉的
  # 依賴倒置原則
  # 接口隔離原則
# 已經寫完的程序代碼是不允許修改的

# 支付功能的例子
  # 支付寶支付
  # qq支付
  # apply_pay
  # 微信支付

# 創建一個規範
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta): # 抽象類 接口類  規範和約束  metaclass指定的是一個元類
    @abstractmethod
    def pay(self):pass
class Alipay:
    def pay(self,money):
        print(使用支付寶支付了%s元%money)

class QQpay:
    def pay(self,money):
        print(使用qq支付了%s元
%money) class Wechatpay: def pay(self,money): print(使用微信支付了%s元%money) def pay(a,money): a.pay(money) a = Alipay() a.pay(100) #歸一化設計:不管是哪一個類的對象,都調用同一個函數去完成相似的功能 q = QQpay() q.pay(80) w = Wechatpay() w.pay(50)
# 歸一化設計
# l = [1,2,2]
# l2 = {1,2,3,4}
# l3 = (1,2)
# a = ‘1234567‘
# print(len(l))
# print(l3.__len__())
# len()  和 __len__()
# 只有一個類中實現了__len__()方法,才能使用len()函數
# def len2(obj):  # 歸一化設計
#     return obj.__len__()

# print(len(l))
# print(len(l2))
# print(len(l3))

抽象類和接口類做的事情:建立規範

指定一個類的metaclass是ABCMeta 那麽這個類就變成了一個抽象類(接口類)這個類的主要功能就是建立一個規範

抽象類中所有被abstractmethod裝飾的方法都必須被繼承的子類實現

如果不實現,那麽在實例化階段會報錯

無論是抽象類和接口類metaclass=ABCMeta都不可以被實例化

p = payment() #報錯

接口隔離原則

什麽叫接口
python裏沒有接口的概念
那接口是哪兒來的概念呢?
java類沒有多繼承 接口可以實現多繼承
# 描述動物園
# 會遊泳的 會走路的 會爬樹的 會飛的
# 老虎
# 青蛙
# 天鵝
# 猴子

from abc import ABCMeta,abstractmethod
class FlyAnimal(metaclass = ABCMeta):
    @abstractmethod
    def fly(self):pass
    @abstractmethod
    def cal_flying_speed(self):pass
    @abstractmethod
    def cal_flying_height(self):pass
class WalkAnimal(metaclass=ABCMeta):
    @abstractmethod
    def walk(self):pass
class SwimAnimal(metaclass = ABCMeta):
    @abstractmethod
    def swim(self):pass
class Tiger(WalkAnimal,SwimAnimal):
    def walk(self):pass
    def swim(self):pass
class Monkey(WalkAnimal):
    def walk(self):pass
    def climb(self):pass
class Swan(FlyAnimal,WalkAnimal,SwimAnimal):
    def fly(self):pass
    def cal_flying_speed(self):pass
    def cal_flying_height(self):pass
    def walk(self):pass
    def swim(self):pass
class Parrot(FlyAnimal):
    def fly(self):pass
    def cal_flying_speed(self):pass
    def cal_flying_height(self):pass

# 所有會飛的動物 具有一些會飛的動物的特性
# 所有會走的動物 具有一些會走的動物的特性

#接口類的作用:

  在java中,能夠滿足接口隔離原則,且完成多繼承的約束

  而在python中,由於python本身支持多繼承,所有不需要接口的概念了

# 抽象類和接口類

在python中:

  並沒有什麽不同,都是用來約束子類中的方法

  只要是抽象類和接口類中被abstractmethod裝飾的方法,都需要被子類實現

  需要註意的是,當多個類之間有相同的功能也有不同的功能的時候,應該采用多個接口類來進行分別的約束

在java中:

  抽象類和接口截然不同

  抽象類的本質還是一個類,是類就必須遵循單繼承的規則,所以一個子類如果被抽象類約束,那麽它只能被一個父類控制

  當多個類之間有相同的功能也有不同的功能的時候 java只能用接口來解決問題

面試題:

  抽象類是python中定義類的一種規範

  在python中沒有接口的概念,但是有接口的功能,多說一些顯示對其他語言的了解

# 在公司裏寫代碼的時候如果遇到抽象類,記得按照抽象類中的規範一一去是實現對應的方法

面試題:

多態:一定是通過繼承實現的

  在java中:一個類之下發展出來的多個類的對象都可以作為參數傳入一個函數

  在python天生自帶多態效果,無論python2還是python3,都不需要刻意實現多態

# 多態
  # java c++ c# —— 強類型語言
  # 相同數據類型之間做運算
  # def func(int a):pass
  # func(‘a‘)

  # shell語言 —— 弱類型語言
  # 1+‘1‘
  # def func(a):pass
  # 1 ‘a‘ [1,2,3] ()

# 介於 強類型 與 弱類型之間 —— python 動態強類型語言

相同數據類型之間做運算

# def func(a):pass
class Payment:
    def pay(self):pass

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(Payment pay_obj,int money):   #  java 多態 在一個類之下發展出來的多個類的對象都可以作為參數傳入這裏
#     pay_obj.pay(money)

# 無論是python的2.*還是3.* : 天生自帶多態效果
# qq_obj = QQpay()
# print(type(qq_obj))  # 一個對象的數據類型就是它所在的類
# # # qq_obj.pay(100)
# pay(qq_obj,100)
# we_obj = Wechatpay()
# # # we_obj.pay(200)
# pay(we_obj,200)
# def len(object obj):pass
# class len_class:pass
# class tuple(len_pass):pass
# class list(len_pass):pass
# class str(len_pass):pass
# tuple list str dict set

<class ‘__main__.QQpay‘>
使用qq支付了100元
使用微信支付了200元

鴨子類型

Python崇尚鴨子類型,即‘如果看起來像、叫聲像而且走起路來像鴨子,那麽它就是鴨子’

python程序員通常根據這種行為來編寫程序。例如,如果想編寫現有對象的自定義版本,可以繼承該對象

也可以創建一個外觀和行為像,但與它無任何關系的全新對象,後者通常用於保存程序組件的松耦合度。

# class QQpay():
#     def pay(self,money):
#         print(‘使用qq支付了%s元‘%money)
#
# class Wechatpay():
#     def pay(self,money):
#         print(‘使用微信支付了%s元‘%money)
#
# def pay(pay_obj,money):
#     pay_obj.pay(money)
例2:序列類型有多種形態:字符串,列表,元組,但他們直接沒有直接的繼承關系
# 索引
class list:
    def index(self):pass
class str:
    def index(self):pass
class tuple:
    def index(self):pass
# [].index()
# ‘‘.index()
# ().index()

# 鴨子類型:python
  # 不是通過具體的繼承關系來約束某些類中必須有哪些方法名
  # 是通過一種約定俗成的概念來保證在多個類中相似的功能叫相同的名字

  

Day21 抽象、接口、多太、鴨子類型