1. 程式人生 > >第12關類和對象

第12關類和對象

西紅柿 傳參 兩個 要求 命名 contain 函數名 -m -c

在這之前,先要和大家講一講兩種編程思維:從【面向過程】編程到【面向對象】編程。

因為我們還沒開始學習【類與對象】的相關知識,為了方便理解,我們舉個生活化的例子。比如我們現在接到的一個需求是:做一道西紅柿炒雞蛋。

第一種方法是:自己按照炒菜的步驟親手制作一道西紅柿炒雞蛋。

第二種方法是:制作一臺炒菜機器人,然後告訴機器人做一道西紅柿炒雞蛋。

在這裏,我們直接面對的是機器人,而非炒菜的過程,所以這裏機器人就是我們面對的對象,這種解決問題的方法就叫做【面向對象】編程。

【面向過程】編程主要用到的是“函數”知識,將每個過程步驟打包成函數,再依次調用,還記得我們項目二用到的幾個函數嗎? 而【面向對象】編程主要用到的是“類和對象”知識,這也是我們這兩關的學習目標。 雖然中文命名代碼一樣可以運行,但這種方式在編程世界裏【並不規範】,屬於非主流。所以大家在實際編程的時候,還是務必用英文取名:
 1
#直接運行即可 2 3 變量1 = 2019 4 變量2 = 中國夢 5 6 def 打印變量(): 7 # 雖然可以中文命名,但括號依舊要用英文 8 print(變量1) 9 print(變量2) 10 11 def 兩倍放大(數據): 12 數據 = 數據 * 2 13 return 數據 14 15 打印變量() 16 print(兩倍放大(1000))

# 用英文取名才是規範的    
var1 = 2019
var2 = 中國夢

def print_var():
    
print(var1) print(var2) def double_num(num): num = num * 2 return num print_var() print(double_num(1000))

輸出

2019
中國夢
2000

類是一個函數包,理解【類】最簡單的方式:【類】是一個函數包。類中可以放置函數和變量,然後類中的函數可以很方便的使用類中的變量。

我們來看看類中是如何放置函數和變量的。

類中可以放置函數和變量

就像我們可以用def語句來自定義一個函數,我們用class語句來自定義一個類。

 語法:創建一個名為“ClassName”的類,類名一般首字母要大寫,(): 不能丟   
class ClassName(): # 如定義一個名為‘狗‘的類,可以寫成class Dog(): # 規範:class語句後續的代碼塊要縮進 def function1(): # 定義類中的函數1

既然【類】是一個函數包,所以一個類中可以放置一堆函數,就像這樣:(如前文所說,以下例子會用中文取名)

class 類A():
    def 函數1():
        print(報道!我是類A的第一個方法!)
    def 函數2():
        print(報道!我是類A的第二個方法!)
    def 函數3():
        print(報道!我是類A的第三個方法!)

在類中被定義的函數被稱為類的【方法】,描述的是這個類能做什麽。我們使用類名.函數名()的格式,就可以讓類的方法運行起來。讓我們來試一試:

class 類A():
    def 函數1():
        print(報道!我是類A的第一個方法!)
    def 函數2():
        print(報道!我是類A的第二個方法!)
    def 函數3():
        print(報道!我是類A的第三個方法!)

類A.函數1()
類A.函數2()
類A.函數3()
報道!我是類A的第一個方法!
報道!我是類A的第二個方法!
報道!我是類A的第三個方法!

除了函數外,在類中還可以放置一堆變量,就像這樣:

class 類A():
    變量1 = 100
    變量2 = -5.83
    變量3 = abc

在類中被定義的變量被稱為類的【屬性】。使用類名.變量名的格式,可以把類中的屬性的值提取出來。讓我們來試一試:(這裏需要用print語句,把取出的數值打印到屏幕上)

class 類A():
    變量1 = 100
    變量2 = -5.83
    變量3 = abc

# 這裏需要用print語句,才能把提取出的數值打印到屏幕上
print(類A.變量1)
print(類A.變量2)
print(類A.變量3)

不過類中的屬性(變量)也不是不能改變,使用類名.變量名的格式,可以讓我們在類的外面,增加或修改類的屬性:

class 類A():
    變量1 = 100
    變量2 = -5.83
    變量3 = abc

類A.變量1 = 99
類A.變量4 = 新增一個變量

print(類A.變量1)
print(類A.變量4)

當類中放置了函數和變量,類就有了方法和屬性

下面我們來制作一個最簡單的,既有方法又有屬性的類:

