Skip to main content

moregeek program

场景编程集锦 - bmi指数与健身达人-多极客编程

1. 场景描述


BMI与健身达人4.png
  BMI指数(身体质量指数,英文Body Mass Index)是用体重公斤数除以身高米数的平方得出的数字,是目前国际上通用的衡量人体胖瘦程度以及是否健康的一个标准。“身体质量指数”这个概念,是由19世纪中期的比利时数学家凯特勒最先提出来的,BMI指数的计算公式:
$BMI = weight / height^2$
其中weight体重的度量单位是公斤,height身高的度量单位是米。
  BMI指数的设计初衷是一个用于公共健康研究的统计工具。如果我们需要知道肥胖与某一疾病的致病原因是否相关时,就可以把病人的身高和体重换算为BMI值,再找出BMI值与病发率是否有线性关系。不过,随着医学科技的发展和进步,现在BMI值只是一个参考值,要检测一个人是否肥胖有了更加科学和先进的检测手段。因此BMI的角色也在慢慢地改变,从医学上的用途逐步变为一般大众的纤体指标。事实上,对于健康达人或者是普通的健身爱好者来说,BMI指数已经成为了衡量健身成效的重要标准。
接下来,我们使用Python来编写一个基于图形界面的BMI计算器。




2. 编程思路


2.1 计算公式


$BMI = weight / height^ 2$


2.2 判断标准


BMI 值中国标准含义如下:BMI <= 18.4 偏瘦;18.4 < BMI < 24 正常;24.0 <= BMI <28 过重; >= 28 肥胖。


2.3 健康建议


  我们可以针对各种形体人群给出相关的健康建议。需要强调的是这些健康建议均取材于互联网,为编写程序的需要,仅供参考:
偏瘦:适度参加体育运动,特别是要多吃鱼、蛋和奶类等各类健康食品。
正常:注重适度运动,平衡的饮食结构,食物多样化,讲究粗细合理搭配。
超重:建议加强体育锻炼,注重食物搭配,特别是少吃高脂肪、高蛋白、含糖高食品,每天40分钟运动。
肥胖:加强体育锻炼,调整饮食结构,少吃或者不吃高脂肪、高蛋白、含糖量高食品,每天40分钟运动。
我们要把这些健康建议保存到文本文件suggestions.txt中,便于以后可以简单地使用Windows Notepad记事本程序就可以修改和完善这些健康建议。而不必修改Python源代码程序,实现数据与程序的分离。为了与我们的程序配套,这个文件保存时需要使用utf8的文件格式。




3. 代码编写


本程序由4个文件组成,它们是:
bmi.py :BMI计算器的图形界面程序。
bmi_base.py:BMI计算器的一些基础函数模块。
suggestions.txt:存放一些与形体相关的健康建议。
calculator.png:BMI计算器的图片文件。


bmi.py 模块的源代码程序


"""
bmi.py : BMI的前世今生
"""
from tkinter import *
import tkinter.messagebox as msg_box
from common.bmi_base import *

def calculate():
""" 计算 BMI值"""
try:
height = float(v_height.get())
weight = float(v_weight.get())
except ValueError:
msg_box.showinfo('提示', '检查数据:身高或体重!')
else:
bmi = calc_bmi(height, weight)
report = check_report(bmi)
advice = make_suggestion(report)
v_bmi.set(str(round(bmi, 1)) + ' ' + report)
info_area.delete("1.0", END)
info_area.insert("1.0", advice)

def reset():
"""清除输入域内容"""
v_height.set('')
v_weight.set('')
v_bmi.set('')
info_area.delete("1.0", END)
lbl_height.focus()

def initialize():
"""初始化屏幕内容"""
v_height.set('1.70')
v_weight.set('65')
lbl_height.focus()
calculate()

