从 JavaScript 角度学 Python(8) - BMI 计算(1)

前言

接下来这一篇算是收割前面几个章节的章节小练习,基本上我是尽量规划每过几个章节就有一些小作业、小东西,最主要是希望这个系列不只是学习 Python 而是希望透过实际一些小练习来让加深印象。

小作业

相信许多人在学习程序语言的时候,应该很常遇到 BMI 计算的小作业,不外乎这边我也是一样会使用 BMI 计算当作小练习,而接下来小作业的功能很小,刚刚好适合练习:

https://ithelp.ithome.com.tw/upload/images/20210908/20119486CfSEJ1u4ck.png

当然这边为了完成条件制作,可能会使用到一些前面完全没有聊过、讲过的语法,毕竟作业在制作上都会有一定难度,所以这边也是为了要训练 Google 的技巧,透过 Google 去学习额外的许多知识。

废话也差不多了,接下来先让我们看一段可能、大概、或许、应该你已经看到腻的 BMI 公式:

BMI = 体重(公斤) / 身高2(公尺2)

很好,相信你看到这边你已经非常兴奋的知道怎麽做了。

所以这一篇就到这边结束

前面开玩笑的,怎麽可能就这样结束呢?所以一开始前面就先以平易近人的简易 JavaScript BMI 计算来写一遍,毕竟我们是从 JavaScript 角度学 Python 你说是吧?

(运作逻辑与程序码这边就不再着墨说明。)

// 身高 175 体重 68
((68 / ((175 ** 2) / 100)) * 100).toFixed(2); // 22.20
// 身高 178 体重 75
((75 / ((178 ** 2) / 100)) * 100).toFixed(2); // 23.67
// 身高 161 体重 45
((45 / ((161 ** 2) / 100)) * 100).toFixed(2); // 17.36

前几个章节的函式有聊到可以将重复性的行为给包装起来,上方我们可以注意到,除了 体重身高 是会随着使用者输入而变化之外,其他参数都是固定的,因此我们就可以包装成一个函式直接重复呼叫:

function bmi (kg, cm) {
  console.log('BMI 计算:', ((kg / ((cm ** 2) / 100)) * 100).toFixed(2));
}

bmi(68, 175); // 22.2
bmi(75, 178); // 23.67
bmi(45, 161); // 17.36

看完平易近人的 JavaScript 後,让我们回到我们这一次的目标 Python 吧!

那麽上面的 BMI 计算如果要改写成 Python 的版本又该如何撰写呢?一开始难度先不拉那麽高,让我们一步一脚印慢慢打稳基础之後再来挑战更难的,所以一开始先试着撰写跟 JavaScript 版本一样还没包装成函式之前的方式:

# 身高 175 体重 68
print(68 / ((175 ** 2) / 100) * 100) # 22.20408163265306
# 身高 178 体重 75
print(75 / ((178 ** 2) / 100) * 100) # 23.671253629592226
# 身高 161 体重 45
print(45 / ((161 ** 2) / 100) * 100) # 17.36044134099765

基本上我们可以看到输出的结果中小数点超级的多,但是在这边我们只取小数点第二位。

那...只取小数点第二位的话我们这边该怎麽做呢?在 Python 中有一个函式叫做 round() 可以帮助我们四舍五入取得特定小数点:

round(x, y)
  • x 要四舍五入的表达式
  • y 要取得小数点第几位的表达式

因此接下来我们就直接套用 round 函式:

print(round(68 / ((175 ** 2) / 100) * 100, 2)) # 22.20
print(round(75 / ((178 ** 2) / 100) * 100, 2)) # 23.67
print(round(45 / ((161 ** 2) / 100) * 100, 2)) # 17.36

要注意 round 函式若是没有传入 y 参数的话,预设是会直接将小数点全部四舍五入:

print(round(68 / ((175 ** 2) / 100) * 100)) # 22
print(round(75 / ((178 ** 2) / 100) * 100)) # 24
print(round(45 / ((161 ** 2) / 100) * 100)) # 17

那麽透过上面程序码我们也可以得知基本上也是除了 身高体重 之外都不会有任何变动,所以搭配函式之後我们可以这样写:

def bmi (kg, cm):
  print('BMI 计算结果:', round((kg / ((cm ** 2) / 100)) * 100, 2))

bmi(68, 175) # BMI 计算结果:22.2
bmi(75, 178) # BMI 计算结果:23.67
bmi(45, 161) # BMI 计算结果:17.36

除此之外你也可以试着挑战使用前面所学的 lambda 改写程序码,让整体程序码更短更简洁:

bmi = lambda kg, cm: print('BMI 计算结果:', round((kg / ((cm ** 2) / 100)) * 100, 2))
bmi(68, 175) # BMI 计算结果:22.2
bmi(75, 178) # BMI 计算结果:23.67
bmi(45, 161) # BMI 计算结果:17.36

尝试使用 lambda 之後有没有很想把全部程序码改用 lambda 呢?

https://ithelp.ithome.com.tw/upload/images/20210908/20119486IApcUSJoxh.png

当然如果你不想使用 BMI 计算当作练习的话也可以考虑使用别的,例如:汇率、单位计算等等,假设你很没有想法的话,我个人推荐 这个网站 的计算机,任何一个你都可以去捞出来试着研究制作练习看看。

字串组合

这边也额外聊一下关於字串相加的部分,为什麽会讲到这个呢?主要原因是每个人制作作业呈现的方式不一定,而这边可能会遇到一些小雷点,所以就顺便聊一下关於字串组合的部分。