class 智能機器人():
    胸圍 = 33
    腰圍 = 44
    臀圍 = 55
    # 以上為類屬性
    def 打招呼():
        print(主人你好!)
    def 賣萌():
        print(主人,求抱抱!)
    def 生氣():
        print(主人,我要報警了!)
    # 以上為類方法

我們可以把類屬性打印出來,也可以調用類方法。請運行代碼體驗一下這個“智能機器人”:

class 智能機器人():
    胸圍 = 33
    腰圍 = 44
    臀圍 = 55
    def 打招呼():
        print(主人你好!)
    def 賣萌():
        print(主人,求抱抱!)
    def 生氣():
        print(主人,我要報警了!)

print(把類的屬性打印出來:)
print(智能機器人.胸圍)
print(智能機器人.腰圍)
print(智能機器人.腰圍)

智能機器人.打招呼()
智能機器人.賣萌()
智能機器人.生氣()

現在你你應該知道使用類的屬性和方法了吧?

下面我們來做個練習,請為機器人再添加一個方法智能機器人.奔跑(),當運行這個方法的時候,屏幕上會打印出一串字符:我快樂地奔跑、奔跑……哎呦餵!撞墻了。

# 請補全代碼    
class 智能機器人():
    胸圍 = 33
    腰圍 = 44
    臀圍 = 55
    def 打招呼():
        print(主人你好!)
    def 賣萌():
        print(主人,求抱抱!)
    def 生氣():
        print(主人,我要報警了!)
    def 奔跑():
        print(我快樂的奔跑,奔跑,,,,,,,哎呦餵!撞墻了。)
智能機器人.奔跑()

再來做個練習,為機器人再添加一個屬性智商 = 200,當運行print(智能機器人.智商)這個的時候,屏幕上會打印出200。請補全代碼。

class 智能機器人():
    胸圍 = 33
    腰圍 = 44
    臀圍 = 55
    智商 = 200

    def 打招呼():
        print(主人你好!)
    def 賣萌():
        print(主人,求抱抱!)
    def 生氣():
        print(主人,我要報警了!)

print(智能機器人.智商)

幹得不錯喲~在這裏,我們為了讓代碼更直觀,一般會把類中的函數和函數之間換行隔開,這不影響代碼運行。

看到這裏,你可能會有有點疑惑,類方法也是函數,那和我們之前學的單獨定義函數有什麽區別嗎?

們兩者最大的區別,一個是它的調用格式:類.函數名()函數名()多了一個【類.】,但更重要的是,“類”中的函數可以利用“類”中的變量(也就是類方法可以調用類屬性)。

技術分享圖片

這裏新出現的@classmethod是聲明了下面的函數是類方法,為什麽要這麽寫呢?這就是我們接下來要講的

類方法和類屬性可以組合

什麽意思呢?我們來看一個例子:下面的類中有兩個變量和一個函數。請直接運行體驗一下。然後請猜猜函數1的功能是什麽

# 請直接運行體驗代碼

class 類A():
    變量1 = 100
    變量2 = 200

    @classmethod
    def 函數1(cls):
        print(cls.變量1)
        print(cls.變量2)

類A.函數1()

函數1()的功能是:把類中的變量1和變量2打印出來。

在這裏,為了把類中的變量傳遞給類中的函數,我們需要用到3個特定格式:

① 第一個格式@classmethod的中文意思就是“類方法”,@classmethod聲明了函數1是類方法,這樣才能允許函數1使用類屬性中的數據。

② 第二個格式cls的意思是class的縮寫。如果類方法函數1想使用類屬性(也就是類中的變量),就要寫上cls函數1的第一個參數,也就是把這個類作為參數傳給自己,這樣就能被允許使用類中的數據。

③ 第三個格式是cls.變量。類方法想使用類屬性的時候,需要在這些變量名稱前加上cls.

這就好比類方法之間的約法三章,所以但凡有任何格式錯誤都會報錯。

另外,當類中的函數【不需要】用到類中的變量時,就不要用@classmethodclscls.三處格式,否則就是占著茅坑不拉屎,終端也會給你報錯。(沒錯,就是這麽傲嬌~)

# 請運行代碼,報錯後,修改格式到正確的樣式就能運行通過

class 類A():
    變量1 = 100
    變量2 = 200
    
    @classmethod
    def 函數1():
        print(我不需要使用類屬性。)

類A.函數1()

讓我們牢記正確格式。當格式正確後,我們就可以開心的玩耍了

‘‘‘【正確案例】‘‘‘

