1. 程式人生 > >python day 17 繼承(inheritance) 和 派生(derived) 、 多型 polymorphic 、 封裝 enclosure 、 內建函式 過載

python day 17 繼承(inheritance) 和 派生(derived) 、 多型 polymorphic 、 封裝 enclosure 、 內建函式 過載

目錄:

繼承(inheritance) 和 派生(derived) 、 多型 polymorphic 、 封裝 enclosure 、 內建函式 過載

issubclass 函式

語法:

issubclass(cls, class_or_tuple) 判斷一個類是否是繼承自其它的類,如果此類cls 是class 或tuple中的一個派生子類,則返回True, 否則返回False

示例:

class A:
  pass

class B(A):
  pass

class C(B):
  pass

class D(B):
  pass

issubclass(B
, A)
# True issubclass(C, B) # True issubclass(D, C) # False issubclass(C, (int, str)) False

封裝 enclosure

作用:

  1. 封裝是指隱藏類的實現細節.讓使用者不關心這些細節;
  2. 封裝的目的是讓使用者通過儘可能少的使用例項變數名(屬性)操作物件

私有屬性和方法

  1. 語法:
    1. python類中以雙下劃線(‘__’)開頭,不以雙下劃線結尾的識別符號為私有成員
    2. 私有成員只能被方法呼叫,不能在子類或其它地方使用
  2. 私有成員有兩種:

    1. 私有屬性
    2. 私有方法
  3. 示例:

      class A:
    def __init__(self): self.__p1 = 100 # 建立私有屬性 def __m1(self): print("A類的私有方法被呼叫!") def test(self): print(self.__p1) # 可以訪問 self.__m1() # 可以訪問!   a = A() # print(a.__p1) #  出錯,不可以訪問 # a.__m1() # 出錯,在類外部不能呼叫類的私有方法 a.test() # 用方法來操作私有屬性和私有方法

多型  polymorphic

字面意思:多種狀態

多型是指在有繼承/派生關係的類中,呼叫基類物件的方法,實際能呼叫子類的覆蓋方法的現象叫多型

多型說明:

多型呼叫方法與物件相關,不與類相關
python的全部物件只有”執行時狀態(動態)”, 沒有”C++/Java”裡的”編譯時狀態(靜態)”

多型示例:

class Shape:
    def draw(self):
        pass

class Point(Shape):
    def draw(self):
        print("正在畫一個點")

class Circle(Point):
    def draw(self):
        print("正在畫一個圓")


def my_draw(s):
    s.draw()  # 呼叫哪兒方法呢? 在執行時動態決定呼叫的方法

s1 = Circle()
s2 = Point()
my_draw(s1)
my_draw(s2) 

面向物件程式語言的特徵:

  1. 封裝
    1. 繼承
    2. 多型

面向物件的語言: C++/Java/Python/Swift/C#

多繼承 multiple inheritance

定義:

多繼承是指一個子類繼承自兩個或兩個以上的基類

語法:

 class 類名(超類名1, 超類名2, ...):
      pass

示例:

# 此示例示意多繼承
class Car:
    def run(self, speed):
        print("汽車以", speed, "km/h的速度行駛")


class Plane:
    def fly(self, height):
        print("飛機以海拔", height, "米的高度飛行")


class PlaneCar(Car, Plane):
    """飛行汽車類, 時繼承 自Car和 Plane"""


p1 = PlaneCar()
p1.fly(10000)
p1.run(299)

多繼承的問題(缺陷)

  1. 識別符號(名字空間)衝突的問題
    要謹慎使用多繼承
  2. 示例:
# 小張寫了一個類A
    class A:
        def m(self):
            print("A.m()被呼叫")

    # 小李寫了一個類B:
    class B:
        def m(self):
            print("B.m() 被呼叫")
    # 小王感覺小張和小李寫的兩個類自己可以用
    class AB(A, B):
         pass
    ab = AB()
    ab.m()  # 請問呼叫誰?

多繼承的 MRO (Method Resolution Order)問題

MRO 方法搜尋順序問題
python 3 廣度優先
python 2 深度優先

函式重寫 overwrite

什麼是函式重寫

在自定義的類中,通過新增特定的方法,讓自定義的類生成的物件(例項) 能象內建物件一樣進行內建函式操作

物件轉字串函式重寫

repr(obj) 返回一個能代表此物件的字串,通常:
eval(repr(obj)) == obj
str(obj) 通過給定的物件返回一個字串(這個字串通常是給人閱讀的)
換句話說:
repr(obj) 返回的字串是給python用的
str(obj) 返回字串是給人看的

重寫方法

repr(obj) 函式的重寫方法 def repr(self)
str(obj) 函式的重寫方法 def str(self)
當物件沒有 str方法時,則返回repr(self)的值

內建函式重寫

obj.abs() 方法對應 abs(obj)
obj.len() 方法對應 len(obj)
obj.reversed() 方法對應 reversed(obj)
obj.round() 方法對應 round(obj)

示例見:


# 此示例示意abs(obj) 函式的重寫方法 obj.__abs__() 方法的使用
class MyInteger:
    def __init__(self, value):
        self.data = value

    def __repr__(self):
        return 'MyInteger(%d)' % self.data

    def __abs__(self):
        if self.data < 0:
            return MyInteger(-self.data)  # 建立一個新的以物件並返回
        return MyInteger(self.data)

    def __len__(self):
        '''len(x)函式規定只能返回整數值,
        因此此方法不能返回字串等其它型別的值'''
        return 100

I1 = MyInteger(-10)
print(I1)   # <-- 此處等同於print(str(I1))
I2 = abs(I1)  # I2 = MyInteger(10)
print(I2)  # MyInteger(10)
print(len(I1))  # I1.__len__()

數值轉換函式重寫

obj.complex() 對應 complex(obj)
obj.int() 對應 int(obj)
obj.float() 對應 float(obj)
obj.bool() 對應 bool(obj)

布林測試函式的重寫

  1. 格式:
    def bool(self):
  2. 作用:
    1. 用於bool(obj)函式取值
    2. 用於if語句真值表達式中
    3. 用於while語句真值表達式中
  3. 說明:
    布測試式方法的查詢順序是 bool方法,其次是len方法
    如果沒有以上方法則返回True
    示例見:
    04_bool.py

迭代器(高階)

什麼是迭代器

可以通過 next(obj) 函式取值的物件,就是迭代器

迭代器協議:

迭代器議是指物件能夠使用next函式獲取下一項資料,在沒有下一項資料時觸發一個StopIteration異常來終止迭代的約定

迭代器協議的實現方法:

  1. 要求:
    在類內需要定義 next(self)方法來實現迭代器協議
  2. 語法形式:

    class MyIterator:
            def __next__(self):
                迭代器協議
                return 資料

什麼是可迭代物件

是指能用iter(obj)函式返回迭代器的物件(例項)
可迭代物件的內部要定義 iter(self)方法來返回迭代器物件

練習:

  1. 完善學生管理系統讀取學生資訊的功能
  2. 看懂類的封裝的用意,及功能的劃分(如:save_to_file(self)方法等)

  3. 寫一個實現迭代器協議的類 Primes 讓此類可以生成從b開始的n個不素數
    class Primes:
    def init(self, b, n):
    ….
    ….
    for x in Primes(10, 4):
    print(x) # 11 13 17 19

    4.擴充套件學生資訊管理程式,試想能否在不改變原Student類的基礎上,為每個學生新增一個家庭住址的資訊
    (提示,用繼承/派生機制建立一個新的類)

  4. 11) 新增修改家庭住址的功能