面向?qū)ο?/h1>

面向?qū)ο蠡A(chǔ)

目標(biāo)

  • 理解面向?qū)ο?/li>
  • 類(lèi)和對(duì)象
  • 添加和獲取對(duì)象屬性
  • 魔法方法

一. 理解面向?qū)ο?/h1>

面向?qū)ο笫且环N抽象化的編程思想,很多編程語(yǔ)言中都有的一種思想。

例如:洗衣服

思考:幾種途徑可以完成洗衣服铆农?

答: 手洗 和 機(jī)洗。

手洗:找盆 - 放水 - 加洗衣粉 - 浸泡 - 搓洗 - 擰干水 - 倒水 - 漂洗N次 - 擰干 - 晾曬。

機(jī)洗:打開(kāi)洗衣機(jī) - 放衣服 - 加洗衣粉 - 按下開(kāi)始按鈕 - 晾曬刃唐。

對(duì)比兩種洗衣服途徑,機(jī)洗更簡(jiǎn)單

思考:機(jī)洗袭景,只需要找到一臺(tái)洗衣機(jī)唁桩,加入簡(jiǎn)單操作就可以完成洗衣服的工作,而不需要關(guān)心洗衣機(jī)內(nèi)部發(fā)生了什么事情耸棒。

總結(jié):面向?qū)ο缶褪菍⒕幊坍?dāng)成是一個(gè)事物荒澡,對(duì)外界來(lái)說(shuō),事物是直接使用的与殃,不用去管他內(nèi)部的情況单山。而編程就是設(shè)置事物能夠做什么事碍现。

二. 類(lèi)和對(duì)象

思考:洗衣機(jī)洗衣服描述過(guò)程中,洗衣機(jī)其實(shí)就是一個(gè)事物米奸,即對(duì)象昼接,洗衣機(jī)對(duì)象哪來(lái)的呢?

答:洗衣機(jī)是由工廠工人制作出來(lái)悴晰。

思考:工廠工人怎么制作出的洗衣機(jī)慢睡?

答:工人根據(jù)設(shè)計(jì)師設(shè)計(jì)的功能圖紙制作洗衣機(jī)。

總結(jié):圖紙 → 洗衣機(jī) → 洗衣服铡溪。

在面向?qū)ο缶幊踢^(guò)程中漂辐,有兩個(gè)重要組成部分:類(lèi)和對(duì)象。

類(lèi)和對(duì)象的關(guān)系:用類(lèi)去創(chuàng)建一個(gè)對(duì)象棕硫。

2.1 理解類(lèi)和對(duì)象

2.1.1 類(lèi)

類(lèi)是對(duì)一系列具有相同特征和行為的事物的統(tǒng)稱(chēng)髓涯,是一個(gè)抽象的概念,不是真實(shí)存在的事物哈扮。

  • 特征即是屬性
  • 行為即是方法

類(lèi)比如是制造洗衣機(jī)時(shí)要用到的圖紙纬纪,也就是說(shuō)類(lèi)是用來(lái)創(chuàng)建對(duì)象。


2.1.2 對(duì)象

對(duì)象是類(lèi)創(chuàng)建出來(lái)的真實(shí)存在的事物滑肉,例如:洗衣機(jī)包各。

注意:開(kāi)發(fā)中,先有類(lèi)赦邻,再有對(duì)象髓棋。

2.2 面向?qū)ο髮?shí)現(xiàn)方法

2.2.1 定義類(lèi)

Python2中類(lèi)分為:經(jīng)典類(lèi) 和 新式類(lèi)

  • 語(yǔ)法
class 類(lèi)名():
    代碼
    ......

注意:類(lèi)名要滿(mǎn)足標(biāo)識(shí)符命名規(guī)則,同時(shí)遵循大駝峰命名習(xí)慣惶洲。

  • 體驗(yàn)
class Washer():
    def wash(self):
        print('我會(huì)洗衣服')
  • 拓展:經(jīng)典類(lèi)

不由任意內(nèi)置類(lèi)型派生出的類(lèi)按声,稱(chēng)之為經(jīng)典類(lèi)

class 類(lèi)名:
    代碼
    ......

2.2.2 創(chuàng)建對(duì)象

對(duì)象又名實(shí)例。

  • 語(yǔ)法
對(duì)象名 = 類(lèi)名()
  • 體驗(yàn)
# 創(chuàng)建對(duì)象
haier1 = Washer()

# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)

# haier對(duì)象調(diào)用實(shí)例方法
haier1.wash()

注意:創(chuàng)建對(duì)象的過(guò)程也叫實(shí)例化對(duì)象恬吕。

