1. 程式人生 > 實用技巧 >python面向物件--繼承

python面向物件--繼承

一. 繼承的概念

生活中的繼承,一般指的是子女繼承父輩的財產。

  • 拓展1:經典類或舊式類

不由任意內建型別派生出的類,稱之為經典類。

class 類名:
    程式碼
    ......
  • 拓展2:新式類
class 類名(object):
  程式碼

Python面向物件的繼承指的是多個類之間的所屬關係,即子類預設繼承父類的所有屬性和方法,具體如下:

# 父類A
class A(object):
    def __init__(self):
        self.num = 1

    def info_print(self):
        print(self.num)

# 子類B
class B(A):
    pass


result = B()
result.info_print()  # 1

在Python中,所有類預設繼承object類,object類是頂級類或基類;其他子類叫做派生類。

二. 單繼承

故事主線:一個煎餅果子老師傅,在煎餅果子界摸爬滾打多年,研發了一套精湛的攤煎餅果子的技術。師父要把這套技術傳授給他的唯一的最得意的徒弟。

分析:徒弟是不是要繼承師父的所有技術?

# 1. 師父類
class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')

        
# 2. 徒弟類
class Prentice(Master):
    pass


# 3. 建立物件daqiu
daqiu = Prentice()
# 4. 物件訪問例項屬性
print(daqiu.kongfu)
# 5. 物件呼叫例項方法
daqiu.make_cake()

三. 多繼承

故事推進:daqiu是個愛學習的好孩子,想學習更多的煎餅果子技術,於是,在百度搜索到黑馬程式設計師,報班學習煎餅果子技術。

所謂多繼承意思就是一個類同時繼承了多個父類。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


# 建立學校類
class School(object):
    def __init__(self):
        self.kongfu = '[小馬煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class Prentice(School, Master):
    pass


daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()

注意:當一個類有多個父類的時候,預設使用第一個父類的同名屬性和方法。

四. 子類重寫父類同名方法和屬性

故事:daqiu掌握了師父和培訓的技術後,自己潛心鑽研出自己的獨門配方的一套全新的煎餅果子技術。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class School(object):
    def __init__(self):
        self.kongfu = '[小馬煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


# 獨創配方
class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


daqiu = Prentice()
print(daqiu.kongfu)
daqiu.make_cake()

print(Prentice.__mro__)

子類和父類具有同名屬性和方法,預設使用子類的同名屬性和方法。

五. 子類呼叫父類的同名方法和屬性

故事:很多顧客都希望也能吃到古法和小馬的技術的煎餅果子。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class School(object):
    def __init__(self):
        self.kongfu = '[小馬煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子配方]'

    def make_cake(self):
        # 如果是先呼叫了父類的屬性和方法,父類屬性會覆蓋子類屬性,故在呼叫屬性前,先呼叫自己子類的初始化
        self.__init__()
        print(f'運用{self.kongfu}製作煎餅果子')

    # 呼叫父類方法,但是為保證呼叫到的也是父類的屬性,必須在呼叫方法前呼叫父類的初始化
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)


daqiu = Prentice()

daqiu.make_cake()

daqiu.make_master_cake()

daqiu.make_school_cake()

daqiu.make_cake()

六. 多層繼承

故事:N年後,daqiu老了,想要把所有技術傳承給自己的徒弟。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class School(object):
    def __init__(self):
        self.kongfu = '[小馬煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子配方]'

    def make_cake(self):
        self.__init__()
        print(f'運用{self.kongfu}製作煎餅果子')

    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)


# 徒孫類
class Tusun(Prentice):
    pass


xiaoqiu = Tusun()

xiaoqiu.make_cake()

xiaoqiu.make_school_cake()

xiaoqiu.make_master_cake()

七. super()呼叫父類方法

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class School(Master):
    def __init__(self):
        self.kongfu = '[小馬煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')

        # 方法2.1
        # super(School, self).__init__()
        # super(School, self).make_cake()

        # 方法2.2
        super().__init__()
        super().make_cake()


