Re: [問題] Class中有關input的疑問

作者: ddavid (謊言接線生)   2020-04-16 13:39:50
※ 引述《jasonhsu14 (14號星期五的傑森)》之銘言:
: H1=Human1()
: print(H1.BMI())得到當初創建類別時的預設或輸入的數字
: print(H1.BMI(170,80))時,得到不一樣的結果
: 有想過直接在 def BMI(self, h=160, w=50)這樣去寫
: 但這樣又等於重複做了跟__init__一樣的事情
: 所以想詢問有無辦法讓BMI變成一個
: 不輸入的話就會根據最一開始創建類別的預設(或輸入)數值
: 但也可以讓BMI自己另外輸入想要的數字
忽然覺得想說的多了點,還是回文好了。雖然推文給了一個回答,但我覺得最好
還是從概念上來處理這個問題。
H1.BMI()
這寫法很直覺,就是得到H1這個實體本身的BMI,沒有問題。但是:
H1.BMI(170, 80)
請問你覺得這是什麼概念呢?叫H1這個人幫你算算170/80的人BMI是多少?
你可以發現,這兩個用法的概念是衝突的。前者把H1當作一個有BMI的實體,後
者卻只是一個計算BMI的計算器。
那麼我的建議是,應該把實體跟計算器的角色分開來。這個計算器誰來負責呢?
我認為是Human1 class本身,把計算方法定義成Human1的一個靜態方法。當我們要計
算任意一組資料的BMI時,我們呼叫:
Human1.cal_BMI(170, 80)
這個cal_BMI()可以定義為:
@classmethod
def cal_BMI(cls, h, w):
# 計算並return BMI
當我們要得知一個實體H1本身的BMI時,我們呼叫:
H1.BMI()
而這個BMI()則定義為:
def BMI(self):
return Human1.cal_BMI(self.h, self.w)
這樣,我們就既不需要在兩處處理default值(__init__跟BMI),也兼顧了code
的重用性,同時讓實體跟class本體的角色更明確。同時,也不需要寫煩人的邏輯來
判斷輸入值是什麼情況、要用內部值或外部值等等。
BMI要修改計算方式,我們只需要改動cal_BMI(),除非引入了其他參數或要改變
實體與類的計算連接方式(比如說,公開測量時的cal_BMI都是很公正的,但是要讓
每個人自報BMI時都故意低報一點,就像NBA球員偷偷高報身高XD)才會動到BMI()。
作者: cuteSquirrel (松鼠)   2020-04-16 13:46:00
作者: jasonhsu14 (小健人)   2020-04-16 13:53:00
謝謝你的回答,現在才看到XD
作者: drysor   2020-04-16 15:32:00
作者: a0956072892 (henk2525)   2020-04-16 15:43:00
推個
作者: s860134 (s860134)   2020-04-17 20:03:00
物件導向
作者: TuCH (謬客)   2020-04-19 16:40:00
想問一下用Human1.cal_BMI 還是 self.cal_BMI 比較好呢
作者: stucode   2020-04-19 23:32:00
我有不同的看法,在這個例子中 BMI 的計算並無涉及類別或類別變數,因此 cal_BMI() 應該寫成純函數比較合適。如果想把它放進 Human1 類別裡,用 @staticmethod 會是比較好的做法。假如想保留彈性空間,例如你覺得未來有個「新人類」類別會繼承自 Human1,而這個新類別的 BMI計算會參考到類別變數,所以使用 @classmethod 的話,呼叫部分應寫成 self.cal_BMI() 才能讓方法覆載正確發揮作用。寫成 Human1.cal_BMI() 的話反而會鎖死在基礎類別
作者: Arescrow   2020-04-20 15:21:00
作者: stucode   2020-04-20 22:35:00
補個推

Links booklink

Contact Us: admin [ a t ] ucptt.com