class 類A():
    變量1 = 100
    變量2 = 200
    
    def 函數1():  # 【不需要】使用類屬性
        print(我不需要使用類屬性。)
    
    @classmethod
    def 函數2(cls):  # 【需要】使用類屬性
        print(cls.變量1)
        print(cls.變量2)

類A.函數1()
類A.函數2()

讓我們做一個練習,為剛才的智能機器人,再寫一個自報三圍的類方法,調用方式是智能機器人.自報三圍(),調用該類方法的終端顯示效果如下:

主人,我的三圍是:
胸圍:33
腰圍:44
臀圍:55
哈哈哈哈哈,下面粗上面細,我長得像個圓錐
class 智能機器人():
    胸圍 = 33
    腰圍 = 44
    臀圍 = 55
    
    def 打招呼():
        print(主人你好!)
    
    def 賣萌():
        print(主人,求抱抱!)

    def 生氣():
        print(主人,我要報警了!)
    
    def 自報三圍 ()
        print(主人,我的三圍是:)


智能機器人.自報三圍()

老師的答案是這樣的:

# 請直接運行體驗代碼

class 智能機器人():
    胸圍 = 33
    腰圍 = 44
    臀圍 = 55
    
    def 打招呼():
        print(主人你好!)
    
    def 賣萌():
        print(主人,求抱抱!)
    
    def 生氣():
        print(主人,我要報警了!)
        
    @classmethod
    def 自報三圍(cls):
        print(主人,我的三圍是:)
        print(胸圍: + str(cls.胸圍))
        print(腰圍: + str(cls.腰圍))
        print(臀圍: + str(cls.臀圍))
        print(哈哈哈哈哈,下面粗上面細,我長得像個圓錐。)

智能機器人.自報三圍()

這個練習中,類方法“自報三圍”通過cls的格式,取得了類屬性“胸圍、腰圍、臀圍”的值並打印了出來。這個過程中,數據是按箭頭方向流轉的:

在實際編程中,通過【數據流轉】,我們還能讓類為我們做更多事情。

給類方法傳參

首先,既然函數能傳遞參數,類方法能不能傳遞參數呢?答案是肯定的。我們談一談如何給類方法傳參。

類方法僅使用外部參數

我們可以給函數傳遞參數被函數內部使用,就像這樣:

def add_100(num):
    sum = num + 100
    print(計算結果如下:)
    print(sum)

num = 1
add_100(num)
計算結果如下:
101

類方法和函數類似,也可以傳遞參數。我們把上面的函數"收編",改造成類中的方法,代碼會變成這樣:

# 請直接運行並體驗代碼效果
class 加100類():
    def 加100函數(參數):
        總和 = 參數 + 100
        print(計算結果如下:)
        print(總和)

參數 = 1
加100類.加100函數(參數)

這裏的加100類()中的加100函數,只使用了外部的參數,沒有使用類屬性,所以格式上不需要@classmethodcls

讓我們做個練習。這裏有一個函數,運行起來可以“念詩”:

一首詩 = [《蔔算子》,我住長江頭,,君住長江尾。,日日思君不見君,,共飲長江水。]

def 念詩函數(參數):
    for i in 參數:
        print(i)

念詩函數(一首詩)

請你把上面的代碼改造成類方法:

首詩 = [《蔔算子》,我住長江頭,,君住長江尾。,日日思君不見君,,共飲長江水。]
class 念詩類():
    def 念詩函數(參數):
        for i in 參數:
            print(i)

念詩類.念詩函數(一首詩)

和函數不同的是,類方法還可以利用類屬性作為參數,也就是從類的內部給自己傳遞參數。

類方法僅使用內部參數

課堂開始的時候有一個智能機器人的例題,就是從類的內部給自己傳遞參數。我們運行代碼體驗一下:

# 請直接運行並體驗代碼效果
class 智能機器人():
    胸圍 = 33
    腰圍 = 44
    臀圍 = 55

    @classmethod
    def 自報三圍(cls):
        print(主人,我的三圍是:)
        print(胸圍: + str(cls.胸圍))
        print(腰圍: + str(cls.腰圍))
        print(臀圍: + str(cls.臀圍))
        print(哈哈哈哈哈,下面粗上面細,我長得像個圓錐。)

智能機器人.自報三圍()

我們來做個練習,這是剛才的念詩類方法

一首詩 = [《蔔算子》,我住長江頭,,君住長江尾。,日日思君不見君,,共飲長江水。]

class 念詩類():
    def 念詩函數(參數):
        for i in 參數:
            print(i)

念詩類.念詩函數(一首詩)

