ARTICLE · 1112216
AI编程(二十三):番茄钟计时器 - 把专注力管起来
👆 点击上方蓝字关注我,获取更多干货
沈阳 · 晴 · 8°C ~ 17°C
☀ 今日天气晴朗,适合学习
📋 文章概览
AI编程(二十三):番茄钟计时器 — 把专注力管起来
学习25分钟、休息5分钟——把第二十一篇的倒计时升级成完整的工作法工具
CHAPTER 01为什么你学不进去,可能不是意志力的问题CHAPTER · 章节内容
你有没有过这种经历:坐下来学习,刚看了两页书,手机亮了;回完消息想继续,脑子里开始想晚饭吃什么;等回过神,半小时没了,书还在第2页。
结论通常是"我意志力太差"。但有个意大利人不同意。
1980年代,Francesco Cirillo发明了一种方法:不要求你学一整天,只要求你专注25分钟。25分钟后休息5分钟,算一个"番茄"。攒够4个番茄,来一次长休息。
就这么简单,但它风靡全世界。原理很反直觉:把"学习一晚上"这种吓人的目标,拆成"熬过25分钟"这种做得到的小任务,大脑就不抗拒了。而且"番茄计数"会让你有种攒金币的快感。
今天我们用程序实现它。这一篇会用到:time模块(第二十一篇刚学的)、datetime(记录日期时间)、循环(工作→休息→工作的循环套循环)、条件判断(长短休息的切换)、文件操作(记录完成统计)、格式化输出(进度显示)。
做完这个,你就有了一个能天天用的专注力工具,还有它生成的每日报告。
CHAPTER 02番茄钟的工作流程CHAPTER · 章节内容
开始 │ ├─ 专注25分钟 🔥 │ └─ 完成 → 番茄数+1 ├─ 休息5分钟 ☕ │ ├─ 番茄数 < 4?→ 回去继续专注 └─ 番茄数 = 4 → 长休息15分钟 → 番茄数清零,重新开始
注意这个结构:外层是"一轮一轮番茄"的循环,内层是"每轮里专注+休息"的流程。循环套循环——第六篇学的东西,今天要正经用一次。
CHAPTER 03先跟AI聊CHAPTER · 章节内容
你的提示词:
用Python写一个番茄钟计时器(命令行版)。规则:专注25分钟,完成后休息5分钟;每完成4个番茄钟,休息15分钟;长休息后番茄计数清零。
用time.sleep每秒递减显示剩余时间(格式mm:ss),专注和休息阶段用不同文字提示。用循环和条件判断实现,中文界面,详细注释。
CHAPTER 04基础版代码CHAPTER · 章节内容
import time# ========== 番茄钟设置 ==========专注时长 = 25 * 60 # 25分钟,换算成秒短休息 = 5 * 60 # 5分钟长休息 = 15 * 60 # 15分钟每轮番茄数 = 4 # 攒够4个来长休息def 倒计时(秒数, 标签): """显示一个带标签的倒计时,数完为止""" 剩余 = 秒数 while 剩余 > 0: print(f"\r{标签} {剩余 // 60:02d}:{剩余 % 60:02d}", end="") time.sleep(1) 剩余 -= 1 print() # 换行,免得接上下一行def 主循环(): """番茄钟的主流程""" print("=== 🍅 番茄钟 ===") print("规则:专注25分钟 → 休息5分钟,攒够4个长休息15分钟") print("按 Ctrl+C 可以随时退出\n") 番茄计数 = 0 # 本轮完成了几个番茄 while True: # 番茄一轮一轮永远转下去 # ---- 阶段1:专注 ---- input("准备好开始专注了吗?按回车开始……") 倒计时(专注时长, "🔥 专注中") 番茄计数 += 1 print(f"🎉 专注完成!这是第{番茄计数}个番茄!\n") # ---- 阶段2:休息 ---- if 番茄计数 % 每轮番茄数 == 0: # 攒够4个:长休息,然后清零 print("🏆 一轮4个番茄全部完成!") 倒计时(长休息, "🌴 长休息") 番茄计数 = 0 else: 倒计时(短休息, "☕ 短休息") print("休息结束,回来继续!\n")主循环()
CHAPTER 05逐行理解CHAPTER · 章节内容
5.1 常量区:设置放在一起
专注时长 = 25 * 60短休息 = 5 * 60长休息 = 15 * 60每轮番茄数 = 4
时长设置全部放在程序开头,用有意义的名字命名。想改成"专注50分钟"?
改第一个数字就行,不用翻代码找魔法数字。把"可配置的东西"和"逻辑"分开,是写代码的好习惯。
5.2 倒计时函数:第二十一篇的老朋友
def 倒计时(秒数, 标签): 剩余 = 秒数 while 剩余 > 0: print(f"\r{标签} {剩余 // 60:02d}:{剩余 % 60:02d}", end="") time.sleep(1) 剩余 -= 1 print()
和上一篇的倒计时一模一样,只是加了个标签参数——专注时显示"🔥 专注中",休息时显示"☕ 短休息"。同一个函数,传不同参数,干不同的活。第七篇说的函数复用,这就是实例。
最后那个光秃秃的print()是换行:倒计时用了\r原地刷新,数完后光标还停在那行上,补个换行让后面的输出从新行开始。小细节,但没有它输出会挤成一团。
5.3 取模判断:什么时候长休息
if 番茄计数 % 每轮番茄数 == 0:
%是取余数(第二十一篇学过)。番茄计数是4的倍数时(4、8、12……),除以4余数为0,该长休息了。
用取模判断"每N次做一次特殊的事",是循环里的经典技巧:每逢3的倍数打印Fizz、每100条数据存一次盘、每4个番茄长休息……全是这一个套路。
5.4 双层循环
while True: # 外层:番茄无限循环 倒计时(专注时长, ...) # 内层:倒计时自己的循环 ... 倒计时(短休息, ...) # 又一个内层循环
外层循环转一圈 = 一个完整的"专注+休息"。内层的倒计时循环则负责把这25分钟一秒一秒地走完。时间在两层循环里被"切"成了规整的小块——这正是番茄钟的精髓。
5.5 input当"开始按钮"
input("准备好开始专注了吗?按回车开始……")
这招很妙:用input暂停程序,等用户按回车才开始。它既是"确认"(人回来了吗),又是"仪式感"(按下按钮,进入状态)。没有它,程序一启动就倒计时,你去倒杯水回来已经过去3分钟了。
CHAPTER 06运行试试CHAPTER · 章节内容
python 番茄钟.py=== 🍅 番茄钟 ===准备好开始专注了吗?按回车开始……🔥 专注中 24:59
然后把窗口放在屏幕角落,开始干活。25分钟后:
🎉 专注完成!这是第1个番茄!☕ 短休息 04:59
用一天你会发现三个可以改进的地方:
每次专注都是25分钟,但我有时候只想专注15分钟啊 今天到底完成了几个番茄?程序没记住 想看看这一周我每天专注了多少
CHAPTER 07第一个改进:自定义时长CHAPTER · 章节内容
让玩家自己选专注时长。顺便学一个新写法——用字典当菜单:
# 预设方案:字典做菜单时长方案 = { "1": ("标准番茄", 25, 5), "2": ("短冲刺", 15, 3), "3": ("深度工作", 50, 10), "4": ("自定义", None, None) # None表示要手动输入}def 选择时长(): """让用户选择专注时长,返回(专注分钟, 休息分钟)""" print("\n选择专注方案:") for 编号, (名称, 专注分, 休息分) in 时长方案.items(): if 专注分: print(f" {编号}. {名称}(专注{专注分}分钟,休息{休息分}分钟)") else: print(f" {编号}. {名称}") 选择 = input("请选择:").strip() if 选择 not in 时长方案: print("无效选择,用标准番茄") return 25, 5 名称, 专注分, 休息分 = 时长方案[选择] # 自定义:让用户自己输 if 专注分 is None: try: 专注分 = int(input("专注多少分钟(5-120):")) 休息分 = int(input("休息多少分钟(1-30):")) except ValueError: print("输入不对,用标准时长") return 25, 5 # 范围检查 if not (5 <= 专注分 <= 120 and 1 <= 休息分 <= 30): print("超出范围,用标准时长") return 25, 5 print(f"✅ {名称}:专注{专注分}分钟,休息{休息分}分钟") return 专注分, 休息分
主循环开头调用它:
专注分, 休息分 = 选择时长()专注时长 = 专注分 * 60短休息 = 休息分 * 60
几个亮点:
- 字典当菜单
:编号→(名称, 专注, 休息)。比一长串if-elif清爽,加方案只需加一行数据 is None判断:自定义方案的值是 None,看到None就走手动输入分支。None是第四篇学过的"空值",专门用来标记"这里还没东西"- 多层防御
:选错菜单→默认标准;输非数字→默认标准;超范围→默认标准。每一步都有兜底,程序永远能给出一个可用的时长,绝不卡死 try...except包两个输入:一句except接住两个input的错,谁出错都走兜底
CHAPTER 08第二个改进:完成统计 — 程序记住你的战绩CHAPTER · 章节内容
现在程序重启就忘了今天攒了几个番茄。用第九篇的文件操作解决——每次完成番茄,就往文件里记一笔:
import jsonfrom datetime import datetime记录文件 = "番茄记录.json"def 加载记录(): """读取历史记录,返回 {日期: 番茄数} 的字典""" try: with open(记录文件, "r", encoding="utf-8") as f: return json.load(f) except FileNotFoundError: return {} # 没有记录文件就从空开始 except json.JSONDecodeError: print("⚠️ 记录文件损坏,重新开始") return {}def 记录一个番茄(记录): """完成一个番茄,记录到今天名下""" 今天 = datetime.now().strftime("%Y-%m-%d") 记录[今天] = 记录.get(今天, 0) + 1 # 今天的数量+1 # 立刻存盘,程序崩了记录也不丢 with open(记录文件, "w", encoding="utf-8") as f: json.dump(记录, f, ensure_ascii=False, indent=2) return 记录[今天]
在主循环里,专注完成之后调用:
番茄计数 += 1今日总数 = 记录一个番茄(记录)print(f"🎉 专注完成!第{番茄计数}个番茄(今天累计{今日总数}个)")
数据结构就是一个字典:{"2025-01-15": 5, "2025-01-16": 3, ...}——日期做键,当天番茄数做值。第二十二篇"按天分组累加"的同款结构,这次连分组都省了:天然按天分组,因为键就是日期。
注意记录[今天] = 记录.get(今天, 0) + 1——又是那个"取不到当0"的老套路。今天的第一个番茄:get返回0,加1存1。第二个:get返回1,加1存2。
每次完成立刻存盘,不等退出。这样程序中途崩溃(或者你直接关窗口),已完成的番茄也都在。重要的数据,尽早落盘——这是真实软件的常规做法。
CHAPTER 09第三个改进:日报表 — 看看这周的自己CHAPTER · 章节内容
有了记录文件,就能做报表了。加一个"查看统计"功能:
def 查看统计(): """显示最近7天的番茄统计""" 记录 = 加载记录() if not 记录: print("📭 还没有记录,先完成一个番茄吧!") return print("\n📊 最近7天专注报告") print("=" * 38) # 生成最近7天的日期列表 from datetime import timedelta 今天 = datetime.now() 总番茄 = 0 总时长 = 0 for 往前几天 in range(6, -1, -1): # 6天前、5天前……今天 日期 = (今天 - timedelta(days=往前几天)).strftime("%Y-%m-%d") 数量 = 记录.get(日期, 0) 总番茄 += 数量 总时长 += 数量 * 25 # 按标准番茄算时长 # 用方块画个迷你柱状图 条 = "🍅" * 数量 if 数量 else "—" 星期名 = ["一", "二", "三", "四", "五", "六", "日"][ (今天 - timedelta(days=往前几天)).weekday()] print(f" 周{星期名} {日期} {数量}个 {条}") print("=" * 38) print(f" 7天总计:{总番茄}个番茄,约{总时长 // 60}小时{总时长 % 60}分钟") if 总番茄: print(f" 日均:{总番茄 / 7:.1f}个")
新知识点:timedelta日期运算
from datetime import timedelta日期 = (今天 - timedelta(days=往前几天)).strftime("%Y-%m-%d")
timedelta(days=3):表示"3天"这个时间段 - 日期 - timedelta
:日期减去3天,得到3天前的日期
datetime模块能直接做日期加减,不用你自己算"这个月有没有31号"。第七篇说import能省很多事,这就是例子——日期计算这种麻烦事,标准库早就帮你做好了。
新知识点:weekday()
(今天 - timedelta(days=往前几天)).weekday()
weekday()返回星期几的数字:周一=0,周二=1……周日=6。用它当列表下标(星期名[数字]),就把数字变成"一二三四五六日"。数字→下标→文字,这个转换链条第四篇学过(数据类型+列表)。
画个迷你图表
条 = "🍅" * 数量 if 数量 else "—"
字符串乘法(第二十一篇进度条用过):几个番茄就画几个🍅。if 数量 else "—"是三元表达式——"有条件的选择"的紧凑写法。数量是0就画个横杠(0乘任何字符串是空字符串,光秃秃不好看)。
输出效果:
📊 最近7天专注报告====================================== 周一 2025-01-13 3个 🍅🍅🍅 周二 2025-01-14 5个 🍅🍅🍅🍅🍅 周三 2025-01-15 0个 — 周四 2025-01-16 4个 🍅🍅🍅🍅 周五 2025-01-17 2个 🍅🍅 周六 2025-01-18 0个 — 周日 2025-01-19 1个 🍅====================================== 7天总计:15个番茄,约6小时15分钟 日均:2.1个
一周的专注情况一目了然。数据被看见,才会被改变——这就是报告的意义。
CHAPTER 10几个值得注意的设计决定CHAPTER · 章节内容
回头看整个程序,有几个决定值得琢磨:
1. 记录用字典而不是列表。如果用列表存[{"日期":..., "数量":...}],查"今天有几个"得遍历整个列表。
用日期做键的字典,记录.get(今天, 0)一步到位。数据结构跟着查询方式选——总是按键查,就用字典。
2. 完成即存盘。 不是退出时才保存,而是每完成一个番茄立刻写文件。多花几毫秒,换来崩溃不丢数据。
3. 倒计时做成函数,专注和休息共用。 加个标签参数就区分了场景。如果专注和休息各写一遍倒计时,代码直接多一倍。
4. 每层输入都有兜底。 选错菜单、输错数字、超出范围,全部有默认值接住。用户怎么折腾,程序都能给出可用的时长。
CHAPTER 11回顾一下用到了什么REVIEW · 知识回顾
CHAPTER 12今日小练习CHAPTER · 章节内容
练习1:暂停功能
专注到一半来电话了怎么办?现在的程序没法暂停。
加一个功能:倒计时期间用户按回车可以暂停,再按回车继续。(提示:这是个难题——time.sleep期间程序听不见键盘。
可以每秒醒来时用某种方式检查键盘。先问问AI有什么办法,你会学到"非阻塞输入"这个概念。做不出来也没关系,思考过程本身就是收获。)
练习2:导出周报
写一个函数,把本周(周一到周日)的记录导出成一个文本文件"周报.txt",内容包括每天的番茄数、总计、日均、最好的一天是哪天。提示:"w"模式写文件,max()函数找最大值(配字典的.get用:max(记录, key=记录.get))。
练习3:任务标签
让每个番茄可以贴标签:开始专注前输入"这25分钟做什么"(如:写论文、刷数学题),记录改成{"2025-01-15": {"写论文": 2, "刷数学题": 3}}——字典套字典。统计时能看到"这周写论文花了几个番茄"。想想哪些函数要跟着改?
下一篇(阶段收官):个人档案管理器 — 把这一路学的所有东西装进一个程序:证件信息、账号密码、联系方式,增删改查、搜索统计、加密存储、导出报表。这是阶段2的毕业作品。
📌 流程总结

既然看到这里了,如果觉得有用,随手点个赞、推荐、转发三连吧
点赞
推荐
转发
THANKS FOR READING