查看全课大纲(第 29 / 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.空气质量数据怎么“洗”干净,还能画成图?

把月份和天数“锁”在一起:用字典给数据配个对

约 17 分钟

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

前面几节课,我们像整理衣柜一样,把月份按天数分成了不同的“抽屉”(集合)。今天,我们要玩个更酷的:直接把“月份”和“天数”配成一对,像钥匙和锁一样,把它们“锁”在一起。这样,想查任何一个月有多少天,直接问“钥匙”就行了。实现这个神奇功能的数据类型,就是 Python 里的字典(Dictionary)。学完这一节,你的“判断第几天”程序会变得更清晰、更强大。

💡 核心导读

  • 新武器:字典:一种“键-值”配对的数据结构,像查字典一样,用“键”就能找到对应的“值”。
  • 项目升级:用字典来存储“月份-天数”的对应关系,让数据组织一目了然。
  • 字典的基本操作:创建、添加、访问、修改和删除字典里的数据。
  • 字典的遍历:如何查看字典里所有的“钥匙”和“宝藏”。

从“分开放”到“锁一起”:字典登场

在之前的版本里,我们把30天的月份放在一个集合 {4, 6, 9, 11},31天的月份放在另一个集合 {1, 3, 5, 7, 8, 10, 12}。这很好,但有没有一种方法,能让我们一眼就看到“1月对应31天,2月对应28天……”呢?

当然有!Python 的字典(dict) 就是干这个的。它把数据组织成一个个“键值对”(Key-Value Pair)。你可以把“键”想象成一把独一无二的钥匙,“值”就是这把钥匙能打开的宝箱里的东西。

生活中的字典例子:

  • 身份证号(键) 对应 个人信息(值)。
  • 商品名称(键) 对应 商品价格(值)。

字典的查找方式叫映射:你拿着“键”这把钥匙,就能直接找到它映射的那个“值”,速度非常快。我们使用字典时通常也不关心数据的排列先后,只关心“键”和“值”的配对关系。(补充:自 Python 3.7 起,字典会保留键值对插入时的顺序,但这不是我们使用字典时依赖的特性;真正“无序”的是下一章会遇到的集合 set。)

玩转字典:创建、增删改查

让我们在代码里亲手创建一个字典,感受一下它的魔力。

# 1. 创建一个空字典
price_dict = {}  # 或者 price_dict = dict()
print("空字典:", price_dict)

# 2. 向字典中添加数据(键值对)
price_dict['鸡蛋'] = 2.59   # 键是'鸡蛋',值是2.59
price_dict['牛奶'] = 3.19
price_dict['奶酪'] = 4.80
print("添加商品后:", price_dict)

# 3. 访问字典中的值(通过键)
milk_price = price_dict['牛奶']
print("牛奶的价格是:", milk_price)

# 4. 修改字典中的值
price_dict['鸡蛋'] = 3.59  # 鸡蛋涨价了
print("鸡蛋涨价后:", price_dict)

# 5. 删除字典中的项
del price_dict['奶酪']
print("删除奶酪后:", price_dict)

# 6. 检查某个键是否在字典中
print("'鸡蛋'在字典中吗?", '鸡蛋' in price_dict)
print("'酸奶'在字典中吗?", '酸奶' in price_dict)
空字典: {}
添加商品后: {'鸡蛋': 2.59, '牛奶': 3.19, '奶酪': 4.80}
牛奶的价格是: 3.19
鸡蛋涨价后: {'鸡蛋': 3.59, '牛奶': 3.19, '奶酪': 4.80}
删除奶酪后: {'鸡蛋': 3.59, '牛奶': 3.19}
'鸡蛋'在字典中吗? True
'酸奶'在字典中吗? False

看,字典的操作非常直观!用方括号[]里面放上“键”,就能进行赋值(添加/修改)、访问和删除。

项目升级4.0:用字典重构“月份-天数”

现在,回到我们的核心项目。本节我们只新增一件事:用字典来存储每个月份对应的天数。 这会让我们的数据看起来就像一张清晰的表格。

思路很简单:

  • 键(Key):月份(1, 2, 3, …)
  • 值(Value):该月的天数(31, 28/29, 31, …)

我们来创建这个字典,并改写计算逻辑:

from datetime import datetime

def is_leap_year(year):
    """判断是否为闰年"""
    return (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0))

# 假设输入日期为 2017/03/05 和 2012/03/05,用固定值代替input()
input_date_str_list = ['2017/03/05', '2012/03/05']

for input_date_str in input_date_str_list:
    input_date = datetime.strptime(input_date_str, '%Y/%m/%d')
    year = input_date.year
    month = input_date.month
    day = input_date.day

    # 4.0 核心升级:创建月份-天数字典
    month_days_dict = {
        1: 31,   # 1月有31天
        2: 28,   # 先按平年算,2月28天
        3: 31,
        4: 30,
        5: 31,
        6: 30,
        7: 31,
        8: 31,
        9: 30,
        10: 31,
        11: 30,
        12: 31
    }
    # 现在,想知道某个月有多少天,直接 month_days_dict[月份] 就行了!

    # 计算总天数
    total_days = day  # 先加上当月的天数
    # 累加之前月份的天数
    for m in range(1, month):  # 从1月累加到(month-1)月
        total_days += month_days_dict[m]

    # 如果是闰年且月份大于2月,需要加1天
    if is_leap_year(year) and month > 2:
        total_days += 1

    print(f'{input_date_str} 是{year}年的第{total_days}天。')
2017/03/05 是2017年的第64天。
2012/03/05 是2012年的第65天。

成功!代码变得更易读了。month_days_dict[3] 直接就是31,我们不再需要去判断3月属于哪个集合。