然後我們把變量一首詩從類的外部放到類的內部,請你調整代碼,讓念詩類()能夠從內部獲得參數,實現和之前相同的念詩功能。提示:可參考上述機器人的例子

class 念詩類():
    一首詩 = [《蔔算子》,我住長江頭,,君住長江尾。,日日思君不見君,,共飲長江水。]

    @classmethod
    def 念詩函數(cls):
        for i in cls.一首詩:
            print(i)


念詩類.念詩函數()

當然,類方法可以同時使用內部參數和外部參數,我們接著看。

老師寫了一個加100類

# 請直接運行並體驗代碼效果
class 加100類():
    變量 = 100
    
    @classmethod
    def 加100函數(cls,參數):
        總和 = cls.變量 + 參數
        print(加100函數計算結果如下:)
        print(總和)

參數 = int(input(請輸入一個整數:))
加100類.加100函數(參數)

這個類一共接受了兩個參數,一個是用戶輸入的外部參數,另一個是cls這個內部參數

另外提一下,當類方法要使用多個外部參數時,我們要多預設幾個參數位置。比如:

# 請直接運行並體驗代碼效果
class 加100類():
    變量 = 100
    
    @classmethod
    def 加100函數(cls,參數1,參數2,參數3):
        總和 = cls.變量 + 參數1 + 參數2 + 參數3
        print(加100函數計算結果如下:)
        print(總和)

參數1 = int(input(請輸入一個整數:))
參數2 = int(input(請輸入一個整數:))
參數3 = int(input(請輸入一個整數:))

加100類.加100函數(參數1,參數2,參數3)

我們再做個練習吧~

你的目標是:改造這段念詩代碼,讓念詩類.念詩函數()可以接受外部參數,且運行效果應如下:

念給張三的詩:
《蔔算子》
我住長江頭,
君住長江尾。
日日思君不見君,
共飲長江水。
class 念詩類():
    一首詩 = [《蔔算子》,我住長江頭,,君住長江尾。,日日思君不見君,,共飲長江水。]
    
    @classmethod
    def 念詩函數(cls,參數1):
        print(念給+參數1+的詩:)
        for i in cls.一首詩:
            print(i)
           


念詩類.念詩函數(張三)

到這裏,給類方法傳參的知識全部講完了,讓我們總結一下

技術分享圖片

接下來我們要講解一下,如何增加/修改類屬性。

增加/修改類屬性

有兩種途徑來增加或修改類屬性。一種是從內部,用類方法去增加/修改;另一種是從外部,用類.變量 = xx直接增加/修改類屬性。

從外部增加/修改屬性

我們先看看從外部直接增加/修改類屬性:

# 請直接運行並體驗代碼效果

class 類A():
    pass


類A.變量1 = 100
print(類A.變量1)

類A()是一個空類(裏面的pass語句代表“什麽都不做”),利用類A.變量1,我們在外部給類A()添加了一個類屬性變量1,然後使用print語句把類屬性打印了出來。

我們來做個練習,請你觀察以下代碼,然後判斷它的運行結果

變量1 = 15
#這是類外部的變量1
變量2 = abc

class 類A():
    變量1 = 100
    #這是類屬性變量1

變量1 = 類A.變量1
類A.變量2 = 變量2

print(類A.變量1)
print(類A.變量2)
我們要區分兩個變量,雖然名字相同,但是類外部的變量1和類屬性變量1是兩個不同的變量。變量1 = 類A.變量1是把類屬性100重新賦值給了類外部的變量1,類屬性變量1的值沒有改變,還是100。

類A.變量2 = 變量2,是為類A增加了一個類屬性變量2,它的值等於外部的變量2也就是abc

我們再做一個練習。請你先體驗以下代碼,然後接下來會有一道題目。

# 請直接運行並體驗代碼效果

class 類():
    @classmethod
    def 打印類屬性(cls):
        print(cls.變量)

類.變量 = input(請輸入字符串:)
類.打印類屬性()

剛才你運行的代碼,先利用input函數從外部接收了一個字符串,並通過賦值的方式保存為了類屬性類.變量。然後利用類方法類.打印類屬性()打印出了這個外部輸入的字符串。

接下來,我們要做一個“幸運數翻倍”小程序,這個程序能接收外部輸入的幸運數字,然後翻888倍打印出來。程序運行效果如下

你的幸運數是多少?請輸入一個整數。(用戶輸入:66)
好的,我把它存了起來,然後翻了888倍還給你:58608

class 幸運():
    @classmethod
    def 好運翻倍(cls):
        
        cls.a=str(cls.幸運數*888)
        print(好的,我把它存了起來,然後翻了888倍還給你:+cls.a)
