1. 程式人生 > >python全棧開發-面向物件-進階2 python_day_19

python全棧開發-面向物件-進階2 python_day_19

今日主要內容:

  • 1.抽象類,介面類
  • 2.多型
  • 3.封裝

1.抽象類,介面類

python 沒有介面這個概念
介面類,抽象類: 制定一個規範.

舉個栗子:
你的專案經理提一個需求,讓你做一個支付功能.
第一版:
class Alipay:
    def __init__(self,money):
        self.money = money

    def pay(self):
        print('使用支付寶支付了%s' %self.money)


class Jdpay:
    def __init__(self, money):
        self.money = money

    def pay(self):
        print('使用京東支付了%s' % self.money)

a1 = Alipay(200)
a1.pay()

j1 = Jdpay(100)
j1.pay()

經理看了,然後讓你改進,讓你支付的方式一樣

第二版:

class Alipay:
    def __init__(self,money):
        self.money = money

    def pay(self):
        print('使用支付寶支付了%s' %self.money)


class Jdpay:
    def __init__(self, money):
        self.money = money

    def pay(self):
        print('使用京東支付了%s' % self.money)

def pay(obj):
    obj.pay()

a1 = Alipay(200)
j1 = Jdpay(100)
pay(a1)  # 歸一化設計
pay(j1)

第三版,野生程式設計師來了.......要增加一個微信支付的功能.
class Alipay:
    def __init__(self,money):
        self.money = money

    def pay(self):
        print('使用支付寶支付了%s' %self.money)

class Jdpay:
    def __init__(self, money):
        self.money = money

    def pay(self):
        print('使用京東支付了%s' % self.money)

class Wechatpay:

    def __init__(self,money):
        self.money = money

    def weixinpay(self):
        print('使用微信支付了%s' % self.money)


def pay(obj):
    obj.pay()

a1 = Alipay(200)
j1 = Jdpay(100)
pay(a1)  # 歸一化設計
pay(j1)

w1 = Wechatpay(300)
w1.weixinpay()

經理看了覺得很亂,打回去重新修改,制定規則,抽象類,介面類
第四版:
from abc import ABCMeta,abstractmethod

class Payment(metaclass=ABCMeta):  # 抽象類(介面類):
    @abstractmethod
    def pay(self): pass  # 制定了一個規範


class Alipay(Payment):
    def __init__(self,money):
        self.money = money

    def pay(self):
        print('使用支付寶支付了%s' %self.money)


class Jdpay(Payment):
    def __init__(self, money):
        self.money = money

    def pay(self):
        print('使用京東支付了%s' % self.money)

class Wechatpay(Payment):

    def __init__(self,money):
        self.money = money

    def pay(self):
        print('使用微信支付了%s' % self.money)


def pay(obj):
    obj.pay()
w1 = Wechatpay(200)
a1 = Alipay(200)
j1 = Jdpay(100)
pay(a1)  # 歸一化設計
pay(j1)
pay(w1)

2.多型.

python面向物件的三大特徵之一: 多型: python處處是多型.

python:弱型別語言
python 不管什麼型別,傳入函式,封裝到物件中都可以.
python的鴨子型別.
鴨子型別 : 看著像鴨子,他就是鴨子.
以下這些類 都互稱為鴨子.
class Str:
    def index(self):
        pass

class List:
    def abc(self):
        pass

class Tuple:
    def rrr(self):
        pass
3.封裝
廣義的封裝: 例項化一個物件,給物件空間封裝一些屬性.
狹義的封裝: 私有制.
私有成員:私有靜態欄位,私有方法,私有物件屬性
私有靜態欄位
class B:
    __money = 100000

class A(B):
    name = 'alex'
    __age = 1000

    def func(self):
        print(self.__age)
        print(A.__age)    # 對於私有靜態欄位,類的內部可以訪問.
        print('func....')
    def func1(self):
        print(self.__money)
        print(A.__money)
a1 = A()
print(a1.name)
print(A.name)

print(a1.__age)  # 例項化物件不能訪問私有靜態欄位
print(A.__age)  # 類名不能訪問私有靜態欄位
對於私有靜態欄位,類的外部不能訪問.

a1.func()

#對於私有靜態欄位,類的內部可以訪問.

a1.func1()

#對於私有靜態欄位來說,只能在本類中內部訪問,類的外部,派生類均不可訪問.

#可以訪問,但是工作中千萬不要用.
print(A._A__age)
print(A.__dict__)

#私有方法

class B:
    __money = 100000
    def __f1(self):
        print('B')

class A(B):
    name = 'alex'

    def __func(self):
        print('func....')

    def func1(self):
        # self.__func()   # 類的內部可以訪問
        self.__f1()
a1 = A()
a1.__func()  # 類外部不能訪問
a1.func1()  # 類的內部可以訪問
a1.func1()  # 類的派生類也不能訪問.

私有物件屬性同私有方法和私有靜態欄位,類外部不能訪問,類的內部可以訪問,類的派生類也不能訪問.

補充一個面試題:
3,下面程式碼執行結果是什麼?為什麼?
class Parent:
    def func(self):
        print('in Parent func')

    def __init__(self):
        self.func()

class Son(Parent):
    def func(self):
        print('in Son func')

son1 = Son()

流程圖;

結果圖;

原因:

因為Son(),是例項化過程,然後自動執行__init__函式,Son類裡沒有,去父類裡找,然後執行父類的__init__方法,執行func方法,先從自己的類中找,有func,執行func,
列印in Son func

補充知識點:
MRO-C演算法-python多繼承原理
class H:

    def bar(self):
        print('F.bar')
class G(H):

    def bar(self):
        print('F.bar')
class F(H):

    def bar(self):
        print('F.bar')
class E(G):

    def bar(self):
        print('E.bar')

class D(F):

    def bar(self):
        print('D.bar')


class C(E):
    def bar(self):
        print('C.bar')


class B(D):

    def bar(self):
        print('B.bar')


class A(B, C, D):

    def bar(self):
        print('A.bar')

a = A()
print(A.mro())

流程圖;

執行過程:

A(B,C,D)

首先找到A繼承的三個類的深度繼承順序,放到一個列表中 L[B] = [B,D,F,H] #B往上面的繼承順序 L[C] = [C,E,G,H] #C往上面的繼承順序 L[D] = [D,F,H] #D往上面的繼承順序

第二步:A自己的廣度,第一層 L[A] = [B,C,D]

每個列表的第一個元素為頭部,從第一個列表的頭部開始找,找其他列表中尾部是否含有 這個類名,如果沒有,提取出來放到一個列表中,如果有,找下一個列表的頭部,迴圈下去 只要提取來一個,我們就從第一個列表的頭部接著重複上面的操作. 1 [B,D,F,H] [C,E,G,H] [D,F,H] [B,C,D] 2 [D,F,H] [C,E,G,H] [D,F,H] [C,D] #提取了頭部的B,然後將其他列表頭部的B刪除,並將B放到list中 3 [D,F,H] [E,G,H] [D,F,H] [D] #因為第一個列表的D在其他列表的尾部存在,所以跳過D,然後找第二個列表的頭部C,提取了頭部的C,然後將其他列表頭部的B刪除,並將B放到list中

.......

4 [H] [H] [H] []

list = [A,B,C,D,F,E,G,H,O]