2.2.3 self

self指的是調(diào)用該函數(shù)的對(duì)象签则。

# 1. 定義類(lèi)
class Washer():
    def wash(self):
        print('我會(huì)洗衣服')
        # <__main__.Washer object at 0x0000024BA2B34240>
        print(self)


# 2. 創(chuàng)建對(duì)象
haier1 = Washer()
# <__main__.Washer object at 0x0000018B7B224240>
print(haier1)
# haier1對(duì)象調(diào)用實(shí)例方法
haier1.wash()


haier2 = Washer()
# <__main__.Washer object at 0x0000022005857EF0>
print(haier2)

注意:打印對(duì)象和self得到的結(jié)果是一致的,都是當(dāng)前對(duì)象的內(nèi)存中存儲(chǔ)地址铐料。

三. 添加和獲取對(duì)象屬性

屬性即是特征渐裂,比如:洗衣機(jī)的寬度、高度钠惩、重量...

對(duì)象屬性既可以在類(lèi)外面添加和獲取柒凉,也能在類(lèi)里面添加和獲取。

3.1 類(lèi)外面添加對(duì)象屬性

  • 語(yǔ)法
對(duì)象名.屬性名 = 值
  • 體驗(yàn)
haier1.width = 500
haier1.height = 800

3.2 類(lèi)外面獲取對(duì)象屬性

  • 語(yǔ)法
對(duì)象名.屬性名
  • 體驗(yàn)
print(f'haier1洗衣機(jī)的寬度是{haier1.width}')
print(f'haier1洗衣機(jī)的高度是{haier1.height}')

3.3 類(lèi)里面獲取對(duì)象屬性

  • 語(yǔ)法
self.屬性名
  • 體驗(yàn)
# 定義類(lèi)
class Washer():
    def print_info(self):
        # 類(lèi)里面獲取實(shí)例屬性
        print(f'haier1洗衣機(jī)的寬度是{self.width}')
        print(f'haier1洗衣機(jī)的高度是{self.height}')

# 創(chuàng)建對(duì)象
haier1 = Washer()

# 添加實(shí)例屬性
haier1.width = 500
haier1.height = 800

haier1.print_info()

四. 魔法方法

在Python中篓跛,__xx__()的函數(shù)叫做魔法方法膝捞,指的是具有特殊功能的函數(shù)。

4.1 __init__()

4.1.1 體驗(yàn)__init__()

思考:洗衣機(jī)的寬度高度是與生俱來(lái)的屬性愧沟,可不可以在生產(chǎn)過(guò)程中就賦予這些屬性呢蔬咬?

答:理應(yīng)如此鲤遥。

==__init__()方法的作用:初始化對(duì)象。==

class Washer():
    
    # 定義初始化功能的函數(shù)
    def __init__(self):
        # 添加實(shí)例屬性
        self.width = 500
        self.height = 800


    def print_info(self):
        # 類(lèi)里面調(diào)用實(shí)例屬性
        print(f'洗衣機(jī)的寬度是{self.width}, 高度是{self.height}')


haier1 = Washer()
haier1.print_info()

注意:

  • __init__()方法林艘,在創(chuàng)建一個(gè)對(duì)象時(shí)默認(rèn)被調(diào)用盖奈,不需要手動(dòng)調(diào)用
  • __init__(self)中的self參數(shù),不需要開(kāi)發(fā)者傳遞狐援,python解釋器會(huì)自動(dòng)把當(dāng)前的對(duì)象引用傳遞過(guò)去钢坦。

4.1.2 帶參數(shù)的__init__()

思考:一個(gè)類(lèi)可以創(chuàng)建多個(gè)對(duì)象,如何對(duì)不同的對(duì)象設(shè)置不同的初始化屬性呢啥酱?

答:傳參數(shù)场钉。

class Washer():
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def print_info(self):
        print(f'洗衣機(jī)的寬度是{self.width}')
        print(f'洗衣機(jī)的高度是{self.height}')


haier1 = Washer(10, 20)
haier1.print_info()


haier2 = Washer(30, 40)
haier2.print_info()

4.2 __str__()

當(dāng)使用print輸出對(duì)象的時(shí)候,默認(rèn)打印對(duì)象的內(nèi)存地址懈涛。如果類(lèi)定義了__str__方法,那么就會(huì)打印在這個(gè)方法中 return 的數(shù)據(jù)泳猬。

class Washer():
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def __str__(self):
        return '這是海爾洗衣機(jī)的說(shuō)明書(shū)'


