貓哥教你寫爬蟲 022--類與對象(下)

類是對象的模板

1558794535243

爲了完成「西紅柿炒蛋」的任務,能夠製造一個「炒菜機器人」,給它下達指令。

1558794563399

機器人.作菜('西紅柿炒雞蛋')
複製代碼

1558794601679

【對象】,都是指【實例對象】。咱們能夠以【類】爲模板,屢次複製,生成多個【實例對象】

1558794640626

從模具變成產品,也就是從【類】變成【實例對象】的過程,就叫作【實例化】

成績單代碼

class 成績單():
 @classmethod
    def 錄入成績單(cls):
        cls.學生姓名 = input('請輸入學生姓名:')
        cls.語文_成績 = int(input('請輸入語文成績:'))
        cls.數學_成績 = int(input('請輸入數學成績:'))
 @classmethod
    def 打印成績單(cls):
        print(cls.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(cls.語文_成績))
        print('數學成績:'+ str(cls.數學_成績))
成績單.錄入成績單()
成績單.打印成績單()
複製代碼

若是咱們須要錄入多份成績呢?

若是沒有學習實例化對象以前. 咱們可能要這樣寫...

class 成績單1():
 @classmethod
    def 錄入成績單(cls):
        cls.學生姓名 = input('請輸入學生姓名:')
        cls.語文_成績 = int(input('請輸入語文成績:'))
        cls.數學_成績 = int(input('請輸入數學成績:'))
    
 @classmethod
    def 打印成績單(cls):
        print(cls.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(cls.語文_成績))
        print('數學成績:'+ str(cls.數學_成績))
class 成績單2():
 @classmethod
    def 錄入成績單(cls):
        cls.學生姓名 = input('請輸入學生姓名:')
        cls.語文_成績 = int(input('請輸入語文成績:'))
        cls.數學_成績 = int(input('請輸入數學成績:'))
 @classmethod
    def 打印成績單(cls):
        print(cls.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(cls.語文_成績))
        print('數學成績:'+ str(cls.數學_成績))
class 成績單3():
 @classmethod
    def 錄入成績單(cls):
        cls.學生姓名 = input('請輸入學生姓名:')
        cls.語文_成績 = int(input('請輸入語文成績:'))
        cls.數學_成績 = int(input('請輸入數學成績:'))
 @classmethod
    def 打印成績單(cls):
        print(cls.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(cls.語文_成績))
        print('數學成績:'+ str(cls.數學_成績))
成績單1.錄入成績單()
成績單1.打印成績單()
成績單2.錄入成績單()
成績單2.打印成績單()
成績單3.錄入成績單()
成績單3.打印成績單()
複製代碼

有了實例化對象...

class 成績單():
    def 錄入成績單(self):
        self.學生姓名 = input('請輸入學生姓名:')
        self.語文_成績 = int(input('請輸入語文成績:'))
        self.數學_成績 = int(input('請輸入數學成績:'))
    def 打印成績單(self):
        print(self.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(self.語文_成績))
        print('數學成績:'+ str(self.數學_成績))
# 成績單()類實例化爲成績單一、成績單二、成績單3三個【實例對象】
成績單1 = 成績單() # 實例化,獲得實例對象「成績單1」
成績單2 = 成績單() # 實例化,獲得實例對象「成績單2」
成績單3 = 成績單() # 實例化,獲得實例對象「成績單3」
print('如今開始錄入三份成績單:')
成績單1.錄入成績單()
成績單2.錄入成績單()
成績單3.錄入成績單()
print('如今開始打印三份成績單:')
成績單1.打印成績單()
成績單2.打印成績單()
成績單3.打印成績單()
複製代碼

1558794845896

如何獲得【實例】,如何使用【實例】,使用【實例】和直接使用【類】有什麼區別?

當類須要被實例化後再使用時,和直接使用類的格式是不一樣的。

咱們以前的直接使用類的代碼

1558794925218

若是是實例化後再使用...