在前一篇我们已经遇到一个雷点是关於 整数字串 相加的雷点,那麽在早期我们在写 JavaScript 中主要都是使用加号运算子达到字串相加的需求,而这又称之为字串连结 or 字串相加:

console.log('第'+ day +'天');

而在 ES6 之後出了一个非常非常方便的语法叫做样板字面值 (Template literals) 的新语法,在开发上组合字串时是非常方便的,尤其是组合 DOM 的时候:

console.log(`第${day}天`);

那麽 Python 呢?前面我们已经尝试过所谓的字串连结,如果传入的不是相同型别,例如:整数 (int) 那麽就必须做型别转换:

day = 1
print('第'+ str(day) +'天')

而这种字串相加的方式其实非常麻烦,你必须一直输入 '"+ 等符号,那...Python 也有跟 JavaScript 一样类似的样板字面值 (Template literals) 语法吗?严格说起来是有的,只是在 Python 中称之为「 字串格式化(String formatting) 」:

day = 1
print(f'第{day}天')

不知道你有没有注意到一件事情,上面的字串格式化范例我并没有使用 str() 做型别转换,但是上面范例确实是不会出现错误的,因为字串格式化会自己帮你传入的任何东西都转换为 String 型别。

你有没有感觉到字串格式化方便方便超多!

https://ithelp.ithome.com.tw/upload/images/20210908/20119486BgG0kKADR5.png

主要使用的方式是在字串最前方加上一个小写 f or 大写 F,接着使用 {} 插入要组合的表达式(expression),例如像是变数也可以:

day = 1
print(f'第{day}天')

刚刚也有提到 {} 内只接受表达式,所以 lambda 也是可以的,只是要记得用类似 IIFE 写法:

print(f'我叫做{ (lambda name: name)("Ray") },你好')

所以上一篇函式的程序码我们可以改成这样:

def fn(day):
  print(f'第{day}天')
  print('起床')
  print('刷牙')
  print('运动')
  print('中午吃饭')
  print('午睡')
  print('下午运动')
  print('晚上吃饭')
  print('晚上洗澡')
  print('睡觉')
  print('---------')

fn(1)

相较之下使用字串格式化会比使用字串连结较简洁好写而且也不用,最後也附上 JavaScript 与 Python 两者都改成相同的 BMI 计算语法比较:

https://ithelp.ithome.com.tw/upload/images/20210908/20119486iDOOANNb4q.png

最後就让我们使用迷因结束今天的回合吧:

https://ithelp.ithome.com.tw/upload/images/20210908/201194869nD9CVpZev.png

优化 BMI 计算

最後的最後,算是简单优化一下 BMI 计算功能而已,延续上方的 BMI 练习题目,我们可以试着在 BMI 中增加判断式,例如:

  • 传入的参数不可以小於 0,当若小於任一参数小於 0 的时候,就要中断程序码并输出讯息
  • 可以判断体重过轻、正常与过重,并输出讯息
def bmi (kg, cm):
  if kg <= 0:
    return print('体重输入不正确')
  if cm <= 0:
    return print('身高输入不正确')

  bmiNum = round((kg / ((cm ** 2) / 100)) * 100, 2)

  if bmiNum < 18.5:
    print(f'你目前的 BMI 是:{bmiNum},介於过轻范围内。')
  elif 18.5 >= bmiNum < 24:
    print(f'你目前的 BMI 是:{bmiNum},介於正常范围内。')
  elif 24 >= bmiNum < 27:
    print(f'你目前的 BMI 是:{bmiNum},介於过重范围内。')
  elif 27 >= bmiNum < 30:
    print(f'你目前的 BMI 是:{bmiNum},介於轻度范围内。')
  elif 30 >= bmiNum < 35:
    print(f'你目前的 BMI 是:{bmiNum},介於中度范围内。')
  elif bmiNum >= 35:
    print(f'你目前的 BMI 是:{bmiNum},介於中度范围内。')
  else:
    print('计算错误。')

bmi(68, 175) # 你目前的 BMI 是: 22.2 介於过重范围内。
bmi(95, 185) # 你目前的 BMI 是: 27.76 介於中度范围内。

今天这一份程序码将会放在这个储存库:https://github.com/hsiangfeng/javascript-to-python

参考文献

作者的话

OH!NO!今天本来要做最後一片花雕醉鸡,结果打开之後发现鸡肉已经臭掉了...事实证明千万不要抓刚刚好过期那天处理全部的鸡肉。

关於兔兔们

兔法无边


<<:  我选择的学习语言跟框架

>>:  电子书阅读器上的浏览器 [Day09] 支援音量键翻页

电子书阅读器上的浏览器 [Day11] 移植 Firefox 阅读模式

这一篇的技术成份稍微高一点点。要谈到的功能,从一开始开发浏览器就有想要做,但是一直找不到比较好的实作...

目录 [10.12更新]

前言 (入门~初阶程度) 篇名"登堂入室",写得冠冕堂皇也只是因为喜欢很台的发音...

Day 0x10 - 整理解密函数与 Webhook api

0x1 前言 昨天确认接到讯息回覆了,今天来把解密函数跟 receive_msg 整理一下 0x2 ...

Day 7 Dart语言-资料型态

资料型态 内建资料型态是构成整个程序的最小型态单位,是程序中不可或缺的元素,而Dart的内建类型主要...

Day9杰森史塔森#vue.js资料库使用json server

延续昨天 今天要来做注册页 把注册的按钮给加了上去 以下是目前页面 那我们就开始搞注册页吧! 跟da...