haier1 = Washer(10, 20)
# 這是海爾洗衣機(jī)的說(shuō)明書(shū)
print(haier1)

4.3 __del__()

當(dāng)刪除對(duì)象時(shí)批钠,python解釋器也會(huì)默認(rèn)調(diào)用__del__()方法。

class Washer():
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def __del__(self):
        print(f'{self}對(duì)象已經(jīng)被刪除')


haier1 = Washer(10, 20)

# <__main__.Washer object at 0x0000026118223278>對(duì)象已經(jīng)被刪除
del haier1

五. 綜合應(yīng)用

5.1 烤地瓜

5.1.1 需求

需求主線:

  1. 被烤的時(shí)間和對(duì)應(yīng)的地瓜狀態(tài):

    0-3分鐘:生的

    3-5分鐘:半生不熟

    5-8分鐘:熟的

    超過(guò)8分鐘:烤糊了

  1. 添加的調(diào)料:

    用戶(hù)可以按自己的意愿添加調(diào)料

5.1.2 步驟分析

需求涉及一個(gè)事物: 地瓜得封,故案例涉及一個(gè)類(lèi):地瓜類(lèi)埋心。

5.1.2.1 定義類(lèi)

  • 地瓜的屬性

    • 被烤的時(shí)間
    • 地瓜的狀態(tài)
    • 添加的調(diào)料
  • 地瓜的方法

    • 被烤
      • 用戶(hù)根據(jù)意愿設(shè)定每次烤地瓜的時(shí)間
      • 判斷地瓜被烤的總時(shí)間是在哪個(gè)區(qū)間,修改地瓜狀態(tài)
    • 添加調(diào)料
      • 用戶(hù)根據(jù)意愿設(shè)定添加的調(diào)料
      • 將用戶(hù)添加的調(diào)料存儲(chǔ)
  • 顯示對(duì)象信息

5.1.2.2 創(chuàng)建對(duì)象忙上,調(diào)用相關(guān)實(shí)例方法

5.1.3 代碼實(shí)現(xiàn)

5.1.3.1 定義類(lèi)

  • 地瓜屬性
    • 定義地瓜初始化屬性拷呆,后期根據(jù)程序推進(jìn)更新實(shí)例屬性
class SweetPotato():
    def __init__(self):
        # 被烤的時(shí)間
        self.cook_time = 0
        # 地瓜的狀態(tài)
        self.cook_static = '生的'
        # 調(diào)料列表
        self.condiments = []

5.1.3.2 定義烤地瓜方法

class SweetPotato():
    ......
    
    def cook(self, time):
        """烤地瓜的方法"""
        self.cook_time += time
        if 0 <= self.cook_time < 3:
            self.cook_static = '生的'
        elif 3 <= self.cook_time < 5:
            self.cook_static = '半生不熟'
        elif 5 <= self.cook_time < 8:
            self.cook_static = '熟了'
        elif self.cook_time >= 8:
            self.cook_static = '烤糊了'

5.1.3.3 書(shū)寫(xiě)str魔法方法,用于輸出對(duì)象狀態(tài)

class SweetPotato():
        ......

    def __str__(self):
        return f'這個(gè)地瓜烤了{(lán)self.cook_time}分鐘, 狀態(tài)是{self.cook_static}'

5.1.3.4 創(chuàng)建對(duì)象疫粥,測(cè)試實(shí)例屬性和實(shí)例方法

digua1 = SweetPotato()
print(digua1)
digua1.cook(2)
print(digua1)

5.1.3.5 定義添加調(diào)料方法茬斧,并調(diào)用該實(shí)例方法

class SweetPotato():
        ......

    def add_condiments(self, condiment):
        """添加調(diào)料"""
        self.condiments.append(condiment)
    def __str__(self):
        return f'這個(gè)地瓜烤了{(lán)self.cook_time}分鐘, 狀態(tài)是{self.cook_static}, 添加的調(diào)料有{self.condiments}'
      

digua1 = SweetPotato()
print(digua1)

digua1.cook(2)
digua1.add_condiments('醬油')
print(digua1)

digua1.cook(2)
digua1.add_condiments('辣椒面兒')
print(digua1)

digua1.cook(2)
print(digua1)

digua1.cook(2)
print(digua1)

5.1.4 代碼總覽

