查看全课大纲(第 25 / 51 节)
  1. 1.为什么人人都该学点编程?
  2. 2.计算机与程序设计:你的电脑到底在“想”什么?
  3. 3.Python 这门语言,到底有什么魔力?
  4. 4.Python 开发环境配置:如何拥有你的第一个“编程工具箱”?
  5. 5.如何安装一个更强大的代码编辑器?
  6. 6.汇率兑换1.0:你的第一个“钱生钱”小程序
  7. 7.你的第一行代码,藏着哪些秘密?
  8. 8.汇率兑换2.0(上):让程序看懂“CNY”和“USD”
  9. 9.汇率兑换程序,如何让它“聪明”地判断币种?
  10. 10.汇率兑换程序能一直运行,直到我喊停吗?
  11. 11.汇率兑换4.0:如何把“算钱”功能打包成积木?
  12. 12.汇率兑换5.0:给你的程序穿上“结构化”的西装
  13. 13.怎么用 Python 画一个会动的五角星?
  14. 14.如何让程序自动画出不同大小的五角星?
  15. 15.函数自己调用自己,会发生什么?
  16. 16.用递归画出神奇的分形树
  17. 17.Python 怎么计算你一天躺着不动能消耗多少热量?
  18. 18.如何让程序“活”起来,持续为你服务?
  19. 19.如何让 BMR 计算器更“聪明”?
  20. 20.当程序遇到“不按套路出牌”的用户怎么办?
  21. 21.怎么用 Python 模拟一个“滚雪球”式的存钱计划?
  22. 22.如何用列表记录每一周的存款?
  23. 23.如何让程序自己数数?—— 用 for 循环解放你的双手
  24. 24.52周存钱挑战4.0:你的存款计算器能有多灵活?
  25. 25.52周存钱挑战:怎么根据日期自动查存款?
  26. 26.Python 怎么判断一年中的第几天?
  27. 27.列表 vs 元组:哪个更适合存储月份天数?
  28. 28.用集合给月份分个队,换个思路算天数
  29. 29.把月份和天数“锁”在一起:用字典给数据配个对
  30. 30.Python 怎么判断密码强弱?
  31. 31.Python 怎么给密码设置“防沉迷”系统?
  32. 32.Python 怎么把密码保存到文件里?
  33. 33.Python 怎么读取文件里的密码?
  34. 34.Python 怎么把密码检查工具“打包”起来?
  35. 35.Python 怎么把文件操作也“打包”起来?
  36. 36.计算机怎么“扔骰子”?——用Python模拟随机事件
  37. 37.如何用 Python 模拟掷两个骰子?
  38. 38.怎么用 Python 把骰子轨迹画出来?
  39. 39.骰子点数分布长啥样?用直方图一眼看穿!
  40. 40.用科学计算库让骰子程序“起飞”
  41. 41.空气质量指数怎么算?手把手教你写一个AQI计算器
  42. 42.空气质量指数计算:从零开始,让程序看懂空气
  43. 43.如何读取空气质量数据文件并找出空气质量最好的五个监测点?
  44. 44.JSON 数据怎么变成 Excel 表格?—— 让数据换个“马甲”
  45. 45.Python 怎么让程序自己判断文件类型?
  46. 46.如何让程序自己上网查空气质量?
  47. 47.用美味的汤来解析网页:Beautiful Soup 入门
  48. 48.如何让爬虫自动抓取全国所有城市的空气质量?
  49. 49.爬到的数据怎么存下来?—— 把全国空气质量数据保存为CSV文件
  50. 50.用 pandas 玩转空气质量数据:找出全国空气最好和最差的城市
  51. 51.空气质量数据怎么“洗”干净,还能画成图?

52周存钱挑战:怎么根据日期自动查存款?

约 21 分钟

小象实战讲义 · Python 入门:8 个小项目边玩边学

还记得我们之前做的“52周存钱挑战”吗?我们已经能让它自动计算每周存多少钱、还能灵活设置存钱规则了。但有个小问题:用户得自己知道“今天是第几周”才能查存款,这太不智能了!

这一节,我们要给存钱挑战加上“日期识别”的超能力——用户只需要输入一个日期(比如“2024/08/05”),程序就能自动算出这是当年的第几周,然后告诉你那周该存多少钱。就像给你的存钱计划装了个智能日历!

