iT邦幫忙

6

[自學Python紀錄] HackerRank 新手30天挑戰-Day04

Hi there! 我是嘟嘟~受到前輩啟發,想說可以紀錄一下自己練習的過程,小女子為程式超超菜鳥,此系列非教學文,僅為個人解題筆記,可能有錯誤或未補充詳盡之處,歡迎前輩們不吝指教!也歡迎正在自學的夥伴一起討論學習~


Day 4: Class vs. Instance (類別VS實例)

第4天難度突變,沒學過class所以花了一些時間,也不確定自己有沒有理解錯誤,歡迎指正補充!

題目要求一個Person類別(class),整數的屬性參數為initialAge,指定到實例變數age,若age < 0,則將age設為0然後印出Age is not valid, setting age to 0.,除此之外還要定義兩個方法(method):

  1. yearPasses() : should increase the instance variable ageby 1 (題目有要求3年後再判斷一次,故讓年齡加1)
  2. amIOld() : should perform the following conditional actions:
    • If age< 13, print You are young.
    • If age≧ 13 and age< 18, print You are a teenager.
    • Otherwise, print You are old.

注意: 不要修改到題目原始格式
Note: Do not remove or alter the stub code in the editor.

輸入格式

第一行輸入整數儲存成t,代表測試值的數量,後面t行輸入整數儲存成age,作為類別Person的實例變數。

輸出格式

age ≧ 0 會印出兩行,若age < 0 會印出三行

樣本輸入

4
-1
10
16
18

樣本輸出

Age is not valid, setting age to 0. #因為-1<0,所以要設成0
You are young. #0歲
You are young. #3歲

You are young. #10歲
You are a teenager. #13歲

You are a teenager. #16歲
You are old. #19歲

You are old. #18歲
You are old. #21歲

原始格式

class Person:
    def __init__(self,initialAge):
        # Add some more code to run some checks on initialAge
    def amIOld(self):
        # Do some computations in here and print out the correct statement to the console
    def yearPasses(self):
        # Increment the age of the person in here

t = int(input())
for i in range(0, t):
    age = int(input())         
    p = Person(age)  
    p.amIOld()
    for j in range(0, 3):
        p.yearPasses()       
    p.amIOld()
    print("") #最後這行是系統要判斷是不是和預期輸出一樣,所以不能動到

我的解答

class Person(): #定義類別Person
    def __init__(self, initialAge):
        #定義建構子函式__init__,輸入參數self和initialAge
        if initialAge < 0:
            print('Age is not valid, setting age to 0.')
            initialAge = 0 #如果initialAge小於0則將其改為0
        self.initialAge = initialAge
        #將initialAge指定給變數self.initialAge

    def amIOld(self):
        #定義函式amIOld,參數為self,印出變數self.initialAge的條件式結果
        if self.initialAge < 13:
            print('You are young.')
        elif 13 <= self.initialAge < 18:
            print('You are a teenager.')
        else:
            print('You are old.')
            
    def yearPasses(self):
        #定義函式yearPasses,參數為self,宣告變數self.initialAge = self.initialAge + 1
        self.initialAge += 1

t = int(input())
for i in range(0,t):
    age = int(input()) #宣告輸入值為變數age
    p = Person(age)
    #宣告類別為Person的物件p,將變數age作為參數傳回類別Person的函式中
    p.amIOld() #呼叫函式amIOld,此時p.initialAge = 原initialAge
    
    for j in range(0,3): 
        p.yearPasses() ##呼叫函式yearPasses三次
    p.amIOld() #此時p.initialAge = 原initialAge + 3

執行結果

輸入值

2
-5
24

結果為

Age is not valid, setting age to 0.
You are young. #0
You are young. #3

You are old. #30
You are old. #33

補充:

基本上只要輸入定義函式的部分就好,下面部分題目本來就給好了(怕太難新手打不出來XD),這題重點就是瞭解 class (類別) ,以下整理了一些資料:

