今天接着来记录我做过的两道练习题。
第五十五题,延时操作:
#编写一个程序,该程序在暂停一秒后获取当前操作系统时间,并将其转换为'YYYY-MM-DD HH:MM:SS'格式的字符串进行打印
#导入time模块
import time
#获取当前系统时间(暂停前先打印输出)
local_time = time.localtime()
time_str = time.strftime('%Y-%m-%d %H:%M:%S',local_time)
print(time_str)
#将程序暂停执行指定的秒数(1秒)
time.sleep(1)
#获取当前系统时间(暂停后看输出是否延迟一秒)
local_time = time.localtime()
time_str = time.strftime('%Y-%m-%d %H:%M:%S',local_time)
print(time_str)
代码思路分析如下:
题目要求:程序暂停一秒后获取当前系统时间,转换为 'YYYY-MM-DD HH:MM:SS' 格式打印。
我的设计:一个"对照实验"
题目本质是验证 time.sleep(1) 真的能让程序"卡住一秒"。光打印一次时间是证明不了延时生效的,所以我用了实验思维:同一段"取时间、格式化、打印"的代码原样跑两遍,中间只插入一句 sleep(1)------对比两次输出,秒数正好差 1,延时就当场验明正身。代码看着重复,其实重复本身就是证据。
新面孔:strftime ------ 自定义格式的翻译官
51 题里 ctime()、asctime() 翻译出的字符串格式是官方定死的,我没法控制。这题要求严格的 年-月-日 时:分:秒 样式,就得请出 strftime:给我一张格式模板(%Y 四位年、%m 月、%d 日、%H:%M:%S 时分秒),它把 struct_time 拼成完全按模板定制的文本。名字里的 f 是 format,和 54 题的 strptime(p 是 parse,解析)正好是一对反向操作------一个"零件变文本",一个"文本变零件"。
这里我发现一个别扭的坑:strftime 是格式在前、时间在后,而 54 题 strptime 是时间在前、格式在后,两个双胞胎的参数顺序居然是反的,一不留神就传错,我只能靠"f 排前面、p 排后面"这种笨口诀硬记。
和前面题目的联系
time 五连做完正好凑齐一条完整链路:51 题认识三种时间形态,52、53 题用时间戳做减法测性能,54 题把文本翻译回秒数,今天用 sleep 让程序学会"等一等"、用 strftime 学会了指定格式输出------至此三种形态之间的正反向翻译,我全走通了。
总结
一句话:同样的动作做两遍,中间睡一秒,输出差值即证明。这题教给我的不只是 sleep 和 strftime 两个函数,还有一个很朴素的思想:想让程序"证明"什么,就给它做对照组。
第五十六题,实现简单秒表:
#编写一个程序,实现简单秒表功能,该程序在用户按下回车键后开始计时,在用户中断程序后停止计时。
#导入time模块,用于处理时间相关的任务
import time
#打印提示信息
print("按回车键开始计时,中断程序则停止计时")
#等待用户按下回车键
input('准备...')
#定义变量保存计时开始时间
start_time = time.time()
#打印消息表明计时开始
print("计时开始...")
#让程序进入一个无限循环,等待用户中断程序
try:
while True:
# 计算经过的时间
elapsed_time = time.time() - start_time
# 打印经过的时间
print(f'\r经过的时间为:{elapsed_time:.2f}秒', end='') # 这里是一个格式限制,end = '\r' 表示不换行,光标返回行首
# 让程序暂停一秒以每秒更新一次显示
time.sleep(1)
except KeyboardInterrupt:
end_time = time.time()
#计算总时间
total_time = round(end_time - start_time,2)
print(f'\n总时间为:{total_time:.2f}秒', end='')
代码思路分析如下:
题目要求:用户按回车后开始计时,中断程序则停止计时。
我的整体设计:三段接力
这个秒表我拆成"定起点 → 跳动显示 → 中断收尾"三段,用到的全是前几题的旧零件,第一次拼成完整程序。
第一段:用 input() 把计时起点"交给用户的手"。 程序走到 input('准备...') 就会停住,等回车按下的那一刻才继续往下------所以在它的下一行取 time.time() 存为起点,这个起点就是用户说了算的。阻塞式等待当"发令枪",这是我觉得最巧妙的一处复用。
第二段:while True 循环每秒报一次账。 循环体里干三件事:拿现在的时间减去起点得到"已经过了多久"(还是 52 题的三明治掐表思想,只是这次只按头表、尾巴实时算);打印这个数字;sleep(1) 歇一秒再循环------55 题刚学的延时,这次成了秒表的"心跳"。
显示上我碰到了一个真问题:普通 print 每轮换一行,屏幕瞬间刷屏。解法是用光标回行首的 \r 配合不换行的 end='',让新的一行数字原地盖掉旧的,看起来就是同一行在跳动。同时数字固定保留两位小数,宽度恒定,不会一跳一跳地抖动。
第三段:用"意外"当停止按钮。 秒表要能随时停,但循环正在忙着刷新,没法同时听回车------于是我反过来利用崩溃:用户按 Ctrl+C 时 Python 会抛 KeyboardInterrupt,我把整个循环包进 try,用 except 接住它,在其中取最终时间、算总耗时、体面收尾。异常处理第三次上岗:43、44 题接的是 ValueError(输错了),这题接的是"用户主动打断"------原来异常不只是错误,还可以是信号。
总结
一句话:回车定起点,循环报实时,Ctrl+C 收全场。零件全是旧的(input 阻塞、掐表减法、sleep、try/except),拼起来却第一次像个"能用的软件"。这也是我在"边刷新边等按键"这个死局面前,找到的最省事的绕法。