💡 核心导读

  • 列表的妙用:把52周的存款总额存进一个列表,想查哪周就取哪周
  • 日期处理的“瑞士军刀”:认识Python自带的datetime库,它能轻松处理各种日期时间问题
  • 字符串 ↔ 日期的魔法转换:学会strptime()和strftime()这对“孪生兄弟”
  • ISO日历的秘密:一键获取“今天是今年的第几周”
  • 编程思维训练:如何“先完成简单的,再攻克复杂的”

一、先解决“查存款”问题:列表就是你的记账本

本节新增了什么?

我们只加一件事:把每周的存款总额存进列表,然后根据周数直接查询。

还记得我们之前用列表记录每周的存款数吗?比如[10, 20, 30, ..., 520]。但用户真正关心的是“到第X周为止,我总共存了多少钱”。

所以我们需要一个新列表,专门记录每周的累计存款总额:

  • 第1周:10元
  • 第2周:10+20=30元
  • 第3周:10+20+30=60元
  • …
  • 第52周:13780元
import math

def save_money_in_n_weeks(money_per_week, increase_money, total_week):
    """
    计算n周内的存款金额
    """
    money_list = []  # 记录每周存款数的列表
    saved_money_list = []   # 记录每周账户累计(新增!)

    for i in range(total_week):
        money_list.append(money_per_week)
        saving = math.fsum(money_list)
        saved_money_list.append(saving)  # 把累计金额存进列表
        
        money_per_week += increase_money
    
    return saved_money_list  # 返回累计存款列表

# 测试一下:每周存10元,每周递增10元,存5周
saved_money_list = save_money_in_n_weeks(10, 10, 5)
print("5周的累计存款列表:", saved_money_list)
5周的累计存款列表: [10.0, 30.0, 60.0, 100.0, 150.0]

看到了吗?列表里依次是第1周、第2周…第5周的累计存款。有了这个列表,查询就超级简单了!

列表索引的小秘密

Python的列表有个特点:位置从0开始数。这和我们平时说的“第几周”差1位:

  • 第1周 → 列表位置0
  • 第2周 → 列表位置1
  • 第16周 → 列表位置15(16-1)

所以查询第N周的存款,就是取列表的第N-1个元素。

import math

def save_money_in_n_weeks(money_per_week, increase_money, total_week):
    """
    计算n周内的存款金额
    """
    money_list = []  # 记录每周存款数的列表
    saved_money_list = []   # 记录每周账户累计(新增!)

    for i in range(total_week):
        money_list.append(money_per_week)
        saving = math.fsum(money_list)
        saved_money_list.append(saving)  # 把累计金额存进列表
        
        money_per_week += increase_money
    
    return saved_money_list  # 返回累计存款列表

# 测试一下:每周存10元,每周递增10元,存5周
saved_money_list = save_money_in_n_weeks(10, 10, 5)
print("5周的累计存款列表:", saved_money_list)


# 接上面的代码,假设我们存了52周
saved_money_list = save_money_in_n_weeks(10, 10, 52)

# 用户输入第几周(这里用固定值代替input())
week_num = 16  # 用户想知道第16周存了多少钱

# 查询:第16周对应列表位置15
deposit = saved_money_list[week_num - 1]
print(f"第{week_num}周的存款:{deposit}元")
5周的累计存款列表: [10.0, 30.0, 60.0, 100.0, 150.0]
第16周的存款:1360.0元
import math

def save_money_in_n_weeks(money_per_week, increase_money, total_week):
    """
    计算n周内的存款金额
    """
    money_list = []  # 记录每周存款数的列表
    saved_money_list = []   # 记录每周账户累计(新增!)

    for i in range(total_week):
        money_list.append(money_per_week)
        saving = math.fsum(money_list)
        saved_money_list.append(saving)  # 把累计金额存进列表
        
        money_per_week += increase_money
    
    return saved_money_list  # 返回累计存款列表

# 测试一下:每周存10元,每周递增10元,存5周
saved_money_list = save_money_in_n_weeks(10, 10, 5)
print("5周的累计存款列表:", saved_money_list)