# 定義類(lèi)
class SweetPotato():
    def __init__(self):
        # 被烤的時(shí)間
        self.cook_time = 0
        # 地瓜的狀態(tài)
        self.cook_static = '生的'
        # 調(diào)料列表
        self.condiments = []

    def cook(self, time):
        """烤地瓜的方法"""
        self.cook_time += time
        if 0 <= self.cook_time < 3:
            self.cook_static = '生的'
        elif 3 <= self.cook_time < 5:
            self.cook_static = '半生不熟'
        elif 5 <= self.cook_time < 8:
            self.cook_static = '熟了'
        elif self.cook_time >= 8:
            self.cook_static = '烤糊了'

    def add_condiments(self, condiment):
        """添加調(diào)料"""
        self.condiments.append(condiment)

    def __str__(self):
        return f'這個(gè)地瓜烤了{(lán)self.cook_time}分鐘, 狀態(tài)是{self.cook_static}, 添加的調(diào)料有{self.condiments}'


digua1 = SweetPotato()
print(digua1)

digua1.cook(2)
digua1.add_condiments('醬油')
print(digua1)

digua1.cook(2)
digua1.add_condiments('辣椒面兒')
print(digua1)

digua1.cook(2)
print(digua1)

digua1.cook(2)
print(digua1)

5.2 搬家具

5.2.1 需求

將小于房子剩余面積的家具擺放到房子中

5.2.2 步驟分析

需求涉及兩個(gè)事物:房子 和 家具,故被案例涉及兩個(gè)類(lèi):房子類(lèi) 和 家具類(lèi)梗逮。

5.2.2.1 定義類(lèi)

  • 房子類(lèi)
    • 實(shí)例屬性
      • 房子地理位置
      • 房子占地面積
      • 房子剩余面積
      • 房子內(nèi)家具列表
    • 實(shí)例方法
      • 容納家具
    • 顯示房屋信息
  • 家具類(lèi)
    • 家具名稱(chēng)
    • 家具占地面積

5.2.2.2 創(chuàng)建對(duì)象并調(diào)用相關(guān)方法

5.2.3 代碼實(shí)現(xiàn)

5.2.3.1 定義類(lèi)

  • 家具類(lèi)
class Furniture():
    def __init__(self, name, area):
        # 家具名字
        self.name = name
        # 家具占地面積
        self.area = area
  • 房子類(lèi)

class Home():
    def __init__(self, address, area):
        # 地理位置
        self.address = address
        # 房屋面積
        self.area = area
        # 剩余面積
        self.free_area = area
        # 家具列表
        self.furniture = []

    def __str__(self):
        return f'房子坐落于{self.address}, 占地面積{self.area}, 剩余面積{self.free_area}, 家具有{self.furniture}'

    def add_furniture(self, item):
        """容納家具"""
        if self.free_area >= item.area:
            self.furniture.append(item.name)
            # 家具搬入后项秉,房屋剩余面積 = 之前剩余面積 - 該家具面積
            self.free_area -= item.area
        else:
            print('家具太大,剩余面積不足慷彤,無(wú)法容納')

5.2.3.2 創(chuàng)建對(duì)象并調(diào)用實(shí)例屬性和方法

bed = Furniture('雙人床', 6)
jia1 = Home('北京', 1200)
print(jia1)

jia1.add_furniture(bed)
print(jia1)

sofa = Furniture('沙發(fā)', 10)
jia1.add_furniture(sofa)
print(jia1)

ball = Furniture('籃球場(chǎng)', 1500)
jia1.add_furniture(ball)
print(jia1)

六. 總結(jié)

  • 面向?qū)ο笾匾M成部分

    • 類(lèi)
      • 創(chuàng)建類(lèi)
    class 類(lèi)名():
      代碼
    
    • 對(duì)象
    對(duì)象名 = 類(lèi)名()
    
  • 添加對(duì)象屬性

    • 類(lèi)外面
    對(duì)象名.屬性名 = 值
    
    • 類(lèi)里面
    self.屬性名 = 值
    
  • 獲取對(duì)象屬性

    • 類(lèi)外面
    對(duì)象名.屬性名
    
    • 類(lèi)里面
    self.屬性名
    
  • 魔法方法

    • __init__(): 初始化
    • __str__():輸出對(duì)象信息
    • __del__():刪除對(duì)象時(shí)調(diào)用

繼承

目標(biāo)

  • 繼承的概念
  • 單繼承
  • 多繼承
  • 子類(lèi)重寫(xiě)父類(lèi)的同名屬性和方法
  • 子類(lèi)調(diào)用父類(lèi)的同名屬性和方法
  • 多層繼承
  • super()
  • 私有屬性和私有方法

一. 繼承的概念

生活中的繼承娄蔼,一般指的是子女繼承父輩的財(cái)產(chǎn)。

  • 拓展1:經(jīng)典類(lèi)或舊式類(lèi)

