夜雨聆风学习资料网

ARTICLE · 1112216

AI编程(二十三):番茄钟计时器 - 把专注力管起来

AI编程(二十三):番茄钟计时器 - 把专注力管起来

👆 点击上方蓝字关注我,获取更多干货

☀️

沈阳 · 晴 · 8°C ~ 17°C

☀ 今日天气晴朗,适合学习

📋 文章概览

AI编程(二十三):番茄钟计时器 — 把专注力管起来

1学习25分钟、休息5分钟——把第二十一篇的倒计时升级成完整的工作法工具
2为什么你学不进去,可能不是意志力的问题
3你有没有过这种经历:坐下来学习,刚看了两页书,手机亮了;回完消息想继续,脑子里开始想晚饭吃什么;等回过神,半小时没了,书还在第2页
4结论通常是"我意志力太差"
51980年代,Francesco Cirillo发明了一种方法:
📝 7966 字⏱ 约 19 分钟阅读📑 深度长文

学习25分钟、休息5分钟——把第二十一篇的倒计时升级成完整的工作法工具

CHAPTER
01
为什么你学不进去,可能不是意志力的问题CHAPTER · 章节内容

你有没有过这种经历:坐下来学习,刚看了两页书,手机亮了;回完消息想继续,脑子里开始想晚饭吃什么;等回过神,半小时没了,书还在第2页。

结论通常是"我意志力太差"。但有个意大利人不同意。

1980年代,Francesco Cirillo发明了一种方法:不要求你学一整天,只要求你专注25分钟。25分钟后休息5分钟,算一个"番茄"。攒够4个番茄,来一次长休息。

就这么简单,但它风靡全世界。原理很反直觉:把"学习一晚上"这种吓人的目标,拆成"熬过25分钟"这种做得到的小任务,大脑就不抗拒了。而且"番茄计数"会让你有种攒金币的快感。

今天我们用程序实现它。这一篇会用到:time模块(第二十一篇刚学的)、datetime(记录日期时间)、循环(工作→休息→工作的循环套循环)、条件判断(长短休息的切换)、文件操作(记录完成统计)、格式化输出(进度显示)。

做完这个,你就有了一个能天天用的专注力工具,还有它生成的每日报告。

CHAPTER
02
番茄钟的工作流程CHAPTER · 章节内容

Code

开始 │ ├─ 专注25分钟 🔥 │    └─ 完成 → 番茄数+1 ├─ 休息5分钟 ☕ │ ├─ 番茄数 < 4?→ 回去继续专注 └─ 番茄数 = 4 → 长休息15分钟 → 番茄数清零,重新开始

注意这个结构:外层是"一轮一轮番茄"的循环,内层是"每轮里专注+休息"的流程。循环套循环——第六篇学的东西,今天要正经用一次。

CHAPTER
03
先跟AI聊CHAPTER · 章节内容

你的提示词:

用Python写一个番茄钟计时器(命令行版)。规则:专注25分钟,完成后休息5分钟;每完成4个番茄钟,休息15分钟;长休息后番茄计数清零。

用time.sleep每秒递减显示剩余时间(格式mm:ss),专注和休息阶段用不同文字提示。用循环和条件判断实现,中文界面,详细注释。

CHAPTER
04
基础版代码CHAPTER · 章节内容

Python

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 常量区:设置放在一起

Python

专注时长 = 25 * 60短休息 = 5 * 60长休息 = 15 * 60每轮番茄数 = 4

时长设置全部放在程序开头,用有意义的名字命名。想改成"专注50分钟"?

改第一个数字就行,不用翻代码找魔法数字。把"可配置的东西"和"逻辑"分开,是写代码的好习惯。

5.2 倒计时函数:第二十一篇的老朋友

Python

def 倒计时(秒数, 标签):    剩余 = 秒数    while 剩余 > 0:        print(f"\r{标签} {剩余 // 60:02d}:{剩余 % 60:02d}", end="")        time.sleep(1)        剩余 -= 1    print()

和上一篇的倒计时一模一样,只是加了个标签参数——专注时显示"🔥 专注中",休息时显示"☕ 短休息"。同一个函数,传不同参数,干不同的活。第七篇说的函数复用,这就是实例。

最后那个光秃秃的print()是换行:倒计时用了\r原地刷新,数完后光标还停在那行上,补个换行让后面的输出从新行开始。小细节,但没有它输出会挤成一团。

5.3 取模判断:什么时候长休息

Python

if 番茄计数 % 每轮番茄数 == 0:

%是取余数(第二十一篇学过)。番茄计数是4的倍数时(4、8、12……),除以4余数为0,该长休息了。

用取模判断"每N次做一次特殊的事",是循环里的经典技巧:每逢3的倍数打印Fizz、每100条数据存一次盘、每4个番茄长休息……全是这一个套路。