class Prentice(School):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子技術]'

    def make_cake(self):
        self.__init__()
        print(f'運用{self.kongfu}製作煎餅果子')

    # 子類呼叫父類的同名方法和屬性:把父類的同名屬性和方法再次封裝
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)

    # 一次性呼叫父類的同名屬性和方法
    def make_old_cake(self):
        # 方法一:程式碼冗餘;父類類名如果變化,這裡程式碼需要頻繁修改
        # Master.__init__(self)
        # Master.make_cake(self)
        # School.__init__(self)
        # School.make_cake(self)

        # 方法二: super()
        # 方法2.1 super(當前類名, self).函式()
        # super(Prentice, self).__init__()
        # super(Prentice, self).make_cake()

        # 方法2.2 super().函式()
        super().__init__()
        super().make_cake()


daqiu = Prentice()

daqiu.make_old_cake()

注意:使用super() 可以自動查詢父類。呼叫順序遵循 __mro__ 類屬性的順序。比較適合單繼承使用。

八. 私有許可權

8.1 定義私有屬性和方法

在Python中,可以為例項屬性和方法設定私有許可權,即設定某個例項屬性或例項方法不繼承給子類。

故事:daqiu把技術傳承給徒弟的同時,不想把自己的錢(2000000個億)繼承給徒弟,這個時候就要為這個例項屬性設定私有許可權。

設定私有許可權的方法:在屬性名和方法名 前面 加上兩個下劃線 __。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class School(object):
    def __init__(self):
        self.kongfu = '[小馬煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子配方]'
        # 定義私有屬性
        self.__money = 2000000

    # 定義私有方法
    def __info_print(self):
        print(self.kongfu)
        print(self.__money)

    def make_cake(self):
        self.__init__()
        print(f'運用{self.kongfu}製作煎餅果子')

    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)


# 徒孫類
class Tusun(Prentice):
    pass


daqiu = Prentice()
# 物件不能訪問私有屬性和私有方法
# print(daqiu.__money)
# daqiu.__info_print()

xiaoqiu = Tusun()
# 子類無法繼承父類的私有屬性和私有方法
# print(xiaoqiu.__money)  # 無法訪問例項屬性__money
# xiaoqiu.__info_print()

注意:私有屬性和私有方法只能在類裡面訪問和修改。

8.2 獲取和修改私有屬性值

在Python中,一般定義函式名get_xx用來獲取私有屬性,定義set_xx用來修改私有屬性值。

class Master(object):
    def __init__(self):
        self.kongfu = '[古法煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class School(object):
    def __init__(self):
        self.kongfu = '[小馬煎餅果子配方]'

    def make_cake(self):
        print(f'運用{self.kongfu}製作煎餅果子')


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨創煎餅果子配方]'
        self.__money = 2000000

    # 獲取私有屬性
    def get_money(self):
        return self.__money

    # 修改私有屬性
    def set_money(self):
        self.__money = 500

    def __info_print(self):
        print(self.kongfu)
        print(self.__money)

    def make_cake(self):
        self.__init__()
        print(f'運用{self.kongfu}製作煎餅果子')

    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

    def make_school_cake(self):
        School.__init__(self)
        School.make_cake(self)


# 徒孫類
class Tusun(Prentice):
    pass


daqiu = Prentice()

xiaoqiu = Tusun()
# 呼叫get_money函式獲取私有屬性money的值
print(xiaoqiu.get_money())
# 呼叫set_money函式修改私有屬性money的值
xiaoqiu.set_money()
print(xiaoqiu.get_money())

九. 總結

  • 繼承的特點

    • 子類預設擁有父類的所有屬性和方法
    • 子類重寫父類同名方法和屬性
    • 子類呼叫父類同名方法和屬性
  • super()方法快速呼叫父類方法

  • 私有許可權

    • 不能繼承給子類的屬性和方法需要新增私有許可權
    • 語法
    class 類名():
      # 私有屬性
      __屬性名 = 值
    
      # 私有方法
      def __函式名(self):
        程式碼