不由任意內(nèi)置類(lèi)型派生出的類(lèi)底哗,稱(chēng)之為經(jīng)典類(lèi)岁诉。

class 類(lèi)名:
    代碼
    ......
  • 拓展2:新式類(lèi)
class 類(lèi)名(object):
  代碼

Python面向?qū)ο蟮睦^承指的是多個(gè)類(lèi)之間的所屬關(guān)系,即子類(lèi)默認(rèn)繼承父類(lèi)的所有屬性和方法跋选,具體如下:

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

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

# 子類(lèi)B
class B(A):
    pass


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

在Python中涕癣,所有類(lèi)默認(rèn)繼承object類(lèi),object類(lèi)是頂級(jí)類(lèi)或基類(lèi)野建;其他子類(lèi)叫做派生類(lèi)属划。

二. 單繼承

故事主線:一個(gè)煎餅果子老師傅恬叹,在煎餅果子界摸爬滾打多年,研發(fā)了一套精湛的攤煎餅果子的技術(shù)同眯。師父要把這套技術(shù)傳授給他的唯一的最得意的徒弟绽昼。

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

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

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

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


# 3. 創(chuàng)建對(duì)象daqiu
daqiu = Prentice()
# 4. 對(duì)象訪問(wèn)實(shí)例屬性
print(daqiu.kongfu)
# 5. 對(duì)象調(diào)用實(shí)例方法
daqiu.make_cake()

三. 多繼承

故事推進(jìn):daqiu是個(gè)愛(ài)學(xué)習(xí)的好孩子须蜗,想學(xué)習(xí)更多的煎餅果子技術(shù)硅确,于是,在百度搜索到學(xué)習(xí)煎餅果子技術(shù)明肮。

所謂多繼承意思就是一個(gè)類(lèi)同時(shí)繼承了多個(gè)父類(lèi)菱农。

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

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


# 創(chuàng)建學(xué)校類(lèi)
class School(object):
    def __init__(self):
        self.kongfu = '[新煎餅果子配方]'

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


class Prentice(School, Master):
    pass


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

注意:當(dāng)一個(gè)類(lèi)有多個(gè)父類(lèi)的時(shí)候,默認(rèn)使用第一個(gè)父類(lèi)的同名屬性和方法柿估。

四. 子類(lèi)重寫(xiě)父類(lèi)同名方法和屬性

故事:daqiu掌握了師父和培訓(xùn)的技術(shù)后循未,自己潛心鉆研出自己的獨(dú)門(mén)配方的一套全新的煎餅果子技術(shù)。

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

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


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

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


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

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


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

print(Prentice.__mro__)

子類(lèi)和父類(lèi)具有同名屬性和方法秫舌,默認(rèn)使用子類(lèi)的同名屬性和方法的妖。

五. 子類(lèi)調(diào)用父類(lèi)的同名方法和屬性