5.4 双层循环

Python

while True:                  # 外层:番茄无限循环    倒计时(专注时长, ...)     # 内层:倒计时自己的循环    ...    倒计时(短休息, ...)       # 又一个内层循环

外层循环转一圈 = 一个完整的"专注+休息"。内层的倒计时循环则负责把这25分钟一秒一秒地走完。时间在两层循环里被"切"成了规整的小块——这正是番茄钟的精髓。

5.5 input当"开始按钮"

Python

input("准备好开始专注了吗?按回车开始……")

这招很妙:用input暂停程序,等用户按回车才开始。它既是"确认"(人回来了吗),又是"仪式感"(按下按钮,进入状态)。没有它,程序一启动就倒计时,你去倒杯水回来已经过去3分钟了。

CHAPTER
06
运行试试CHAPTER · 章节内容

Bash

python 番茄钟.py=== 🍅 番茄钟 ===准备好开始专注了吗?按回车开始……🔥 专注中 24:59

然后把窗口放在屏幕角落,开始干活。25分钟后:

Code

🎉 专注完成!这是第1个番茄!☕ 短休息 04:59

用一天你会发现三个可以改进的地方:

  1. 每次专注都是25分钟,但我有时候只想专注15分钟啊
  2. 今天到底完成了几个番茄?程序没记住
  3. 想看看这一周我每天专注了多少

CHAPTER
07
第一个改进:自定义时长CHAPTER · 章节内容

让玩家自己选专注时长。顺便学一个新写法——用字典当菜单:

Python

# 预设方案:字典做菜单时长方案 = {    "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 专注分, 休息分

主循环开头调用它:

Python

专注分, 休息分 = 选择时长()专注时长 = 专注分 * 60短休息 = 休息分 * 60

几个亮点:

  • 字典当菜单
    :编号→(名称, 专注, 休息)。比一长串if-elif清爽,加方案只需加一行数据
  • is None判断
    :自定义方案的值是None,看到None就走手动输入分支。None是第四篇学过的"空值",专门用来标记"这里还没东西"
  • 多层防御
    :选错菜单→默认标准;输非数字→默认标准;超范围→默认标准。每一步都有兜底,程序永远能给出一个可用的时长,绝不卡死
  • try...except包两个输入
    :一句except接住两个input的错,谁出错都走兜底

CHAPTER
08
第二个改进:完成统计 — 程序记住你的战绩CHAPTER · 章节内容

现在程序重启就忘了今天攒了几个番茄。用第九篇的文件操作解决——每次完成番茄,就往文件里记一笔:

Python

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 记录[今天]

在主循环里,专注完成之后调用:

Python

番茄计数 += 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 · 章节内容

有了记录文件,就能做报表了。加一个"查看统计"功能:

Python

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日期运算

Python

from datetime import timedelta日期 = (今天 - timedelta(days=往前几天)).strftime("%Y-%m-%d")

  • timedelta(days=3)
    :表示"3天"这个时间段
  • 日期 - timedelta
    :日期减去3天,得到3天前的日期

datetime模块能直接做日期加减,不用你自己算"这个月有没有31号"。第七篇说import能省很多事,这就是例子——日期计算这种麻烦事,标准库早就帮你做好了。

新知识点:weekday()

Python

(今天 - timedelta(days=往前几天)).weekday()

weekday()返回星期几的数字:周一=0,周二=1……周日=6。用它当列表下标(星期名[数字]),就把数字变成"一二三四五六日"。数字→下标→文字,这个转换链条第四篇学过(数据类型+列表)。

画个迷你图表

Python

条 = "🍅" * 数量 if 数量 else "—"

字符串乘法(第二十一篇进度条用过):几个番茄就画几个🍅。if 数量 else "—"是三元表达式——"有条件的选择"的紧凑写法。数量是0就画个横杠(0乘任何字符串是空字符串,光秃秃不好看)。

输出效果:

Code

📊 最近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 · 知识回顾

知识点
在哪里用的
time.sleep
每秒倒计时
while循环
番茄主循环、倒计时循环
循环套循环
主流程套倒计时
for循环
遍历7天、遍历菜单
range(6, -1, -1)
倒序生成6→0
条件判断
长短休息切换、输入验证
取模%
每4个番茄长休息
函数
倒计时、选择时长、记录、报表
函数参数
标签、秒数
return
返回时长、返回统计
字典
时长方案菜单、按天记录
字典.get
累加番茄数、查某天数量
None
标记自定义方案
is None
判断走不走自定义分支
列表+下标
数字转星期名
文件操作
JSON记录读写
try/except
多种错误兜底
datetime/timedelta
日期、日期减N天
weekday()
星期几
字符串乘法
🍅柱状图
三元表达式
数量为0画横杠
f-string格式化
mm:ss显示、对齐

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

相关学习资料