if __name__ == '__main__':
root = Tk()
root.title('BMI 计算器')
root.geometry('350x350+500+300')
# 设置初值
v_height = StringVar() # ①
v_weight = StringVar()
v_bmi = StringVar()
v_bmi.set('')
# 定义图片
photo = PhotoImage(file='calculator.png') # ②
lbl_banner = Label(root, image=photo, compound='top', width=340, height=120)
lbl_banner.grid(row=0, column=0, columnspan=4, sticky=N + S + E + W)
# 显示身高提示和输入身高
Label(root, text='身高 (m)').grid(row=1, column=1, pady=5, sticky=E) # ③
lbl_height = Entry(root, textvariable=v_height) # ④
lbl_height.grid(row=1, column=2) # ⑤
# 定义体重提示和输入体重
Label(root, text='体重 (kg)').grid(row=2, column=1, sticky=E)
Entry(root, textvariable=v_weight).grid(row=2, column=2)
# 定义功能按钮
Button(root, text='计算', width=8, command=calculate).grid(row=6, column=1, pady=6, sticky=E) # ⑥
Button(root, text='清空', width=8, command=reset).grid(row=6, column=2)
# 定义结果显示字段
Label(root, text='BMI').grid(row=5, column=1, pady=5, sticky=E)
Entry(root, textvariable=v_bmi).grid(row=5, column=2)

Label(text='健康建议').grid(row=8, column=1, pady=5, sticky=E)
info_area = Text(width=20, height=4, font=("微软雅黑", 9)) # ⑦
info_area.grid(row=8, column=2)
# 防止屏幕开"天窗"
initialize() # ⑧
# 进入事件驱动模式
root.mainloop() # ⑨


重要函数说明如下:
函数calculate():计算bmi指数,获取形体诊断结果,提取相关的健康建议。
函数reset():清除BMI计算器界面中的输入域的内容。
函数initialize():初始化界面内容,自动计算一个案例,填充屏幕内容。
重要语句说明如下:
语句①定义与界面控件联动的变量内容,也就是说当屏幕界面控件Entry输入域内容发生变化,将自动映射到关联的变量中,实现同步更新。
语句②加载图片以便与有关屏幕控件关联。
语句③定义有关标签控件,以便存放文本字符串。
语句④定义一个输入域控件,并与变量关联,实现数据同步更新。
语句⑤把控件放到屏幕中的指定位置,这里使用tkinter 的grid布局方式。
语句⑥定义按钮实现与函数的关联绑定。意味着当你鼠标点击这个按钮,将自动执行在参数command中指定的函数代码。
语句⑦使用控件Text定义多行的文本输入框,既能输入内容,又可显示文本。
语句⑧执行初始化的案例计算,并使用计算结果填充屏幕内容,避免在图形界面上开“天窗”,留下空白内容,它会给人造成界面不友好的印象。
语句⑨程序进入事件驱动模式。也就是说当用户点击屏幕界面中的控件时,将执行不同的程序代码。


bmi_base.py 模块的源代码


"""
bmi_base.py : BMI计算器可重用代码
"""
__all__ = ['calc_bmi', 'check_report', 'make_suggestion'] # ①
suggestions = {}

def decorate_bmi(func): # ②
"""
扩展calc_bmi()函数功能的装饰器
"""
def wrapper(height, weight):
if is_valid(height, weight):
return func(height, weight)
else:
return -1
return wrapper

@decorate_bmi # ③
def calc_bmi(height, weight):
"""
height : 计量单位是米
weight : 计量单位是公斤
"""
bmi = weight / height ** 2
bmi = round(bmi, 1)
return abs(bmi)

def is_number(number):
"""
判断 number 是数字
"""
if isinstance(number, int) or isinstance(number, float): # ④
return True
else:
return False

def is_valid(height, weight):
"""
判断 height,weight有效性
"""
if height and is_number(height) and is_number(weight):
return True
else:
return False

def check_report(bmi):
"""
bmi : BMI 指数值
report : 形体评测结果
"""
report = '正常'
if bmi < 18.5:
report = '偏瘦'
elif 18.5 <= bmi < 24:
report = '正常'
elif 24 <= bmi < 28:
report = '超重'
elif bmi >= 28:
report = '肥胖'
return report

def load_suggestions(file_name):
"""加载健康建议"""
with open(file_name, encoding='utf-8') as file: # ⑤
for line in file:
key, value = line.split(':') # ⑥
suggestions[key.strip()] = value.strip() # ⑦