字典的遍历:看看里面都有啥

有时候我们想看看字典里所有的“钥匙”或者所有的“宝藏”,或者想一对一对地检查,该怎么做呢?字典提供了几种遍历方式:

# 沿用之前的商品价格字典
price_dict = {'鸡蛋': 3.59, '牛奶': 3.19, '面包': 5.50}

print("--- 遍历所有的键(商品名)---")
for key in price_dict.keys():
    print(f"商品:{key}")

print("\n--- 遍历所有的值(价格)---")
for value in price_dict.values():
    print(f"价格:{value}")

print("\n--- 遍历所有的键值对(数据项)---")
for key, value in price_dict.items(): # items()返回的是(键, 值)元组
    print(f"{key} 的价格是 {value}")
--- 遍历所有的键(商品名)---
商品:鸡蛋
商品:牛奶
商品:面包

--- 遍历所有的值(价格)---
价格:3.59
价格:3.19
价格:5.5

--- 遍历所有的键值对(数据项)---
鸡蛋 的价格是 3.59
牛奶 的价格是 3.19
面包 的价格是 5.5

换个思路:用“天数”当键?

我们的 month_days_dict 是用月份作键,天数作值。讲师在视频里提了一个有趣的思考题:能不能反过来,用“天数”作键,“月份集合”作值呢?

当然可以!因为字典的“值”可以是任何类型,包括列表、集合等。

# 这是一个思考方向,不是最终代码
day_months_dict = {
    30: {4, 6, 9, 11},   # 30天对应的月份集合
    31: {1, 3, 5, 7, 8, 10, 12}, # 31天对应的月份集合
    28: {2}, # 平年2月
    29: {2}  # 闰年2月
}

如果这样组织数据,我们的计算逻辑可能就需要调整:先判断当前月份有多少天(需要查两次?),然后再去累加。这不一定比之前的方式更简单,但这是一个很好的思维训练,能帮你更深入地理解数据的多种组织方式。

📝 动手练一练

  1. 字典翻转:编写一段代码,将 price_dict = {'苹果': 5, '香蕉': 3, '橙子': 4} 翻转成一个新字典,其中价格作为键,水果名作为值。注意,价格可能重复吗?如果重复该怎么处理?(提示:值可以用列表来存放多个水果名)

  2. 探索官方“黑科技”:讲师提到,Python 标准库其实有一行代码就能算出一年中第几天的方法。请你根据提示(strftime 方法),查阅 Python 官方文档,找到这个格式化字符,并写一行代码验证它。(提示:关注 %j 这个格式符)

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

思路:遍历原字典,对于每个键值对,以原“值”作为新字典的“键”,原“键”作为新字典的“值”。因为价格可能相同,所以新字典的值应该是一个列表,用来存放所有对应这个价格的水果。

price_dict = {'苹果': 5, '香蕉': 3, '橙子': 4, '梨': 3} # 香蕉和梨都是3元

flipped_dict = {}
for fruit, price in price_dict.items():
    # 如果这个价格还没作为键出现过,就创建一个空列表
    if price not in flipped_dict:
        flipped_dict[price] = []
    # 将水果名添加到这个价格对应的列表中
    flipped_dict[price].append(fruit)

print(flipped_dict)
{5: ['苹果'], 3: ['香蕉', '梨'], 4: ['橙子']}
👉 点击查看第2题参考答案

思路:datetime 对象有一个 strftime 方法,可以将日期格式化成字符串。查阅文档可知,%j 表示“一年中的第几天(001-366)”。我们可以直接用这个方法获取天数。

from datetime import datetime

# 假设日期是 2012/03/05
input_date = datetime.strptime('2012/03/05', '%Y/%m/%d')
day_of_year = input_date.strftime('%j') # %j 输出是字符串,如 '065'
print(f"2012/03/05 是这一年的第 {int(day_of_year)} 天。") # 转为整数
2012/03/05 是这一年的第 65 天。

看,一行 strftime(‘%j’) 就搞定了!我们之前写那么多代码,是为了学习元组、列表、集合、字典这些重要的基础知识。在实际工作中,如果发现标准库已有现成方案,直接用它往往是最高效、最可靠的选择。

本章小结

恭喜你!通过“判断第几天”这个项目,我们一口气解锁了 Python 中四种最常用的集合数据类型,它们就像编程世界里的四种“收纳容器”,各有各的妙用:

  • 元组 (Tuple):(1, 2, 3) —— 一旦创建,内容不可变,安全可靠,适合存放固定数据。
  • 列表 (List):[1, 2, 3] —— 灵活可变,有顺序,可以随时增删改查,最常用的“序列”。
  • 集合 (Set):{1, 2, 3} —— 元素不重复,且无序,擅长做成员检查、去重和集合运算(交、并、差)。
  • 字典 (Dict):{‘键’: ‘值’} —— “键-值”对的映射结构,通过唯一的“键”快速查找对应的“值”,组织关联数据的神器。

理解它们的区别(是否可变、是否有序、是否允许重复、如何索引),是你从“写代码”迈向“写好代码”的关键一步。

📋 行动清单

  • 运行本节最后的完整项目代码,尝试输入不同的日期,看看结果是否正确。
  • 动手完成“字典翻转”的练习,理解如何处理字典中值重复的情况。
  • 访问 Python 官方文档,亲自查一下 strftime 的用法,感受一下阅读一手资料的能力。

在下一个项目中,我们将面对一个新问题:程序运行完,结果就消失了,如何把它保存下来?我们将一起学习文件的基本操作,让你的程序学会“读写记忆”。同时,我们还会接触到循环的跳出技巧和令人期待的面向对象编程入门。敬请期待!

—— 小象教研组

配套资料 · 直接下载

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

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