class (類別),就是像一個模組,可以產出具有相似特性(屬性Attribute 及方法Method)的實體(物件Object),也有人會說他像是一個蛋糕模子,可以一直套用生產蛋糕,代表之後的大家都可以取用這個類別的設定,達到避免重複設定函式

  • 類別名稱建議為駝峰式大小寫(CamelCase),字母首字為大寫,單字之間不以空格斷開(例:camel case)或連接號(-,例:camel-case)、底線(_,例:camel_case)連結

  • 每個類別有兩種變數: 類別變數(class variables)實例變數(instance variables)

  • def __init__(self, <parameters>):
    這邊代表宣告時會自動執行的函式,也就是宣告類別的"起手式",所以一般會拿來放基礎的屬性設定。(非強制)

  • 類別方法的第一個參數一定是 self ,他是 Python 類別定義中預設的參數,代表建立的物件實體,因此 self.a 與 self.b 都是實體屬性。

  • 存取屬性與執行方法,語法都是利用點號:
    <object>.<attribute> # 存取屬性(變數)
    <object>.<method>() # 執行方法(函式)

  • 題目的Tutorial有提到 Function overloading (函數重載、函數多載),重載函數是函數的一種特殊情況,為方便使用,允許在同一範圍中聲明幾個功能類似的同名函數,但是這些同名函數的形式參數(指參數的個數、類型或者順序)必須不同,也就是說用同一個函數完成不同的功能。參考文章【為什麼Python不支持函數重載?而其他語言大都支持?

  • 參考來源:
    Python 程式設計-第 15 章 物件與類別
    Python類別與例外-高中資訊科技概論教師黃建庭的教學網站
    ↑ 嘟嘟覺得他寫得很淺顯易懂又詳細,還有延伸變化(繼承、多型....比較複雜的還沒有理解,未來可以回來看)
    關於Python的類別(Class)...基本篇-張凱喬-Medium
    Python 入門指南 - 類別
    Python 入門指南 - init()
    Python 使用類別】(像教科書但寫得很清楚)


1 則留言

2
心原一馬
iT邦研究生 5 級 ‧ 2020-04-29 20:42:39

哈囉~ 小馬來支持好友發文囉,
小馬覺得你的比喻不錯呢:
「class (類別)像是一個蛋糕模子,可以一直套用生產蛋糕實體(物件Object)」
已筆記~

真心覺得你筆記整理的蠻好的 ^^

對了,小小糾正一點,
你文章說的類別名稱必須為駝峰式大小寫(CamelCase)
那個應該是程式風格建議,不是強制規定(不這樣寫程式還是可以編譯的)

小馬提出一個問題給你思考,可以一起腦力激盪一下,
你覺得用Class有什麼特別的好處嗎?

比如說為什麼不用一個整數代表人的年齡就好?
多一歲就單純寫個函數yearPasses呢?
例如像這樣:

def yearPasses(age):
    return age + 1

people_one = 15 #設一個人的年齡15歲
people_one = yearPasses(people_one) #他的年齡多一歲

如你所見,用class的語法看似複雜許多,
既然人們會用表示當開發大型程式時應該有某種好處?
你覺得好處是什麼呢?

Pondudu iT邦新手 5 級 ‧ 2020-04-30 12:49:37 檢舉

小馬哥安安!那個比喻是參考資料裡寫的唷XD 我也覺得形容的很貼切呢!

謝謝糾正!!已修改~

用class的好處,在大型程式裡面,使用不同的模組,可以避免掉很多重複的內容(嗎??) 重複宣告類別,套用屬性和函式,直接生成多個物件,像蛋糕模型的概念? 似乎稍微理解,但沒碰過實作,所以還沒辦法體會它的厲害之處>.< 對實例(物件)的概念也不是非常瞭解,想說先有個大概,配合比較有系統的書籍或教學文,回頭複習時會比較清楚XD

再麻煩您提點了!!

心原一馬 iT邦研究生 5 級 ‧ 2020-04-30 14:13:40 檢舉

嗨,嘟嘟:

對對,感覺應該是需要寫過大型程式會比較有感覺,
這邊小馬也分享自己的看法給你參考

對,可以「避免重複的內容」,
用一個蛋糕模子可以做很多蛋糕的感覺,

另分享幾個小馬好處:

  1. 封裝,因為開發大型程式時,可能要團隊合作寫程式,不一定所有的程式都是自己寫,有可能別人寫好的程式碼你需要拿來用。如果把程式包裝成一個物件,你不用完全了解他裡面的程式碼是怎麼寫的,可以直接拿來用 (像是你買了一個電鍋,你不必懂電鍋裡面的構造,還是可以拿電鍋來煮飯)

  2. 語意比較清楚。以這題來說程式太小了,你會覺得宣告成Person類別跟直接寫一個整數people_one = 15代表人的年齡好像沒差,但是當程式大的時候會很容易不知道每個變數代表的意義。比如說人有「年齡」、「性別」、「身高」、…很多種屬性,單獨宣告很多變數可能很亂,定義在Person的屬性裡比較清楚知道它是屬於人的屬性

分享小馬的理解,沒把握講的很好,
也歡迎提出其它看法討論 ^^

Pondudu iT邦新手 5 級 ‧ 2020-04-30 17:26:53 檢舉

謝謝小馬哥用心補充!!

  1. 適合團隊開發,互相使用時能更快上手
  2. 像是整理抽屜時將文具分門別類,清楚表達變數類別和屬性,可讀性較高,也可以更快速瞭解內容

/images/emoticon/emoticon41.gif

我要留言

立即登入留言