# 接上面的代码,假设我们存了52周
saved_money_list = save_money_in_n_weeks(10, 10, 52)

# 用户输入第几周(这里用固定值代替input())
week_num = 16  # 用户想知道第16周存了多少钱

# 查询:第16周对应列表位置15
deposit = saved_money_list[week_num - 1]
print(f"第{week_num}周的存款:{deposit}元")
5周的累计存款列表: [10.0, 30.0, 60.0, 100.0, 150.0]
第16周的存款:1360.0元

太棒了!现在只要用户告诉我们周数,我们就能立刻查出存款。但问题来了——用户怎么知道今天是第几周呢?


二、日期处理的“瑞士军刀”:datetime库

本节新增了什么?

我们引入Python自带的datetime库,它能轻松处理各种日期问题。

想象一下,你有个智能助理,你问它“2024年8月5号是今年的第几周?”,它立刻就能回答你。Python的datetime库就是这样的智能助理!

首先,认识一下这个强大的库:

import datetime

# 获取当前日期和时间
now = datetime.datetime(2025, 3, 20, 14, 30, 25)  # 固定时刻,真实程序这里用 now() 取当前时间
print("当前时间:", now)
print("时间类型:", type(now))
当前时间: 2025-03-20 14:30:25
时间类型: <class 'datetime.datetime'>

datetime.datetime是Python专门用来表示日期时间的类型。有了它,你可以轻松获取各种信息:

import datetime

now = datetime.datetime(2025, 3, 20, 14, 30, 25)  # 固定时刻,真实程序这里用 now() 取当前时间
print("年份:", now.year)
print("月份:", now.month)  
print("日期:", now.day)
print("小时:", now.hour)
print("分钟:", now.minute)
年份: 2025
月份: 3
日期: 20
小时: 14
分钟: 30

但这还不是最厉害的——datetime真正的超能力是在字符串和日期之间自由转换。


三、字符串 ↔ 日期的魔法转换

魔法一:字符串变日期(strptime)

用户输入的是字符串,比如"2024/08/05"。我们需要把它变成datetime类型才能处理。

import datetime

# 用户输入的日期字符串(这里用固定值代替input())
date_str = "2024/08/05"

# 魔法转换:字符串 → datetime
# strptime = string parse time(解析时间字符串)
input_date = datetime.datetime.strptime(date_str, "%Y/%m/%d")
print("转换后的日期:", input_date)
print("日期类型:", type(input_date))
转换后的日期: 2024-08-05 00:00:00
日期类型: <class 'datetime.datetime'>

关键点解析:

  • strptime()需要两个参数:
    1. 日期字符串("2024/08/05")
    2. 格式说明("%Y/%m/%d")

格式说明就像“翻译指南”:

  • %Y:4位数的年份(2024)
  • %m:2位数的月份(08,8月)
  • %d:2位数的日期(05)

如果用户输入"2024-08-05",格式就要写成"%Y-%m-%d"。格式必须和字符串完全匹配!

魔法二:获取“第几周”(isocalendar)

日期转换好了,怎么知道是第几周呢?datetime早就准备好了:

import datetime

date_str = "2024/08/05"
input_date = datetime.datetime.strptime(date_str, "%Y/%m/%d")

# 获取ISO日历信息
iso_info = input_date.isocalendar()
print("ISO日历信息:", iso_info)
print("类型:", type(iso_info))
ISO日历信息: datetime.IsoCalendarDate(year=2024, week=32, weekday=1)
类型: <class 'datetime.IsoCalendarDate'>

isocalendar()返回一个元组(可以暂时理解为“固定顺序的列表”):

  • 第1个值:年份(2024)
  • 第2个值:第几周(32) ← 我们需要的!
  • 第3个值:星期几(1=周一,7=周日)

所以获取周数超级简单:

import datetime

date_str = "2024/08/05"
input_date = datetime.datetime.strptime(date_str, "%Y/%m/%d")

week_num = input_date.isocalendar()[1]  # 取元组的第2个值(索引1)
print(f"{date_str} 是2024年的第{week_num}周")
2024/08/05 是2024年的第32周

魔法三:日期变字符串(strftime)

有时候我们需要把日期按特定格式显示出来,比如显示成“2024年08月05日”。

import datetime