def make_suggestion(report):
"""形成健康建议"""
if not suggestions:
# 一次性加载健康建议
load_suggestions('suggestions.txt')

if report in suggestions:
return suggestions[report]
else:
return None


重要函数说明:
函数load_suggestions():从文本文件suggestions.txt中读入健康建议,以字典的方式保存,供后续程序访问。
函数make_suggestion():针对不同的体型,生成不同的健康建议。
函数def calc_bmi(height, weight):计算BMI值的函数,需要注意的是调用此函数,将自动执行该函数的装饰器函数decorate_bmi(),以便对height和weight参数的有效性进行检测。
函数decorate_bmi():是一个装饰器函数,用于对calc_bmi()函数的参数进行有效性检测,以增强程序执行的容错能力。
函数check_report(bmi):通过对bmi值进行判断,获得形体类型的结论报告。
函数is_number(number):判断参数number是否是数字。
函数is_valid(height, weight):判断身高height和体重weight参数的有效性。
重要语句说明:
语句①定义本模块中提供的公共接口函数,即是可由其他程序模块调用的函数,以此实现代码重用。
语句②定义装饰器函数。
语句③将装饰器函数decorate_bmi()与被装饰函数calc_bmi(height, weight)建立绑定关系,当程序调用函数calc_bmi()时,首先要调用装饰器函数decorate_bmi(),然后再执行calc_bmi()函数。使用装饰器功能,我们可以在不修改calc_bmi()函数代码的情况下,扩展其功能。这里相当于利用装饰器是实现了对函数calc_bmi()的输入参数height和参数weight进行的合法性检查。
语句④判断某个变量是否是整数或者浮点数。
语句⑤以utf8的方式打开文件,供后续处理。这里需要强调的是文件suggestions.txt是以utf8的格式保存的文本文件。
语句⑥以冒号为分隔符,解析形体类型和健康建议的内容。
语句⑦以形体类型为键,健康建议为值,创建字典suggestions有存放健康建议,供后续代码使用。




4. 执行效果


4.1 程序结构


模块bmi.py、suggestions.txt和calculator.png存放在当前目录:D:\cases\BMI指数的前世今生,而bmi_base.py则是以Python包的形式,存放在目录common中。


D:\cases\BMI指数与健身达人>dir
2022/12/08 11:47 2,442 bmi.py
2020/12/04 17:49 75,504 calculator.png
2022/12/08 14:33 <DIR> common
2022/12/08 11:59 473 suggestions.txt

D:\cases\BMI指数与健身达人>

查询Python包文件内容


D:\cases\BMI指数与健身达人>cd common
D:\cases\BMI指数与健身达人\common>
D:\cases\BMI指数与健身达人\common>dir
2022/12/08 14:33 1,867 bmi_base.py
2022/04/01 07:34 106 __init__.py
D:\cases\BMI指数与健身达人\common>

4.2 执行程序


D:\cases\BMI指数与健身达人>python bmi.py

将显示以下界面,你可以根据提示进行操作。
image.png
  经过测试表明,BMI计算器完全达到甚至超越了设计要求。更为重要的是BMI计算器提供了比较完善的容错机制,那就是对输入参数height和weight的有效性检测。如果留意的话,你会发现这样一个事实:往往一个程序的容错处理程序代码量不少于10%。如果一个程序尤其是具有商业用途的产品没有适当的容错机制的话,容易引发程序执行中的意外终止。这些现象通常会被客户或者用户认为程序中存在bugs,程序很low,最起码会认为程序员不够专业!



©著作权归作者所有:来自51CTO博客作者罗杰_重庆的原创作品,请联系作者获取转载授权,否则将追究法律责任

场景编程集锦 - 捏紧你的钱袋子-多极客编程

1. 场景描述 下面是一通电话的通话内容: 陌生人:“李总,最近还好吗?” 李总:“您是哪一位?” 陌生人:“我的声音听不出来啦?” 李总:“有点耳熟,想不起来。” 陌生人:“猜猜我是谁?” 李总:“想起来啦,你是猪二娃!” 陌生人:“对啊!” 李总:“猪二娃两年前就死啦!” 陌生人狠狠地挂断了电话。   哈哈哈,高手在民间!想必电话那头的陌生人肺都要气炸了。这是一个典型的电信诈骗套路,幽默睿智

