Featured image of post 從零開始學Python (12) — 物件與類別:我們不一樣,每個人都有不同的際遇(上)

從零開始學Python (12) — 物件與類別:我們不一樣,每個人都有不同的際遇(上)

Day 12 物件與類別:我們不一樣,每個人都有不同的際遇(上)

註:本篇文章同步刊載於iT邦幫忙,為鐵人賽之系列文章。
https://ithelp.ithome.com.tw/articles/10244018

先來解答昨天的問題吧!

  1. 給定兩個字串s跟t,已經知道t的組成,
    是將s的字母打亂以後進行重組,再隨機加上一個字母。
    請用前面所學,找出被加上的那個字母。

以這題來說,我們可以採用內建的方式來處理,
或者使用上一篇提到的Counter()。
首先,讓我們再額外教一對有用的方法:ord()跟chr()。

一般狀況下,程式語言中有時候會提到char(字元)這個單位,
字元的單位就是單一一個英文字母或符號,
是用8個二進位來組成,有定義的有128個不同的字元。
這種字元的表達方是我們稱之為ASCII Code (阿斯奇扣德)。
更詳細的介紹可以看 https://zh.wikipedia.org/wiki/ASCII

我們只需要知道,ASCI Code上面6590是AZ,而97122是az。
而要如何在數字和對應的字元做轉換呢?
在Python中會使用ord() ,也就是order,
將一個字元轉成對應的ASCII Code;
而使用chr() ,則可以將一個數字轉為對應的字元。

利用這點,我們可以取一個長度為26的list,
把a放到list的index 0,b放到list的index 1…,z放到list的index 25。
什麼?你不記得哪個數字對應的ASCII Code?
我們只需要拿ord(‘a’)為基準去相減就好囉!
因此,我們要做的事情就是將s的東西全部當做減1次,
t的東西全部當做加1次,最後因為t只比s多一個字元而已,
留下來計數是1的那個就會是答案囉!

如果先減後加的話,只要我們找到即將由0轉1的時候的那個字元,
就是我們要的答案囉!

1
2
3
4
5
6
7
# 變數後面加冒號,再加資料型態,可以提示輸入的資料型態。
# 但實質上Python並不會強制檢查是否正確。
# "->" 後面接的則是回傳的資料型態
def findTheDifference(s: str, t: str) -> str:
    cnt = [0] * 26
    for c in s:
        cnt[ord(c) - ord('a')] -= 1
1
2
3
    for c in t:
        if cnt[ord(c) - ord('a')] == 0: return c
        cnt[ord(c) - ord('a')] += 1

第二種方法,我們可以直接使用Counter()。

1
2
3
4
5
6
def findTheDifference(self, s: str, t: str) -> str:
    from collections import Counter
    cnt_s = Counter(s)
    cnt_t = Counter(t)
    # most_common(1)[0]取到了唯一的一組,再一個[0]取到key的部分
    return (cnt_t - cnt_s).most_common(1)[0][0]

接下來今天我們要講很多程式語言都有的重要的東西:物件
我們先前講過函式,就是透過自己組合一些程式碼,
做成自己想要的一組功能。
事實上,以Python的角度來說,任何東西都是一種物件,
物件不只有自己的函式(方法) ,還有一些屬於它的變數(屬性)

舉例來說:
如果有一個人叫阿明,另一個人叫小美,
他們都是同一個高中同一班的學生,
所以要考試時,阿明要考數學跟英文,小美也要考數學跟英文。
如果我們要記錄阿明跟小美的成績的話,按照先前所學的,
讀者可能會做類似如下的變數設定:

1
2
3
4
ming_score_math = 55
ming_score_english = 70
mei_score_math = 90
mei_score_english = 88

這麼做有以下幾個缺點:

  1. 字很長XD
  2. 每個變數都要重新再命名一次,如果今天要40個同學都這樣的話,
    寫變數命名就累死了!
    所以為了加以簡化,我們可以用物件的概念來處理這個問題。
    在創造一個物件(object)之前,我們要先定義類別(class)
    什麼是類別呢?
    我們要考慮處理的目標,其共通性是什麼?
    比方說阿明是學生,小美也是學生,
    阿明會有考試的成績,小美也是,同時,阿明和小美都會上課。
    那麼我們就會可以定義一個類別稱為Student
    (一般類別習慣會使用第一個字大寫)。