now = datetime.datetime(2025, 3, 20, 14, 30, 25)  # 固定时刻便于输出对账;真实程序这里用 datetime.now() 取当前时间

# 魔法转换:datetime → 字符串
# strftime = string format time(格式化时间字符串)
formatted = now.strftime("%Y年%m月%d日 %H:%M:%S")
print("格式化后的时间:", formatted)

# 各种格式随心变
print("简写日期:", now.strftime("%y/%m/%d"))  # 2位年份
print("英文月份:", now.strftime("%d-%b-%Y"))  # Mar表示3月
print("星期几:", now.strftime("%A"))         # Thursday
格式化后的时间: 2025年03月20日 14:30:25
简写日期: 25/03/20
英文月份: 20-Mar-2025
星期几: Thursday

strptime和strftime就像一对孪生兄弟:

  • strptime:字符串 → datetime(解析)
  • strftime:datetime → 字符串(格式化)

记住口诀:p是parse(解析),f是format(格式化)。


四、完整程序:智能查存款

现在我们把所有零件组装起来,做一个真正智能的存钱查询工具!

"""
    52周存钱挑战 5.0
    功能:根据用户输入的日期,自动查询该周存款金额
"""
import math
import datetime

def save_money_in_n_weeks(money_per_week, increase_money, total_week):
    """
    计算n周内的存款金额
    """
    money_list = []  # 记录每周存款数
    saved_money_list = []   # 记录每周账户累计

    for i in range(total_week):
        money_list.append(money_per_week)
        saving = math.fsum(money_list)
        saved_money_list.append(saving)
        
        money_per_week += increase_money
    
    return saved_money_list

# 主程序
# 1. 设置存钱计划(这里用固定值代替input())
money_per_week = 10     # 每周存10元
increase_money = 10     # 每周递增10元  
total_week = 52         # 存52周

# 2. 计算所有周的存款
saved_money_list = save_money_in_n_weeks(money_per_week, increase_money, total_week)

# 3. 用户输入日期(这里用固定值代替input())
input_date_str = "2024/08/05"  # 格式必须是yyyy/mm/dd

# 4. 字符串转日期
input_date = datetime.datetime.strptime(input_date_str, "%Y/%m/%d")

# 5. 获取是第几周
week_num = input_date.isocalendar()[1]

# 6. 查询存款(注意:第N周对应列表位置N-1)
deposit = saved_money_list[week_num - 1]

print(f"日期 {input_date_str} 是2024年的第{week_num}周")
print(f"第{week_num}周的存款:{deposit}元")
日期 2024/08/05 是2024年的第32周
第32周的存款:5280.0元

运行一下试试! 你可以把input_date_str改成你自己的生日,看看你生日那周该存多少钱。


五、编程思维:先易后难,步步为营

你可能注意到了,我们写程序时没有一口气写完所有功能,而是:

  1. 先实现“根据周数查存款”(这个我们熟悉)
  2. 再研究“怎么把日期变成周数”(学习新知识)
  3. 最后把两部分拼起来

这种“先完成简单的,再攻克复杂的”思维方式在编程中特别重要。就像拼乐高:

  • 先把你会拼的部分拼好
  • 再研究新零件的用法
  • 最后把新旧零件组合起来

如果一开始就想着“我要做一个能识别日期、能查存款、还能…的超级程序”,很容易被卡住。拆解问题,逐个击破,这是程序员的核心技能之一。


📝 动手练一练

  1. 日期格式大挑战:我们的程序要求用户输入yyyy/mm/dd格式。如果用户输入2024-08-05(用横杠分隔),程序会报错。你能修改程序,让它同时支持yyyy/mm/dd和yyyy-mm-dd两种格式吗?

  2. 生日存款查询器:写一个小程序,让用户输入自己的生日(格式自定),然后告诉ta:“在你生日那一周,52周存钱挑战应该存XX元”。

  3. 【选做】错误处理小能手:如果用户输入的日期格式不对(比如2024/8/5少写了0),程序会崩溃。你能用try...except让程序友好地提示用户“日期格式错误,请重新输入”吗?

👉 点击查看第1题参考答案

思路:先尝试用第一种格式解析,如果失败(抛出异常),再尝试第二种格式。