[oeasy]python0043-多极客编程

八进制(oct)回忆上次内容什么是 转义? 转义转义 转化含义​​\​​ 是 转义字符​​\n​​​、​​\r​​是 转义序列还有什么 转义序列 吗? ​​\a​​是 响铃​​\b​​ 退格键​​\t​​ 水平制表符 tab键​​\v​​​、​​\f​​ 实现喂纸不回车通过 16进制数值 转义 ​​\xhh​​输出 (​​hh​​​)<sub>​​16进制​​​</sub>

python爬虫-第三章-4-利用beautifulsoup模块爬取某网壁纸图库图片-多极客编程

思路:1.提取子页面链接 2.访问子链接页面,提取下载地址 3.访问下载地址下载内容到本地# Demo Describe:数据解析 bs4import timeimport requestsimport randomimport stringfrom bs4 import BeautifulSoupfrom fake_useragent import UserAgentpicType = inpu

场景编程集锦 - 捏紧你的钱袋子-多极客编程

1. 场景描述 下面是一通电话的通话内容: 陌生人:“李总,最近还好吗?” 李总:“您是哪一位?” 陌生人:“我的声音听不出来啦?” 李总:“有点耳熟,想不起来。” 陌生人:“猜猜我是谁?” 李总:“想起来啦,你是猪二娃!” 陌生人:“对啊!” 李总:“猪二娃两年前就死啦!” 陌生人狠狠地挂断了电话。   哈哈哈,高手在民间!想必电话那头的陌生人肺都要气炸了。这是一个典型的电信诈骗套路,幽默睿智

(一)java基础语法-多极客编程

一.基础写法/*使用命令行的方式执行的时候,cmd的默认编码是GBK所以在输入中文的时候需要设置文件的编码格式为ANSI这样不会出现乱码格式*/public class HelloWorld/*java文件的名称必须跟public class的名称保持一致*/{ public static void main(String[] args) /* 1.该代码是所有java程序的入口,如果向执行

[oeasy]python0043-多极客编程

八进制(oct)回忆上次内容什么是 转义? 转义转义 转化含义​​\​​ 是 转义字符​​\n​​​、​​\r​​是 转义序列还有什么 转义序列 吗? ​​\a​​是 响铃​​\b​​ 退格键​​\t​​ 水平制表符 tab键​​\v​​​、​​\f​​ 实现喂纸不回车通过 16进制数值 转义 ​​\xhh​​输出 (​​hh​​​)<sub>​​16进制​​​</sub>

使用file类创建简单的文件目录检索小工具-多极客编程

File类的常用方法 序号 方法描述 1 public String getName() 返回由此抽象路径名表示的文件或目录的名称。 2 public String getParent()****、 返回此抽象路径名的父路径名的路径名字符串,如果此路径名没有指定父目录,则返回 null。 3 public File getParentFile() 返回此抽象路径名的父路径名

shell 命令奇淫技巧,就是有点短-多极客编程

1、在任意目录之间快速移动 你发现自己要在两个或更多目录之间频繁移动,一会切换到这里,一会切换到那里,来回跳转。这些目录之间隔得还挺远,反复输入冗长的路径让人疲惫不堪。 使用内建命令 pushd 和 popd 来管理目录栈,轻松地在目录之间切换。下面是一个简单的示例: $ cd /tmp/tank $ pwd /tmp/tank $ pushd /var/log/cups /var/log/cu

c语言实现三子棋-多极客编程

前言:在此之前我们学习了循环,函数,数组等相关知识,我们来写一个小游戏练练手概述:代码大致分为三部分程序主函数,函数,声明函数(这一点我们在通讯录项目是就介绍过了,将代码分为三部分可以是代码各司其职,不冗余,可读性高),游戏框架大概分为以下几部分,主函数main,菜单函数,初始化棋盘,打印棋盘,玩家走函数,电脑走函数,判断输赢函数,所以我们也会按照这几个部分来讲解,先给大家演示一下,我们是通过输入