故事:很多顧客都希望也能吃到古法和新技術(shù)的煎餅果子。

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

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


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

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


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

    def make_cake(self):
        # 如果是先調(diào)用了父類(lèi)的屬性和方法足陨,父類(lèi)屬性會(huì)覆蓋子類(lèi)屬性嫂粟,故在調(diào)用屬性前,先調(diào)用自己子類(lèi)的初始化
        self.__init__()
        print(f'運(yùn)用{self.kongfu}制作煎餅果子')

    # 調(diào)用父類(lèi)方法墨缘,但是為保證調(diào)用到的也是父類(lèi)的屬性星虹,必須在調(diào)用方法前調(diào)用父類(lèi)的初始化
    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老了镊讼,想要把所有技術(shù)傳承給自己的徒弟宽涌。

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

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


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

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


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

    def make_cake(self):
        self.__init__()
        print(f'運(yùn)用{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)


# 徒孫類(lèi)
class Tusun(Prentice):
    pass


xiaoqiu = Tusun()

xiaoqiu.make_cake()

xiaoqiu.make_school_cake()

xiaoqiu.make_master_cake()

七. super()調(diào)用父類(lèi)方法

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

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


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

    def make_cake(self):
        print(f'運(yùn)用{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 = '[獨(dú)創(chuàng)煎餅果子技術(shù)]'

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

    # 子類(lèi)調(diào)用父類(lèi)的同名方法和屬性:把父類(lèi)的同名屬性和方法再次封裝
    def make_master_cake(self):
        Master.__init__(self)
        Master.make_cake(self)

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

    # 一次性調(diào)用父類(lèi)的同名屬性和方法
    def make_old_cake(self):
        # 方法一:代碼冗余;父類(lèi)類(lèi)名如果變化蝶棋,這里代碼需要頻繁修改
        # Master.__init__(self)
        # Master.make_cake(self)
        # School.__init__(self)
        # School.make_cake(self)

        # 方法二: super()
        # 方法2.1 super(當(dāng)前類(lèi)名, self).函數(shù)()
        # super(Prentice, self).__init__()
        # super(Prentice, self).make_cake()

        # 方法2.2 super().函數(shù)()
        super().__init__()
        super().make_cake()


daqiu = Prentice()

daqiu.make_old_cake()

注意:使用super() 可以自動(dòng)查找父類(lèi)护糖。調(diào)用順序遵循 __mro__ 類(lèi)屬性的順序。比較適合單繼承使用嚼松。

八. 私有權(quán)限

8.1 定義私有屬性和方法

在Python中嫡良,可以為實(shí)例屬性和方法設(shè)置私有權(quán)限,即設(shè)置某個(gè)實(shí)例屬性或?qū)嵗椒ú焕^承給子類(lèi)献酗。

故事:daqiu把技術(shù)傳承給徒弟的同時(shí)寝受,不想把自己的錢(qián)(2000000個(gè)億)繼承給徒弟,這個(gè)時(shí)候就要為錢(qián)這個(gè)實(shí)例屬性設(shè)置私有權(quán)限罕偎。

設(shè)置私有權(quán)限的方法:在屬性名和方法名 前面 加上兩個(gè)下劃線 __很澄。

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

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


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

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


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

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

    def make_cake(self):
        self.__init__()
        print(f'運(yùn)用{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)


# 徒孫類(lèi)
class Tusun(Prentice):
    pass


daqiu = Prentice()
# 對(duì)象不能訪問(wèn)私有屬性和私有方法
# print(daqiu.__money)
# daqiu.__info_print()

xiaoqiu = Tusun()
# 子類(lèi)無(wú)法繼承父類(lèi)的私有屬性和私有方法
# print(xiaoqiu.__money)  # 無(wú)法訪問(wèn)實(shí)例屬性__money
# xiaoqiu.__info_print()

注意:私有屬性和私有方法只能在類(lèi)里面訪問(wèn)和修改。

8.2 獲取和修改私有屬性值

在Python中,一般定義函數(shù)名get_xx用來(lái)獲取私有屬性甩苛,定義set_xx用來(lái)修改私有屬性值蹂楣。

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

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


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

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


class Prentice(School, Master):
    def __init__(self):
        self.kongfu = '[獨(dú)創(chuàng)煎餅果子配方]'
        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'運(yùn)用{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)


# 徒孫類(lèi)
class Tusun(Prentice):
    pass


daqiu = Prentice()

xiaoqiu = Tusun()
# 調(diào)用get_money函數(shù)獲取私有屬性money的值
print(xiaoqiu.get_money())
# 調(diào)用set_money函數(shù)修改私有屬性money的值
xiaoqiu.set_money()
print(xiaoqiu.get_money())

九. 總結(jié)

  • 繼承的特點(diǎn)

    • 子類(lèi)默認(rèn)擁有父類(lèi)的所有屬性和方法
    • 子類(lèi)重寫(xiě)父類(lèi)同名方法和屬性
    • 子類(lèi)調(diào)用父類(lèi)同名方法和屬性
  • super()方法快速調(diào)用父類(lèi)方法

  • 私有權(quán)限

    • 不能繼承給子類(lèi)的屬性和方法需要添加私有權(quán)限
    • 語(yǔ)法
    class 類(lèi)名():
      # 私有屬性
      __屬性名 = 值
    
      # 私有方法
      def __函數(shù)名(self):
        代碼
    

    課程:面向?qū)ο?其他

目標(biāo)

  • 面向?qū)ο笕筇匦?/li>
  • 類(lèi)屬性和實(shí)例屬性
  • 類(lèi)方法和靜態(tài)方法

一. 面向?qū)ο笕筇匦?/h1>
  • 封裝
    • 將屬性和方法書(shū)寫(xiě)到類(lèi)的里面的操作即為封裝
    • 封裝可以為屬性和方法添加私有權(quán)限
  • 繼承
    • 子類(lèi)默認(rèn)繼承父類(lèi)的所有屬性和方法
    • 子類(lèi)可以重寫(xiě)父類(lèi)屬性和方法
  • 多態(tài)
    • 傳入不同的對(duì)象,產(chǎn)生不同的結(jié)果

二. 多態(tài)

2.1 了解多態(tài)