1558795009830
`
1558795112030

完整版的對比代碼...

# 直接使用類
class 成績單():
 @classmethod
    def 錄入成績單(cls):
        cls.學生姓名 = input('請輸入學生姓名:')
        cls.語文_成績 = int(input('請輸入語文成績:'))
        cls.數學_成績 = int(input('請輸入數學成績:'))
 @classmethod
    def 打印成績單(cls):
        print(cls.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(cls.語文_成績))
        print('數學成績:'+ str(cls.數學_成績))
成績單.錄入成績單()
成績單.打印成績單()
# 實例化以後
class 成績單():   # ①不用再寫@classmethod
    def 錄入成績單(self):  # ②cls變成self
        self.學生姓名 = input('請輸入學生姓名:')  # ③cls.變成self.
        self.語文_成績 = int(input('請輸入語文成績:'))
        self.數學_成績 = int(input('請輸入數學成績:'))
    def 打印成績單(self):
        print(self.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(self.語文_成績))
        print('數學成績:'+ str(self.數學_成績))
成績單1 = 成績單() # ④建立實例對象:成績單1
成績單1.錄入成績單() # ⑤實例化後使用
成績單1.打印成績單()
複製代碼

如下代碼是直接使用類的格式,請改爲實例化後再使用的格式

class 智能機器人():
    胸圍 = 33
    腰圍 = 44
    臀圍 = 55
    
 @classmethod
    def 自報三圍(cls):
        print('主人,個人三圍是:')
        print('胸圍:' + str(cls.胸圍))
        print('腰圍:' + str(cls.腰圍))
        print('臀圍:' + str(cls.臀圍))
        print('哈哈哈哈哈,下面粗上面細,我長得像個圓錐。')
智能機器人.自報三圍()
複製代碼

實例化後再使用的代碼...

class 智能機器人():
    胸圍 = 33
    腰圍 = 44
    臀圍 = 55
    
    def 自報三圍(self):
        print('主人,個人三圍是:')
        print('胸圍:' + str(self.胸圍))
        print('腰圍:' + str(self.腰圍))
        print('臀圍:' + str(self.臀圍))
        print('哈哈哈哈哈,下面粗上面細,我長得像個圓錐。')
a = 智能機器人() # 實例化「智能機器人」類獲得一個名字叫作「a」的實例
a.自報三圍()
複製代碼

cls表明「類」的意思,self表明「實例」的意思

若是把self改爲別的單詞呢 ? 好比bbb ?

class 智能機器人():
    胸圍 = 33
    腰圍 = 44
    臀圍 = 55
    
    def 自報三圍(bbb):
        print('主人,個人三圍是:')
        print('胸圍:' + str(bbb.胸圍))
        print('腰圍:' + str(bbb.腰圍))
        print('臀圍:' + str(bbb.臀圍))
        print('哈哈哈哈哈,下面粗上面細,我長得像個圓錐。')
a = 智能機器人() # 實例化「智能機器人」類獲得一個名字叫作「a」的實例
a.自報三圍()
複製代碼

self是全部類方法位於首位、默認的特殊參數。

1558795807454

實例屬性和類屬性有什麼區別

1558795861395

class():
    變量 = 100
實例1 = 類() # 實例化
實例2 = 類() # 實例化
print(類.變量) # 100
print(實例1.變量) # 100
print(實例2.變量) # 100
複製代碼

修改類屬性,會致使全部實例屬性變化(由於類是模板)

1558795941390

代碼爲證

class():
    變量 = 100
實例1 = 類() # 實例化
實例2 = 類() # 實例化
print(實例1.變量)
print(實例2.變量)
類.變量 = 'abc'   # 修改類屬性
print(實例1.變量)   # 實例屬性同步變化
print(實例2.變量)   # 實例屬性同步變化
複製代碼

修改實例屬性,不會影響到其餘實例,也不會影響到類。由於每一個實例都是獨立的個體

1558796018752

有代碼爲證

# 請直接運行並體驗代碼
class():
    變量 = 100
實例1 = 類() # 實例化
實例2 = 類() # 實例化
print('原先的類屬性:')
print(類.變量)
print('原先的實例1屬性:')
print(實例1.變量)
print('原先的實例2屬性:')
print(實例2.變量)
實例1.變量 = 'abc'
print('--------修改實例1的屬性後----------') 
print('如今的類屬性:')
print(類.變量)
print('如今的實例1屬性:')
print(實例1.變量)
print('如今的實例2屬性:')
print(實例2.變量)
複製代碼

新增也是同樣的道理,在類中新增屬性會影響到實例,但在實例中新增屬性隻影響這個實例本身。

類新增屬性...

# 請直接運行並體驗代碼
class():
    變量1 = 100
實例 = 類() # 實例化
類.變量2 = 'abc' # 新增類屬性
print(實例.變量1)
print(實例.變量2)
複製代碼

實例新增屬性...

# 請直接運行並體驗代碼
class():
    變量1 = 100
實例 = 類() # 實例化
實例.變量2 = 'abc' # 新增實例屬性
print(類.變量2)
複製代碼

1558796285578

請閱讀如下代碼,而後想想它的運行結果將會是什麼。

class 類:
    變量 = 100 #類屬性
實例1 = 類() # 實例化
實例2 = 類() # 實例化
實例1.變量 = 10
類.變量 = 1
print(實例1.變量)
print(實例2.變量)
複製代碼

1558796377815

實例方法和類方法的區別...

重寫類方法,這會致使全部實例方法自動被重寫

1558796457821

「重寫類方法」分紅兩個步驟:

第一個步驟是在類的外部寫一個函數,

第二個步驟是把這個新函數的名字賦值給類.原始函數

1558796535066

【不要加上括號】—— 寫成類.原始函數() = 新函數()是錯誤的。

是賦值, 不是調用...

class():
    def 原始函數(self):
        print('我是原始函數!')
def 新函數(self):
    print('我是重寫後的新函數!')
a = 類()  # 實例化
a.原始函數()
# 用新函數代替原始函數,也就是【重寫類方法】
類.原始函數 = 新函數
# 如今原始函數已經被替換了
a.原始函數() # 重寫類方法, 會波及到實例的方法...
複製代碼

補全代碼, 使其符合效果...

1558797088072

class 幸運():
    def 好運翻倍(self):
        print('好的,我把它存了起來,而後翻了888倍還給你:' + str(self.幸運數*888))
……
    ……
幸運.幸運數 = int(input('你的幸運數是多少?請輸入一個整數。'))
……
實例 = 幸運()  # 實例化
實例.好運翻倍()
複製代碼

補全以後的代碼

# 請直接運行並體驗代碼
class 幸運():
    def 好運翻倍(self):
        print('好的,我把它存了起來,而後翻了888倍還給你:' + str(self.幸運數*888))
def 新好運翻倍(self):
    print('我是重寫後的新函數!')
    print('好的,我把它存了起來,而後翻了666倍還給你:' + str(self.幸運數*666))
幸運.幸運數 = int(input('你的幸運數是多少?請輸入一個整數。'))
幸運.好運翻倍 = 新好運翻倍
實例 = 幸運()  # 實例化
實例.好運翻倍()
複製代碼

咱們能夠經過重寫類方法,讓實例方法發生變化,

但咱們不能重寫實例方法,模板給的技能不是說換就能換的。

1558797369845

不信 ? 來, 作個死...

class 幸運():
    def 好運翻倍(self):
        print('好的,我把它存了起來,而後翻了888倍還給你:' + str(self.幸運數*888))
def 新好運翻倍(self):
    print('我是重寫後的新函數!')
    print('好的,我把它存了起來,而後翻了666倍還給你:' + str(self.幸運數*666))
幸運.幸運數 = int(input('你的幸運數是多少?請輸入一個整數。'))
實例 = 幸運()  # 實例化
實例.好運翻倍 = 新好運翻倍    # 嘗試重寫實例方法,將會報錯
實例.好運翻倍()
複製代碼

1558797543177

什麼是初始化函數

先上代碼

class():
    def __init__(self):
        print('實例化成功!')
實例 = 類()
複製代碼

初始化函數的意思是,當你建立一個實例的時候,這個函數就會被調用

__init__()的括號中,第一個參數必定要寫上self,否則會報錯

1558797762839

初始化函數照樣能夠傳遞參數

以前的代碼...

class 成績單():
    def 錄入成績單(self):
        self.學生姓名 = input('請輸入學生姓名:')
        self.語文_成績 = int(input('請輸入語文成績:'))
        self.數學_成績 = int(input('請輸入數學成績:'))
    def 打印成績單(self):
        print(self.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(self.語文_成績))
        print('數學成績:'+ str(self.數學_成績))
成績單1 = 成績單() # 實例化
成績單2 = 成績單() # 實例化
成績單3 = 成績單() # 實例化
成績單1.錄入成績單()
成績單2.錄入成績單()
成績單3.錄入成績單()
成績單1.打印成績單()
成績單2.打印成績單()
成績單3.打印成績單()
複製代碼

咱們能夠直接把須要錄入的信息做爲參數傳遞給成績單1成績單2成績單3這三個實例對象。

class 成績單():
    def __init__(self,學生姓名,語文_成績,數學_成績):
        self.學生姓名 = 學生姓名
        self.語文_成績 = 語文_成績
        self.數學_成績 = 數學_成績
    def 打印成績單(self):
        print(self.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(self.語文_成績))
        print('數學成績:'+ str(self.數學_成績))
成績單1 = 成績單('張三',99,88)
成績單2 = 成績單('李四',64,73)
成績單3 = 成績單('王五',33,22)
成績單1.打印成績單()
成績單2.打印成績單()
成績單3.打印成績單()
複製代碼

九九乘法表...

1558797934642

三三乘法表...

1558798025445

五五乘法表

1558798070716

補全代碼後,運行效果:打印了一個三三乘法表和五五乘法表

1558798249675

class 乘法表():
    def __init__(……):
        ……
    def 打印(……):
        for i in range(……):
            for x in range(1,i+1):
                print( '%d X %d = %d' % (i ,x ,i*x) ,end = ' ' )
            print(' ')
三三乘法表 = 乘法表(3)
三三乘法表.打印()
五五乘法表 = 乘法表(5)
五五乘法表.打印()
複製代碼

代碼答案...

# 請直接運行和體驗代碼
class 乘法表():
    def __init__(self,n):
        self.n = n
    def 打印(self):
        for i in range(1,self.n + 1):
            for x in range(1,i+1):
                print( '%d X %d = %d' % (i ,x ,i*x) ,end = ' ' )
            print(' ')
三三乘法表 = 乘法表(3)
三三乘法表.打印()
五五乘法表 = 乘法表(5)
五五乘法表.打印()
複製代碼

代碼解析...

1558798282937

小結

1558798330895

什麼是繼承

偶像劇裏富二代繼承老爹遺產,今後甩開99%同齡人,走上人生巔峯...

「類的繼承」也和這個有點相似,「子類」繼承了「父類」的「財產」。

類的繼承很大程度也是爲了不重複性勞動。

好比說當咱們要寫一個新的類,若是新的類有許多代碼都和舊類相同,又有一部分不一樣的時候,

就能夠用「繼承」的方式避免重複寫代碼。

class 成績單_():
    def __init__(self,學生姓名,語文_成績,數學_成績):
        self.學生姓名 = 學生姓名
        self.語文_成績 = 語文_成績
        self.數學_成績 = 數學_成績
    def 打印成績單(self):
        print(self.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(self.語文_成績))
        print('數學成績:'+ str(self.數學_成績))
    def 打印平均分(self):
        平均分 = (self.語文_成績 + self.數學_成績)/2
        print(self.學生姓名 + '的平均分是:' + str(平均分))
class 成績單_():
    def __init__(self,學生姓名,語文_成績,數學_成績):
        self.學生姓名 = 學生姓名
        self.語文_成績 = 語文_成績
        self.數學_成績 = 數學_成績
    def 打印成績單(self):
        print(self.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(self.語文_成績))
        print('數學成績:'+ str(self.數學_成績))
    def 打印平均分(self):
        平均分 = (self.語文_成績 + self.數學_成績)/2
        print(self.學生姓名 + '的平均分是:' + str(平均分))
    def 打印總分(self):
        總分 = self.語文_成績 + self.數學_成績
        print(self.學生姓名 + '的總分是:' + str(總分))
實例_舊 = 成績單_舊('王明明',99,88)
實例_舊.打印成績單()
實例_舊.打印平均分()
實例_新 = 成績單_新('王明明',99,88)
實例_新.打印成績單()
實例_新.打印平均分()
實例_新.打印總分()
複製代碼

1558798496335

若是運用繼承來改寫代碼...

class 成績單_():
    def __init__(self,學生姓名,語文_成績,數學_成績):
        self.學生姓名 = 學生姓名
        self.語文_成績 = 語文_成績
        self.數學_成績 = 數學_成績
    def 打印成績單(self):
        print(self.學生姓名 + '的成績單以下:')
        print('語文成績:'+ str(self.語文_成績))
        print('數學成績:'+ str(self.數學_成績))
    def 打印平均分(self):
        平均分 = (self.語文_成績 + self.數學_成績)/2
        print(self.學生姓名 + '的平均分是:' + str(平均分))
class 成績單_(成績單_舊):
    def 打印總分(self):
        總分 = self.語文_成績 + self.數學_成績
        print(self.學生姓名 + '的總分是:' + str(總分))
實例_舊 = 成績單_舊('王明明',99,88)
實例_舊.打印成績單()
實例_舊.打印平均分()
實例_新 = 成績單_新('王明明',99,88)
實例_新.打印成績單()
實例_新.打印平均分()
實例_新.打印總分()
複製代碼

class 成績單_新(成績單_舊)就用到了類的繼承,格式是class 新類(舊類)

1558798585455

舊的類稱爲父類,新寫的類稱爲子類

子類能夠在父類的基礎上改造類方法,因此咱們能夠說子類繼承了父類

class 父類():
    def __init__(self,參數):
        self.變量 = 參數
    def 打印屬性(self):
        print('變量的值是:')
        print(self.變量)
class 子類(父類):
    pass  # pass語句表明「什麼都不作」
子類實例 = 子類(2)
子類實例.打印屬性()
複製代碼

1558798702165

小練習, 補全代碼...

class 基礎機器人():
    def __init__(self,參數):
        self.姓名 = 參數
    def 自報姓名(self):
        print('我是' + self.姓名 + '!')     
    def 賣萌(self):
        print('主人,求抱抱!')
……
    ……
        ……
安迪 = 高級機器人('安迪')
安迪.自報姓名()
安迪.賣萌()
安迪.高級賣萌()
複製代碼

用到的方法...

安迪 = 高級機器人('安迪')
安迪.自報姓名()
安迪.賣萌()
安迪.高級賣萌()
複製代碼

運行效果

我是安迪!
主人,求抱抱!
主人,每次想到怎麼欺負你的時候,就感受本身全身biubiubiu散發着智慧的光芒!
複製代碼

補全後的代碼...

class 基礎機器人():
    def __init__(self,參數):
        self.姓名 = 參數
    def 自報姓名(self):
        print('我是' + self.姓名 + '!')     
    def 賣萌(self):
        print('主人,求抱抱!')
class 高級機器人(基礎機器人):
    def 高級賣萌(self):
        print('主人,每次想到怎麼欺負你的時候,就感受本身全身biubiubiu散發着智慧的光芒!')
安迪 = 高級機器人('安迪')
安迪.自報姓名()
安迪.賣萌()
安迪.高級賣萌()
複製代碼

子類除了能夠定製新的類方法,還能直接覆蓋父類的方法,

只要使用相同的類方法名稱就能作到這一點。

# 請閱讀註釋,而後運行代碼
class 基礎機器人():
    def __init__(self,參數):
        self.姓名 = 參數
    def 自報姓名(self):
        print('我是' + self.姓名 + '!')     
    def 賣萌(self):
        print('主人,求抱抱!')
class 高級機器人(基礎機器人):
    def 賣萌(self):  # 這裏使用了相同的類方法名稱「賣萌」,這樣可讓子類方法覆蓋父類方法
        print('主人,每次想到怎麼欺負你的時候,就感受本身全身biubiubiu散發着智慧的光芒!')
魯賓 =  基礎機器人('魯賓')
魯賓.自報姓名()
魯賓.賣萌()  # 調用父類方法
安迪 = 高級機器人('安迪')
安迪.自報姓名()
安迪.賣萌()  # 父類方法被子類中的同名方法覆蓋
複製代碼

小練習: 補全代碼, 使其符合效果

class 基礎機器人():
    def __init__(self,參數):
        self.姓名 = 參數
    def 自報姓名(self):
        print('我是' + self.姓名 + '!')     
    def 賣萌(self):
        print('主人,求抱抱!')
class 高級機器人(基礎機器人):
    def ……
        ……
        ……
    def 賣萌(self):
        print('主人,每次想到怎麼欺負你的時候,就感受本身全身biubiubiu散發着智慧的光芒!')
安迪 = 高級機器人('安迪')
安迪.自報姓名()
安迪.高級賣萌()
複製代碼

1558799010874

補全後的代碼...

class 基礎機器人():
    def __init__(self,參數):
        self.姓名 = 參數
    def 自報姓名(self):
        print('我是' + self.姓名 + '!')     
    def 賣萌(self):
        print('主人,求抱抱!')
class 高級機器人(基礎機器人):
    def 自報姓名(self):
        print('我是高級機器人' + self.姓名 + '!')
    def 賣萌(self):
        print('主人,每次想到怎麼欺負你的時候,就感受本身全身biubiubiu散發着智慧的光芒!')
安迪 = 高級機器人('安迪')
安迪.自報姓名()
安迪.賣萌()
複製代碼

咱們能在子類中重寫覆蓋任意父類方法,哪怕是初始化函數__init__

小練習: 補全代碼, 使其符合效果

class 基礎機器人():
    def __init__(self,參數):
        self.姓名 = 參數
    def 自報姓名(self):
        print('我是' + self.姓名 + '!')     
    def 賣萌(self):
        print('主人,求抱抱!')
class 高級機器人(基礎機器人):
    def __init__(……):
        ……
    
    def 自報姓名(self):
        print(……)       
    def 賣萌(self):
        print('主人,每次想到怎麼欺負你的時候,就感受本身全身biubiubiu散發着智慧的光芒!')
安迪 = 高級機器人('安迪',150)
安迪.自報姓名()
安迪.賣萌()
複製代碼

1558799102665

補全後的代碼...

class 基礎機器人():
    def __init__(self,參數):
        self.姓名 = 參數
    def 自報姓名(self):
        print('我是' + self.姓名 + '!')     
    def 賣萌(self):
        print('主人,求抱抱!')
class 高級機器人(基礎機器人):
    def __init__(self,參數,參數2):
        self.姓名 = 參數
        self.智商 = 參數2
    
    def 自報姓名(self):
        print('我是高級機器人' + self.姓名 + '!' + '智商高達' + str(self.智商) + '!' )       
    def 賣萌(self):
        print('主人,每次想到怎麼欺負你的時候,就感受本身全身biubiubiu散發着智慧的光芒!')
安迪 = 高級機器人('安迪',150)
安迪.自報姓名()
安迪.賣萌()
複製代碼

1558799193212

子類從【一個父類】繼承類方法,咱們叫作「單繼承」。還有一種更復雜的繼承狀況,叫「多重繼承」

1558799231472

多重繼承 就是一個子類從【多個父類】中繼承類方法。

格式是class 子類(父類1,父類2,……)

class 基礎機器人():
    def 賣萌(self):
        print('主人,求抱抱!')
# 注:由於多重繼承要求父類是平等的關係,因此這裏的「高級機器人」沒有繼承「基礎機器人」
class 高級機器人(): 
    def 高級賣萌(self): 
        print('主人,每次想到怎麼欺負你的時候,就感受本身全身biubiubiu散發着智慧的光芒!')
class 超級機器人(基礎機器人,高級機器人):
    def 超級賣萌(self): 
        print('pika, qiu!')
        print('''   へ     /| /\7   ∠_/ / │  / / │ Z_,< /  /`ヽ │     ヽ  /  〉 Y     ` /  / イ● 、 ●  ⊂⊃〈  / () へ    | \〈 >ー、_ ィ │// /へ  / ノ<|\\ ヽ_ノ  (_/ │// 7       |/ >―r ̄ ̄`ー―_''')
        
皮卡 = 超級機器人()
皮卡.賣萌()
皮卡.高級賣萌()
皮卡.超級賣萌()
複製代碼

子類超級機器人同時繼承了父類基礎機器人高級機器人中的類方法

多重繼承有利有弊。過分使用繼承容易把事情搞複雜,就像一我的有不少爹一定會帶來諸多麻煩。

課堂實操

隔壁小王請你爲他編寫了一個出租車計費的程序html

class 出租車():
    def 計費(self):
        千米數 = float(input('請輸入行程千米數:'))
        費用 = 千米數 * 2.5
        print('費用一共是:' + str(費用) + '元')
小王的出租車 = 出租車()
小王的出租車.計費()
複製代碼

程序不完美的地方在於,每千米費用2.5元是一個寫死的數據,沒法修改。 小王但願你能完善一下這個代碼,也就是寫出一個初始化函數,讓這個類能接收參數(也就是每千米計費價格)生成不一樣的實例。python

這樣,他就能把這個程序借個隔壁的隔壁,也就是司機小李用。瀏覽器

補全代碼, 效果以下 cookie

1558799607006

class 出租車():
    ……
        ……
        ……
    def 計費(self):
        千米數 = float(input('請輸入行程千米數:'))
        費用 = 千米數 * ……
        print('費用一共是:' + str(費用) + '元')
小王的出租車 = 出租車(2.5)
小王的出租車.計費()
小李的出租車 = 出租車(3)
小李的出租車.計費()
複製代碼

補全後的代碼...

# 請直接運行並體驗代碼
class 出租車():
    def __init__(self,參數):
        self.每千米費用 = 參數    
    def 計費(self):
        千米數 = float(input('請輸入行程千米數:'))
        費用 = 千米數 * self.每千米費用
        print('費用一共是:' + str(費用) + '元')
小王的出租車 = 出租車(2.5)
小王的出租車.計費()
小李的出租車 = 出租車(3)
小李的出租車.計費()
複製代碼

1558800305828

這裏的計費規則不太科學。司機小王對代碼提出意見 小王:「我這裏都是前3千米15元,後面每千米2.5元,你幫我把代碼改一下,讓它按個人方式計費。」 session

1558800384871

修改後的代碼...

class 出租車():
    def __init__(self,參數):
        self.每千米費用 = 參數
        
    def 計費(self):
        千米數 = int(input('請輸入行程千米數:'))
        if 千米數<= 3:
            費用 = 15
        else:
            費用 = 15 + (千米數-3)*self.每千米費用
        print('費用一共是:' + str(費用) + '元')
小王的出租車 = 出租車(2.5)
小王的出租車.計費()
複製代碼

小王:「你的代碼仍是不夠方便。我有時候想改爲4千米20元,有時候想改爲2千米12元,你這代碼不支持我傳遞這些參數,能不能修改一下?」 補全代碼後,「出租車」類能夠接受3個參數,程序的運行效果不變: app

1558800518864

修改的代碼...

class 出租車():
    def __init__(self,參數1,參數2,參數3):
        self.每千米費用 = 參數1
        self.最低千米 = 參數2
        self.最低費用 = 參數3
        
    def 計費(self):
        千米數 = float(input('請輸入行程千米數:'))
        if 千米數<= self.最低千米:
            費用 = self.最低費用
        else:
            費用 = self.最低費用 + (千米數 - self.最低千米)*self.每千米費用
        print('費用一共是:' + str(費用) + '元')
小王的出租車 = 出租車(2.5,3,15)
小王的出租車.計費()
複製代碼

重構代碼,把計費函數拆解成計費記錄行程統計費用結算信息四個函數:框架

class 出租車():
    def __init__(self,參數1,參數2,參數3):
        self.每千米費用 = 參數1
        self.最低千米 = 參數2
        self.最低費用 = 參數3
    
    def 計費(self):
        self.記錄行程()
        self.統計費用()
        self.結算信息()
    def 記錄行程(self):
        ……
    def 統計費用(self):
        ……
    def 結算信息(self):
        ……
小王的出租車 = 出租車(2.5,3,15)
小王的出租車.計費()
複製代碼

程序的運行效果和剛纔如出一轍: dom

1558800666611

修改的代碼...

class 出租車():
    def __init__(self,參數1,參數2,參數3):
        self.每千米費用 = 參數1
        self.最低千米 = 參數2
        self.最低費用 = 參數3
    
    def 計費(self):
        self.記錄行程()
        self.統計費用()
        self.結算信息()
    def 記錄行程(self):
        self.行程千米數 = float(input('請輸入行程千米數:'))
    def 統計費用(self):
        if self.行程千米數<= self.最低千米:
            self.最終費用 = self.最低費用
        else:
            self.最終費用 = self.最低費用 + (self.行程千米數 - self.最低千米) * self.每千米費用
    def 結算信息(self):
        print('費用一共是:' + str(self.最終費用) + '元')
小王的出租車 = 出租車(2.5,3,15)
小王的出租車.計費()
複製代碼

小王對你的代碼很滿意。不過,開電動車的小李又跑來找你 小李:「我是開電動車的,如今政府號召環保,對電動車也補貼,全部電動車計費按8折算,你能幫我寫個程序麼?」scrapy

補全代碼

class 出租車():
    def __init__(self,參數1,參數2,參數3):
        self.每千米費用 = 參數1
        self.最低千米 = 參數2
        self.最低費用 = 參數3
    
    def 計費(self):
        self.記錄行程()
        self.統計費用()
        self.結算信息()
    def 記錄行程(self):
        self.行程千米數 = float(input('請輸入行程千米數:'))
    def 統計費用(self):
        if self.行程千米數<= self.最低千米:
            self.最終費用 = self.最低費用
        else:
            self.最終費用 = self.最低費用 + (self.行程千米數 - self.最低千米) * self.每千米費用
    def 結算信息(self):
        print('費用一共是:' + str(self.最終費用) + '元')
class ……:
    def ……:
        ……
小王的出租車 = 出租車(2.5,3,15)
小王的出租車.計費() 
小李的電動車 = 電動車(2.5,3,15)
小李的電動車.計費()
複製代碼

效果以下...

1558800823418

補全的代碼...(推薦使用繼承)

class 出租車():
    def __init__(self,參數1,參數2,參數3):
        self.每千米費用 = 參數1
        self.最低千米 = 參數2
        self.最低費用 = 參數3
    
    def 計費(self):
        self.記錄行程()
        self.統計費用()
        self.結算信息()
    def 記錄行程(self):
        self.行程千米數 = float(input('請輸入行程千米數:'))
    def 統計費用(self):
        if self.行程千米數<= self.最低千米:
            self.最終費用 = self.最低費用
        else:
            self.最終費用 = self.最低費用 + (self.行程千米數 - self.最低千米) * self.每千米費用
    def 結算信息(self):
        print('費用一共是:' + str(self.最終費用) + '元')
class 電動車(出租車):
    def 統計費用(self):
        if self.行程千米數<= self.最低千米:
            self.最終費用 = self.最低費用
        else:
            self.最終費用 = self.最低費用 + (self.行程千米數 - self.最低千米) * self.每千米費用
        self.最終費用 = self.最終費用*0.8
小王的出租車 = 出租車(2.5,3,15)
小王的出租車.計費() 
小李的電動車 = 電動車(2.5,3,15)
小李的電動車.計費()
複製代碼

總結

就像是一個模版,經過這個模版能夠製造出許多個實例對象,這個製造過程,咱們稱之爲實例化

能夠經過初始化函數__init__給類傳遞不一樣的參數,這樣的方式可讓咱們獲得屬性不一樣的實例

1558800966565

有了繼承以後,咱們能夠很方便的改裝,獲得子類

這個過程就像在改裝模版,咱們既能夠直接複製模版,

又能夠給模版增長一些功能,亦或是替換、強化原來模板的某些功能

1558801016433

今日做業

使用面向對象的方式, 來改寫代碼...

import time
import random
user1 = {
    'name': '',
    'life': 0,
    'victory':0
}
user2 = {
    'name': '',
    'life': 0,
    'victory':0
}
attack_list = [
    {
        'desc':'{} 揮劍向 {} 砍去',
        'num':20
    },
    {
        'desc':'{} 準備剛正面, 對 {} 使出一記"如來神掌"',
        'num':30
    },
    {
        'desc':'{} 擼起了袖子給 {} 一頓胖揍',
        'num':25
    },
    {
        'desc':'{} 向 {} 拋了個媚眼',
        'num':10
    },
    {
        'desc':'{} 抄起衝鋒槍就是一梭子, {} 走位風騷, 輕鬆躲過',
        'num':0
    },
    {
        'desc':'{} 出了一個大招, {} 躲閃不及, 正中要害',
        'num':40
    }
]
user1['name'] = input('請輸入玩家1的暱稱: ')
user2['name'] = input('請輸入玩家2的暱稱: ')
while True:
    user1['victory'] = 0
    user2['victory'] = 0
    for i in range(3):
        print(' \n——————如今是第 {} 局——————'.format(i+1))
        user1['life'] = random.randint(100, 150)
        user2['life'] = random.randint(100, 150)
        print(user1['name']+'\n血量:{}'.format(user1['life']))
        print('------------------------')
        print(user2['name']+'\n血量:{}'.format(user2['life']))
        print('-----------------------')
        time.sleep(4)
        first_attack = random.randint(0,1)
        users_list = []
        if first_attack:
            user1['isfirst'] = 1
            print('漂亮!!! '+user1['name']+' 得到先發優點!')
            print('')
            users_list.append(user1)
            users_list.append(user2)
        else:
            user2['isfirst'] = 1
            print('難以置信! '+user2['name']+' 得到先發優點!')
            print('')
            users_list.append(user2)
            users_list.append(user1)
        time.sleep(2)
        while user1['life'] > 0 and user2['life'] > 0:
            tmp_rand = random.randint(0,len(attack_list)-1)
            users_list[1]['life'] = users_list[1]['life'] - attack_list[tmp_rand]['num']
            print(attack_list[tmp_rand]['desc'].format(users_list[0]['name'],users_list[1]['name'])+' 形成了{}點傷害 ==> '.format(attack_list[tmp_rand]['num'])+users_list[1]['name']+' 的剩餘血量:{}'.format(users_list[1]['life']))
            time.sleep(4)
            if users_list[1]['life'] <= 0:
                print('')
                print(users_list[1]['name']+' 慘敗 -_-||')
                users_list[0]['victory']+=1
                break
            tmp_rand = random.randint(0,len(attack_list)-1)
            users_list[0]['life'] = users_list[0]['life'] - attack_list[tmp_rand]['num']
            print(attack_list[tmp_rand]['desc'].format(users_list[1]['name'],users_list[0]['name'])+' 形成了{}點傷害 ==> '.format(attack_list[tmp_rand]['num'])+users_list[0]['name']+' 的剩餘血量:{}'.format(users_list[0]['life']))
            time.sleep(4)
            if users_list[0]['life'] <= 0:
                print('')
                print(users_list[0]['name']+' 慘敗 -_-||')
                time.sleep(3)
                users_list[1]['victory']+=1
                break
            print('-----------------------')
        if user1['victory'] == 2:
            print('')
            print('三局兩勝中 '+user1['name']+' 獲勝!')
            break
        if user2['victory'] == 2:
            print('')
            print('三局兩勝中 '+user2['name']+' 獲勝!')
            break
    print('')
    res = input('要不要再來一局? (回覆"是"再來一局, 其餘退出...) ') 
    if res != '是':
        break
複製代碼

面向對象的方式...

未完待續...
複製代碼

快速跳轉:

貓哥教你寫爬蟲 000--開篇.md
貓哥教你寫爬蟲 001--print()函數和變量.md
貓哥教你寫爬蟲 002--做業-打印皮卡丘.md
貓哥教你寫爬蟲 003--數據類型轉換.md
貓哥教你寫爬蟲 004--數據類型轉換-小練習.md
貓哥教你寫爬蟲 005--數據類型轉換-小做業.md
貓哥教你寫爬蟲 006--條件判斷和條件嵌套.md
貓哥教你寫爬蟲 007--條件判斷和條件嵌套-小做業.md
貓哥教你寫爬蟲 008--input()函數.md
貓哥教你寫爬蟲 009--input()函數-人工智能小愛同窗.md
貓哥教你寫爬蟲 010--列表,字典,循環.md
貓哥教你寫爬蟲 011--列表,字典,循環-小做業.md
貓哥教你寫爬蟲 012--布爾值和四種語句.md
貓哥教你寫爬蟲 013--布爾值和四種語句-小做業.md
貓哥教你寫爬蟲 014--pk小遊戲.md
貓哥教你寫爬蟲 015--pk小遊戲(全新改版).md
貓哥教你寫爬蟲 016--函數.md
貓哥教你寫爬蟲 017--函數-小做業.md
貓哥教你寫爬蟲 018--debug.md
貓哥教你寫爬蟲 019--debug-做業.md
貓哥教你寫爬蟲 020--類與對象(上).md
貓哥教你寫爬蟲 021--類與對象(上)-做業.md
貓哥教你寫爬蟲 022--類與對象(下).md
貓哥教你寫爬蟲 023--類與對象(下)-做業.md
貓哥教你寫爬蟲 024--編碼&&解碼.md
貓哥教你寫爬蟲 025--編碼&&解碼-小做業.md
貓哥教你寫爬蟲 026--模塊.md
貓哥教你寫爬蟲 027--模塊介紹.md
貓哥教你寫爬蟲 028--模塊介紹-小做業-廣告牌.md
貓哥教你寫爬蟲 029--爬蟲初探-requests.md
貓哥教你寫爬蟲 030--爬蟲初探-requests-做業.md
貓哥教你寫爬蟲 031--爬蟲基礎-html.md
貓哥教你寫爬蟲 032--爬蟲初體驗-BeautifulSoup.md
貓哥教你寫爬蟲 033--爬蟲初體驗-BeautifulSoup-做業.md
貓哥教你寫爬蟲 034--爬蟲-BeautifulSoup實踐.md
貓哥教你寫爬蟲 035--爬蟲-BeautifulSoup實踐-做業-電影top250.md
貓哥教你寫爬蟲 036--爬蟲-BeautifulSoup實踐-做業-電影top250-做業解析.md
貓哥教你寫爬蟲 037--爬蟲-寶寶要聽歌.md
貓哥教你寫爬蟲 038--帶參數請求.md
貓哥教你寫爬蟲 039--存儲數據.md
貓哥教你寫爬蟲 040--存儲數據-做業.md
貓哥教你寫爬蟲 041--模擬登陸-cookie.md
貓哥教你寫爬蟲 042--session的用法.md
貓哥教你寫爬蟲 043--模擬瀏覽器.md
貓哥教你寫爬蟲 044--模擬瀏覽器-做業.md
貓哥教你寫爬蟲 045--協程.md
貓哥教你寫爬蟲 046--協程-實踐-吃什麼不會胖.md
貓哥教你寫爬蟲 047--scrapy框架.md
貓哥教你寫爬蟲 048--爬蟲和反爬蟲.md
貓哥教你寫爬蟲 049--完結撒花.md函數

相關文章
相關標籤/搜索