import datetime

def parse_date(date_str):
    """
    尝试两种格式解析日期
    """
    formats = ["%Y/%m/%d", "%Y-%m-%d"]
    
    for fmt in formats:
        try:
            return datetime.datetime.strptime(date_str, fmt)
        except ValueError:
            continue  # 这种格式不对,试下一种
    
    # 两种格式都失败了
    raise ValueError(f"无法解析日期: {date_str},请使用yyyy/mm/dd或yyyy-mm-dd格式")

# 测试
test_dates = ["2024/08/05", "2024-08-05", "2024/8/5"]  # 最后一个会失败

for date_str in test_dates:
    try:
        date_obj = parse_date(date_str)
        print(f"成功解析 {date_str} → {date_obj}")
    except ValueError as e:
        print(f"解析失败 {date_str}: {e}")
成功解析 2024/08/05 → 2024-08-05 00:00:00
成功解析 2024-08-05 → 2024-08-05 00:00:00
成功解析 2024/8/5 → 2024-08-05 00:00:00
👉 点击查看第2题参考答案

思路:结合本节学的所有知识,先解析生日日期,再计算周数,最后查询存款。

import math
import datetime

def save_money_in_n_weeks(money_per_week, increase_money, total_week):
    """计算存款(复用之前的函数)"""
    saved_money_list = []
    total = 0
    
    for week in range(total_week):
        total += money_per_week + week * increase_money
        saved_money_list.append(total)
    
    return saved_money_list

# 主程序
# 1. 设置存钱计划
money_per_week = 10
increase_money = 10
total_week = 52

# 2. 计算所有存款
saved_money_list = save_money_in_n_weeks(money_per_week, increase_money, total_week)

# 3. 用户输入生日(这里用固定值代替input())
birthday_str = "2000/05/20"  # 假设生日是2000年5月20日

try:
    # 4. 解析生日
    birthday = datetime.datetime.strptime(birthday_str, "%Y/%m/%d")
    
    # 5. 获取生日是第几周(注意:我们只看周数,不管年份)
    week_num = birthday.isocalendar()[1]
    
    # 6. 确保周数不超过52
    if week_num > 52:
        week_num = 52
    
    # 7. 查询存款
    deposit = saved_money_list[week_num - 1]
    
    print(f"你的生日 {birthday_str} 是当年的第{week_num}周")
    print(f"在你生日那一周,52周存钱挑战应该存 {deposit} 元!")
    
except ValueError:
    print("日期格式错误!请使用 yyyy/mm/dd 格式")
你的生日 2000/05/20 是当年的第20周
在你生日那一周,52周存钱挑战应该存 2100 元!

本章小结

恭喜!你刚刚给“52周存钱挑战”装上了“日期识别”的超能力。现在它不再是一个简单的计算器,而是一个智能的理财小助手——用户只需要输入日期,就能立刻知道该存多少钱。

本节我们学到了:

  1. 列表的查询功能:把52周的存款总额存进列表,用列表[周数-1]就能快速查询
  2. datetime库:Python处理日期时间的“瑞士军刀”
  3. 字符串 ↔ 日期转换:
    • strptime():字符串变日期(解析)
    • strftime():日期变字符串(格式化)
  4. ISO日历:isocalendar()一键获取年份、周数、星期几
  5. 编程思维:先易后难,拆解问题,逐个击破

📋 行动清单

学完立刻可以做的3件事:

  • 运行完整程序:把5.0的代码复制运行,输入几个不同的日期试试
  • 改造日期格式:修改程序,让它支持yyyy-mm-dd格式(参考动手练一练第1题)
  • 查查特殊日期:输入春节、国庆节、你的生日,看看这些日子该存多少钱

现在你已经掌握了列表、函数、循环、日期处理等多个核心技能。下一章,我们将探索更多处理“组合数据”的方法——除了列表,Python还有哪些“容器”可以帮我们更好地组织数据?它们各有什么绝活?

敬请期待!

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 第5章代码包:52周存钱挑战(含全部版本 5 个 .py)
    ZIP · 3KB
    下载
看图文没弄懂?展开看本节视频讲解(约 21 分钟)
📺 正在播放小象学院官方高清录播(支持倍速与清晰度调节)