多態(tài)指的是一類(lèi)事物有多種形態(tài)讯蒲,(一個(gè)抽象類(lèi)有多個(gè)子類(lèi)痊土,因而多態(tài)的概念依賴(lài)于繼承)。

  • 定義:多態(tài)是一種使用對(duì)象的方式墨林,子類(lèi)重寫(xiě)父類(lèi)方法赁酝,調(diào)用不同子類(lèi)對(duì)象的相同父類(lèi)方法,可以產(chǎn)生不同的執(zhí)行結(jié)果
  • 好處:調(diào)用靈活旭等,有了多態(tài)酌呆,更容易編寫(xiě)出通用的代碼,做出通用的編程搔耕,以適應(yīng)需求的不斷變化隙袁!
  • 實(shí)現(xiàn)步驟:
    • 定義父類(lèi),并提供公共方法
    • 定義子類(lèi)弃榨,并重寫(xiě)父類(lèi)方法
    • 傳遞子類(lèi)對(duì)象給調(diào)用者藤乙,可以看到不同子類(lèi)執(zhí)行效果不同

2.2 體驗(yàn)多態(tài)

class Dog(object):
    def work(self):  # 父類(lèi)提供統(tǒng)一的方法,哪怕是空方法
        print('指哪打哪...')


class ArmyDog(Dog):  # 繼承Dog類(lèi)
    def work(self):  # 子類(lèi)重寫(xiě)父類(lèi)同名方法
        print('追擊敵人...')


class DrugDog(Dog):
    def work(self):
        print('追查毒品...')


class Person(object):
    def work_with_dog(self, dog):  # 傳入不同的對(duì)象惭墓,執(zhí)行不同的代碼,即不同的work函數(shù)
        dog.work()


ad = ArmyDog()
dd = DrugDog()

daqiu = Person()
daqiu.work_with_dog(ad)
daqiu.work_with_dog(dd)

三. 類(lèi)屬性和實(shí)例屬性

3.1 類(lèi)屬性

3.1.1 設(shè)置和訪問(wèn)類(lèi)屬性

  • 類(lèi)屬性就是 類(lèi)對(duì)象 所擁有的屬性而姐,它被 該類(lèi)的所有實(shí)例對(duì)象 所共有腊凶。
  • 類(lèi)屬性可以使用 類(lèi)對(duì)象實(shí)例對(duì)象 訪問(wèn)。
class Dog(object):
    tooth = 10


wangcai = Dog()
xiaohei = Dog()

print(Dog.tooth)  # 10
print(wangcai.tooth)  # 10
print(xiaohei.tooth)  # 10

類(lèi)屬性的優(yōu)點(diǎn)

  • 記錄的某項(xiàng)數(shù)據(jù) 始終保持一致時(shí)拴念,則定義類(lèi)屬性钧萍。
  • 實(shí)例屬性 要求 每個(gè)對(duì)象 為其 單獨(dú)開(kāi)辟一份內(nèi)存空間 來(lái)記錄數(shù)據(jù),而 類(lèi)屬性 為全類(lèi)所共有 政鼠,僅占用一份內(nèi)存风瘦,更加節(jié)省內(nèi)存空間

3.1.2 修改類(lèi)屬性

類(lèi)屬性只能通過(guò)類(lèi)對(duì)象修改公般,不能通過(guò)實(shí)例對(duì)象修改万搔,如果通過(guò)實(shí)例對(duì)象修改類(lèi)屬性,表示的是創(chuàng)建了一個(gè)實(shí)例屬性官帘。

class Dog(object):
    tooth = 10


wangcai = Dog()
xiaohei = Dog()

# 修改類(lèi)屬性
Dog.tooth = 12
print(Dog.tooth)  # 12
print(wangcai.tooth)  # 12
print(xiaohei.tooth)  # 12

# 不能通過(guò)對(duì)象修改屬性瞬雹,如果這樣操作,實(shí)則是創(chuàng)建了一個(gè)實(shí)例屬性
wangcai.tooth = 20
print(Dog.tooth)  # 12
print(wangcai.tooth)  # 20
print(xiaohei.tooth)  # 12

3.2 實(shí)例屬性

class Dog(object):
    def __init__(self):
        self.age = 5

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


wangcai = Dog()
print(wangcai.age)  # 5
# print(Dog.age)  # 報(bào)錯(cuò):實(shí)例屬性不能通過(guò)類(lèi)訪問(wèn)
wangcai.info_print()  # 5

四. 類(lèi)方法和靜態(tài)方法

4.1 類(lèi)方法

