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