最基礎的類別定義如下:

1
2
class Student():
    pass # pass表示暫時不做任何事情,但將來必須要將其填補好。

如果要從一個定義產生物件,其用法如下:

1
2
ming = Student() # 阿明是個學生
mei = Student() # 小美是個學生,但和阿明不一樣

上面的ming和mei都是分別都是一個物件,其類別為Student。
以最初始的定義來說,它什麼事情都不會做,接下來我們來加入一些屬性:

1
2
3
class Student():
    def __init__(self, name):
        self.name = name

在一個物件被初始化的時候,最先會呼叫其中的__init__()函式。
它最前面必須要是self開頭,self的概念是指這個物件本體
我們可以透過self.xxx 的方式來取得或修改物件的其他屬性或方法。
注意到除了self以外,我們還增加一個name,
代表當我們呼叫Student()時,其第一個位置傳入的將會是name。
self.name = name 則代表我們要在開始時,
將從外面傳入進來的name的值,
存放進這個物件本體的name的值。

所以我們現在在來修改一下剛剛產生物件的方式:

1
2
3
4
5
ming = Student('阿明') # 阿明是個學生
mei = Student('小美') # 小美是個學生,但和阿明不一樣
# 要使用'.'來取得各自的名字
print(ming.name)
print(mei.name)

除了屬性以外,我們還可以為類別新增一些方法,
其方式基本和前面函式定義的方法一致,只是要加上self。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Student():
    def __init__(self, name):
        self.name = name

    # 可以利用self取得自己這個類別裡面的變數
    def readMyName(self):
        print('聽清楚了,我的名字是' + self.name + '!!!')

ming = Student('阿明')
mei = Student('小美')
print(ming.name)
print(mei.name)
ming.readMyName()
mei.readMyName()

由於物件概念比較需要仔細釐清,我們就分成兩篇來細講,
請務必仔細完成今天的練習呦!

那我們來練習一下題目吧!

  1. 在上述的例子當中,請為類別新增一個字典,名稱為score,
    將該字典用來儲存{‘科目’:’分數’}的各科成績,並修改__init__()的函式,
    在產生阿明及小美時,同時輸入各科成績,
    如未輸入則預設為0分(也就是缺考)。
    阿明的成績分別為:數學55/英文70/物理55
    小美的成績分別為:數學90/英文88/物理100
  2. 承上題,請新增一名Student,其name為’HowHow’,
    數學成績為80,英文成績為60,物理成績為40。
  3. 請為Student新增一個方法,讓兩個Student可以互相比較,
    名稱為compare()。
    例如A.compare(B),假設:
    A的總分高於B -> A的名字 + ‘贏了!’
    A的總分等於B -> ‘什麼?竟然平手?!’
    A的總分小於B -> ‘可…可惡,難道,這就是’ + B的名字 + ‘真正的實力嗎?’

並分別讓阿明和HowHow比較、阿明和小美比較、小美和HowHow比較,
輸出結果。

辛苦啦!我們明天見!

工商時間:

抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)
Python Taiwan的連結第100篇的文章 底下,
公開分享到你的臉書、按讚該篇文章、並留言告訴我說,
「你最喜歡這一整個系列的哪一篇?為什麼?」或
「除了從LeetCode學演算法系列以外,
你還想要看到關於什麼方向的文章?」

超過20則留言的話 (有完成以上步驟的才算),我們就抽一組
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」
課程的免費兌換券進行贈送!

期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)

容筆者工商一下,
「從Leetcode學演算法|進階篇」 開放預購啦!
這次選了40道難度加深的LeetCode題目,
同樣也會細部解說對應的技巧及須要掌握的演算法!
同時這次購買進階篇的話,
額外還加贈**「從Leetcode學演算法|面試篇」** !
當中包含了面試準備須知分享及訪談國內外不同經驗的工程師
讓你不論是想走前端/後端/一般軟工 或者是想找國外的工作
初學想轉職 還是正在工作 ,都能夠從中得到收穫呦!
有興趣的朋友可以使用下面的早鳥優惠~
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」
https://bit.ly/advleetcode

「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠:
https://bit.ly/allleetcode

共發表了 171 篇文章 ‧ 總計 311.6k
使用 Hugo 建立
主題 StackJimmy 設計