4.1.1 類(lèi)方法特點(diǎn)

  • 需要用裝飾器@classmethod來(lái)標(biāo)識(shí)其為類(lèi)方法刽虹,對(duì)于類(lèi)方法酗捌,第一個(gè)參數(shù)必須是類(lèi)對(duì)象,一般以cls作為第一個(gè)參數(shù)。

4.1.2 類(lèi)方法使用場(chǎng)景

  • 當(dāng)方法中 需要使用類(lèi)對(duì)象 (如訪問(wèn)私有類(lèi)屬性等)時(shí)胖缤,定義類(lèi)方法
  • 類(lèi)方法一般和類(lèi)屬性配合使用
class Dog(object):
    __tooth = 10

    @classmethod
    def get_tooth(cls):
        return cls.__tooth


wangcai = Dog()
result = wangcai.get_tooth()
print(result)  # 10

4.2 靜態(tài)方法

4.2.1 靜態(tài)方法特點(diǎn)

  • 需要通過(guò)裝飾器@staticmethod來(lái)進(jìn)行修飾尚镰,靜態(tài)方法既不需要傳遞類(lèi)對(duì)象也不需要傳遞實(shí)例對(duì)象(形參沒(méi)有self/cls)
  • 靜態(tài)方法 也能夠通過(guò) 實(shí)例對(duì)象類(lèi)對(duì)象 去訪問(wèn)哪廓。

4.2.2 靜態(tài)方法使用場(chǎng)景

  • 當(dāng)方法中 既不需要使用實(shí)例對(duì)象(如實(shí)例對(duì)象狗唉,實(shí)例屬性),也不需要使用類(lèi)對(duì)象 (如類(lèi)屬性撩独、類(lèi)方法敞曹、創(chuàng)建實(shí)例等)時(shí),定義靜態(tài)方法
  • 取消不需要的參數(shù)傳遞综膀,有利于 減少不必要的內(nèi)存占用和性能消耗
class Dog(object):
    @staticmethod
    def info_print():
        print('這是一個(gè)狗類(lèi)澳迫,用于創(chuàng)建狗實(shí)例....')


wangcai = Dog()
# 靜態(tài)方法既可以使用對(duì)象訪問(wèn)又可以使用類(lèi)訪問(wèn)
wangcai.info_print()
Dog.info_print()

五. 總結(jié)

  • 面向?qū)ο笕筇匦?
    • 封裝
    • 繼承
    • 多態(tài)
  • 類(lèi)屬性
    • 歸屬于類(lèi)對(duì)象的屬性,所有對(duì)象共有的屬性
  • 實(shí)例屬性
  • 類(lèi)方法
@classmethod
def xx():
  代碼
  • 靜態(tài)方法
@staticmethod
def xx():
  代碼
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者

  • 序言:七十年代末剧劝,一起剝皮案震驚了整個(gè)濱河市橄登,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌讥此,老刑警劉巖拢锹,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異萄喳,居然都是意外死亡卒稳,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)他巨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)充坑,“玉大人,你說(shuō)我怎么就攤上這事染突∧硪” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵份企,是天一觀的道長(zhǎng)也榄。 經(jīng)常有香客問(wèn)我,道長(zhǎng)司志,這世上最難降的妖魔是什么甜紫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮骂远,結(jié)果婚禮上棵介,老公的妹妹穿的比我還像新娘。我一直安慰自己吧史,他們只是感情好邮辽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布唠雕。 她就那樣靜靜地躺著,像睡著了一般吨述。 火紅的嫁衣襯著肌膚如雪岩睁。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,541評(píng)論 1 305
  • 那天揣云,我揣著相機(jī)與錄音捕儒,去河邊找鬼。 笑死邓夕,一個(gè)胖子當(dāng)著我的面吹牛刘莹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播焚刚,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼点弯,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了矿咕?” 一聲冷哼從身側(cè)響起抢肛,我...
    開(kāi)封第一講書(shū)人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎碳柱,沒(méi)想到半個(gè)月后捡絮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡莲镣,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年福稳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瑞侮。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡的圆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出区岗,到底是詐尸還是另有隱情,我是刑警寧澤毁枯,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布慈缔,位于F島的核電站,受9級(jí)特大地震影響种玛,放射性物質(zhì)發(fā)生泄漏藐鹤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一赂韵、第九天 我趴在偏房一處隱蔽的房頂上張望娱节。 院中可真熱鬧,春花似錦祭示、人聲如沸肄满。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)稠歉。三九已至掰担,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間怒炸,已是汗流浹背带饱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阅羹,地道東北人勺疼。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像捏鱼,于是被迫代替她去往敵國(guó)和親执庐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容