漏发了一个第五十六题的内容,在之前的那个代码块的基础上,我重新优化了一个版本:
# 编写一个程序,实现简单秒表功能:
# 按下回车开始计时,再按一次回车停止并显示计时结果;
# 显示结果后给用户两个选择:再次计时 / 结束程序
# 导入time模块,用于处理时间相关的任务
import time
# 外层while循环支撑"多次计时"的整体流程,直到用户选择结束才break退出
while True:
print('\n===== 简单秒表 =====')
# 第一次回车:开始计时,并记录起始时间
input('按回车开始计时...')
start_time = time.time()
# 第二次回车:停止计时(input会一直等待,回车一按立即向下执行)
input('计时中... 按回车停止并查看结果 >>> ')
# 记录结束时间,算出总耗时并保留两位小数
end_time = time.time()
total_time = round(end_time - start_time, 2)
# 显示本次计时结果
print(f'\n本次经过的时间为:{total_time} 秒')
# 给用户两个选择:y 再次计时,n(或任意其他键)结束程序
choice = input('是否再次计时?(按 y 重新开始 / 按 n 结束):')
if choice.lower() == 'y':
continue # 回到循环顶部,开始新一轮计时
else:
break # 退出循环,程序结束
print('已结束计时,再见!')
这个程序的优化思路如下:
优化目标:按下回车显示计时结果,并在结束后给用户两个选择------再次计时,或结束程序。
不变的核心:掐表原理一模一样
先说没变的部分,好让"优化"有参照。两版底层都是三明治掐表法:任务开始前 time.time() 存起点、结束后再按一次取终点、相减保留两位小数。变的不是"怎么算时间",而是用户怎么操控它。
优化一:停止方式从"中断程序"换成"再按回车"
原版要停表得按 Ctrl+C,触发 KeyboardInterrupt 异常,再用 try/except 接住才算出总时间------这个交互对使用者相当不友好:"中断程序"四个字劝退新人,而且万一哪天真想强制退出,和"正常停表"撞车分不清。优化版改成第二次 input() 等回车:回车一按,阻塞解除,顺手取终点时间。停表从"制造一场意外"变成"走一步流程",try/except 整个都省掉了,代码理解门槛明显降低。
优化二:从"一次性"升级成"可反复"
原版跑完一次就结束,想再测只能重新运行程序。优化版在外面套了一个 while True 大循环,报完结果后追问一句"是否再次计时":答 y 就 continue 回到循环头开启新一轮,答 n(或任意其他键兜底)就 break 体面告别。菜单常驻这个套路,把单次脚本变成了小产品。
优化的代价:我主动放弃了"实时跳动"
这里要坦白一个取舍。原版 while True 循环里每秒刷新一次耗时(配 \r 回行首覆盖显示),屏幕上的数字会跳。优化版做不到------因为 input() 是阻塞的,它死等回车时程序没法同时干"每秒打印"的活。要做"边跳动边等按键"得动 Windows 专用的非阻塞按键检测,对现阶段练习超纲。所以我用一行安静的"计时中..."换掉了跳动效果:手感换简单,值不值看场景------自己练习记录用简单版足够,展示型应用才值得上复杂方案。
总结
一句话:计时内核没动,交互外壳全换------异常当按钮改成回车当按钮、一次性改成无限轮、实时刷新改成阻塞等待。回头看,这次优化其实是把"程序能跑"推进到"人愿意用",代码量差不多,但每一步都在替使用者着想。