幸運.幸運數 = int(input(你的幸運數是多少?請輸入一個整數:))
幸運.好運翻倍()

這是自己寫的,老師寫的如下


class 幸運():
@classmethod
def 好運翻倍(cls):
print(‘好的,我把它存了起來,然後翻了888倍還給你:‘ + str(cls.幸運數*888))
# 或者這樣寫也可以:
# print(‘好的,我把它存了起來,然後翻了888倍還給你:%d‘ % (cls.幸運數*888))

幸運.幸運數 = int(input(‘你的幸運數是多少?請輸入一個整數。‘))
幸運.好運翻倍()


到這裏,如何從【類的外部】增加/修改類屬性就比較清楚了,讓我們再看看如何從【類的內部】增加/修改類屬性

從內部增加/修改屬性

我們來體驗一段代碼:讓類方法直接增加/修改類屬性:

# 請直接運行體驗代碼

class 類():
    @classmethod
    def 增加類屬性(cls):
        cls.變量 = input(請隨意輸入字符串:)

類.增加類屬性()

print(打印新增的類屬性:)
print(類.變量)

可以發現,我們直接通過類方法類.增加並打印類屬性()接收外部輸入的字符串,然後新增為類屬性

掌握這個技巧後,我們再做一個練習,這裏是“給張三的詩”代碼

class 念詩類():
    一首詩 = [《蔔算子》,我住長江頭,,君住長江尾。,日日思君不見君,,共飲長江水。]
    
    @classmethod
    def 念詩函數(cls,參數):
        print(念給+ 參數 +的詩:)
        for i in cls.一首詩:
            print(i)

念詩類.念詩函數(張三)

現在希望你能改良這段程序,令它的運行效果如下:

請輸入你想給誰念詩:(用戶輸入“張三”)
念給張三的詩:
《蔔算子》
我住長江頭,
君住長江尾。
日日思君不見君,
共飲長江水。
class 念詩類():
    一首詩 = [《蔔算子》,我住長江頭,,君住長江尾。,日日思君不見君,,共飲長江水。]
    
    @classmethod
    def 念詩函數(cls):
        a = input(請輸入你想給誰念詩:)
        print(念給+a+的詩)
        for i in cls.一首詩:
            print(i)

念詩類.念詩函數()

老師寫的如下

class 念詩類():
    一首詩 = [《蔔算子》,我住長江頭,,君住長江尾。,日日思君不見君,,共飲長江水。]
    
    @classmethod
    def 念詩函數(cls):
        cls.接收人 = input(請輸入你想給誰念詩:)
        print(念給+ cls.接收人 +的詩:)
        for i in cls.一首詩:
            print(i)

念詩類.念詩函數()

到這裏,如何從類的內部和外部增加/修改類屬性就學習完畢了:

現在是人人都會寫代碼的時代,作為班主任的你也不例外,為了錄入學生的成績,你自己寫了一段代碼:

# 請直接運行體驗代碼

class 成績單():
    @classmethod
    def 錄入成績單(cls):
        cls.學生姓名 = input(請輸入學生姓名:)
        cls.語文_成績 = int(input(請輸入語文成績:))

成績單.錄入成績單()
print(成績單.學生姓名 + 的成績單如下:)
print(語文成績:+ str(成績單.語文_成績))

我們現在要做的第一步改裝是,請寫出一個類方法成績單.打印成績單(),代替那兩句print語句,起到同樣的運行效果。

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

成績單.錄入成績單()
成績單.打印成績單()

請繼續改良class 成績單(),讓它可以錄入和打印的信息多一項“數學成績”。要求改良後的代碼運行效果是這樣的:

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

讓我們再接再厲,繼續改良class 成績單(),讓它多一個類方法成績單.打印平均分()。要求改良後的代碼運行效果是這樣的

class 成績單():
    @classmethod
    def 錄入成績單(cls):
        cls.學生姓名 = input(請輸入學生姓名:)
        cls.語文_成績 = int(input(請輸入語文成績:))
        cls.數學_成績 = int(input(請輸入數學成績:))
        
    @classmethod
    def 打印成績單(cls):
        print(cls.學生姓名 + 的成績單如下:)
        print(語文成績:+ str(cls.語文_成績))
        print(數學成績:+ str(cls.數學_成績))
              
    @classmethod
    def 打印平均分(cls):
        print(int(cls.語文_成績+cls.數學_成績)/2)

成績單.錄入成績單()
成績單.打印成績單()
成績單.打印平均分()

第12關類和對象