查看全课大纲(第 26 / 51 节)
- 1.为什么人人都该学点编程?
- 2.计算机与程序设计:你的电脑到底在“想”什么?
- 3.Python 这门语言,到底有什么魔力?
- 4.Python 开发环境配置:如何拥有你的第一个“编程工具箱”?
- 5.如何安装一个更强大的代码编辑器?
- 6.汇率兑换1.0:你的第一个“钱生钱”小程序
- 7.你的第一行代码,藏着哪些秘密?
- 8.汇率兑换2.0(上):让程序看懂“CNY”和“USD”
- 9.汇率兑换程序,如何让它“聪明”地判断币种?
- 10.汇率兑换程序能一直运行,直到我喊停吗?
- 11.汇率兑换4.0:如何把“算钱”功能打包成积木?
- 12.汇率兑换5.0:给你的程序穿上“结构化”的西装
- 13.怎么用 Python 画一个会动的五角星?
- 14.如何让程序自动画出不同大小的五角星?
- 15.函数自己调用自己,会发生什么?
- 16.用递归画出神奇的分形树
- 17.Python 怎么计算你一天躺着不动能消耗多少热量?
- 18.如何让程序“活”起来,持续为你服务?
- 19.如何让 BMR 计算器更“聪明”?
- 20.当程序遇到“不按套路出牌”的用户怎么办?
- 21.怎么用 Python 模拟一个“滚雪球”式的存钱计划?
- 22.如何用列表记录每一周的存款?
- 23.如何让程序自己数数?—— 用 for 循环解放你的双手
- 24.52周存钱挑战4.0:你的存款计算器能有多灵活?
- 25.52周存钱挑战:怎么根据日期自动查存款?
- 26.Python 怎么判断一年中的第几天?
- 27.列表 vs 元组:哪个更适合存储月份天数?
- 28.用集合给月份分个队,换个思路算天数
- 29.把月份和天数“锁”在一起:用字典给数据配个对
- 30.Python 怎么判断密码强弱?
- 31.Python 怎么给密码设置“防沉迷”系统?
- 32.Python 怎么把密码保存到文件里?
- 33.Python 怎么读取文件里的密码?
- 34.Python 怎么把密码检查工具“打包”起来?
- 35.Python 怎么把文件操作也“打包”起来?
- 36.计算机怎么“扔骰子”?——用Python模拟随机事件
- 37.如何用 Python 模拟掷两个骰子?
- 38.怎么用 Python 把骰子轨迹画出来?
- 39.骰子点数分布长啥样?用直方图一眼看穿!
- 40.用科学计算库让骰子程序“起飞”
- 41.空气质量指数怎么算?手把手教你写一个AQI计算器
- 42.空气质量指数计算:从零开始,让程序看懂空气
- 43.如何读取空气质量数据文件并找出空气质量最好的五个监测点?
- 44.JSON 数据怎么变成 Excel 表格?—— 让数据换个“马甲”
- 45.Python 怎么让程序自己判断文件类型?
- 46.如何让程序自己上网查空气质量?
- 47.用美味的汤来解析网页:Beautiful Soup 入门
- 48.如何让爬虫自动抓取全国所有城市的空气质量?
- 49.爬到的数据怎么存下来?—— 把全国空气质量数据保存为CSV文件
- 50.用 pandas 玩转空气质量数据:找出全国空气最好和最差的城市
- 51.空气质量数据怎么“洗”干净,还能画成图?
Python 怎么判断一年中的第几天?
约 22 分钟
小象实战讲义 · Python 入门:8 个小项目边玩边学
欢迎来到我们的第六个小项目!今天我们要玩一个“时间侦探”的游戏:给你一个具体的日期,比如你的生日,你能立刻说出这是那一年的第几天吗?是不是感觉有点难?别担心,学完这一节,你就能写一个超酷的“日期侦探”程序,让它帮你瞬间算出答案!
💡 核心导读
本节你将学到:
- 新朋友:元组(tuple),一个“一旦创建就不能修改”的列表。
- 核心算法:如何把“四年一闰,百年不闰,四百年再闰”的规则,变成计算机能理解的代码。
- 项目迭代:从零开始,一步步构建出完整的“判断第几天”程序。
- 本节只新增一个知识点:认识并使用元组来存储固定的月份天数。
一、项目启动:侦探需要什么线索?
我们的“日期侦探”程序要解决什么问题呢?很简单:输入一个具体的年月日,输出它是那一年的第几天。
听起来容易,但仔细一想,有两个“陷阱”:
- 月份天数不同:1月31天,2月28或29天,4月30天……不能简单相加。
- 闰年捣乱:2月的天数在闰年(29天)和平年(28天)不一样。
所以,我们的侦探需要两条核心线索:
- 每个月的天数表(一个固定不变的数据)。
- 闰年判断法则(一个清晰的逻辑规则)。
我们先来解决第二个问题,因为它是整个案件的“钥匙”。
二、破解闰年密码:把常识变成代码
闰年的规则大家可能听过:“四年一闰,百年不闰,四百年再闰”。怎么用程序表达呢?
我们把它拆解成计算机能懂的“条件语句”:
- 条件A(四百年再闰):年份能被400整除(
年份 % 400 == 0)。 - 条件B(四年一闰且百年不闰):年份能被4整除 并且 不能被100整除(
(年份 % 4 == 0) and (年份 % 100 != 0))。
这两个条件满足任意一个,就是闰年。所以是“或”的关系。
举个例子:1900年。
- 它能被4整除吗?能(1900 % 4 == 0)。
- 它能被100整除吗?能(1900 % 100 == 0)。
- 所以它不满足“百年不闰”的条件,因此1900年不是闰年。很多人的常识在这里会出错,但我们的程序不会!
# 闰年判断逻辑演示
year = 1900
# 条件A:能被400整除
condition_a = (year % 400 == 0)
# 条件B:能被4整除 且 不能被100整除
condition_b = (year % 4 == 0) and (year % 100 != 0)
is_leap_year = condition_a or condition_b
print(f"{year}年是闰年吗? {is_leap_year}")1900年是闰年吗? False看,程序完美地执行了规则。有了这把“钥匙”,我们就可以处理2月天数的问题了。
三、引入新工具:元组(tuple),一个“固执”的列表
现在我们需要一个地方来存放每个月的天数。之前我们学过列表(list),它可以存放一系列数据。今天我们来认识它的“表哥”——元组(tuple)。
它们最大的区别是:列表创建后可以随意修改(增删改),而元组一旦创建,里面的内容就不能修改了。就像一个刻在石头上的名单,无法擦写。
为什么用元组?因为一年的月份天数是固定的(1月永远是31天),我们不需要修改它,用元组更安全,也能提醒我们这是固定数据。
怎么创建和访问元组?
- 创建:用圆括号
()把数据括起来,数据之间用逗号隔开。 - 访问:和列表一模一样,用中括号
[索引]。
# 对比列表和元组
# 1. 创建
my_list = [31, 28, 31] # 列表,用方括号
my_tuple = (31, 28, 31) # 元组,用圆括号
print("列表:", my_list)
print("元组:", my_tuple)
print("它们的类型分别是:", type(my_list), type(my_tuple))
# 2. 访问(和列表一样)
print("元组的第一个元素:", my_tuple[0])
# 3. 尝试修改(看看会发生什么)
my_list[0] = 30 # 修改列表,完全OK
print("修改后的列表:", my_list)
# my_tuple[0] = 30 # 如果取消这行的注释,运行会报错!元组不能修改。
# print("修改后的元组:", my_tuple)列表: [31, 28, 31]
元组: (31, 28, 31)
它们的类型分别是: <class 'list'> <class 'tuple'>
元组的第一个元素: 31
修改后的列表: [30, 28, 31]看到了吗?当我们试图修改元组时,程序会报错。这种“固执”的特性,在存储像月份天数这种固定数据时,反而是个优点!
四、组装我们的“日期侦探”程序(1.0版)
万事俱备,我们来把线索和工具组装起来。本节新增的核心就是用元组来存储月份天数。
思路拆解:
- 获取输入:让用户输入一个日期,并把它解析成Python能处理的日期格式。
- 提取年月日:从日期中分离出年、月、日。
- 计算基础天数:
- 用一个元组存储平年时每个月的天数。
- 计算输入月份之前的所有月份的天数总和。
- 加上输入日期中“日”的部分。
- 闰年修正:
- 判断年份是否是闰年。
- 如果是闰年 并且 月份大于2月(即已经过了2月),则在总天数上加1(因为2月是29天)。
下面是完整的1.0版程序:
# 判断第几天 1.0
# 使用元组(tuple)存储月份天数
# 导入datetime模块,用于处理日期
from datetime import datetime
# 1. 获取用户输入的日期
# 原程序使用 input(),这里为了你能直接运行,用一个固定日期代替
# 你可以将 `date_str` 的值改成任何你想测试的日期,格式必须是 `年/月/日`
date_str = '2012/03/05' # 例如:2012年3月5日
# 2. 将字符串解析为真正的日期对象
input_date = datetime.strptime(date_str, '%Y/%m/%d')
print(f"你输入的日期是: {input_date}")
# 3. 从日期对象中提取年、月、日
year = input_date.year
month = input_date.month
day = input_date.day
print(f"解析得到:{year}年 {month}月 {day}日")
# 4. 使用元组存储平年各月的天数
# 注意:这里假设2月是28天(平年)
days_in_month_tup = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
# 5. 计算基础天数:之前月份的总天数 + 当月的天数
# days_in_month_tup[: month - 1] 表示获取从开始到(month-1)月份的所有天数
# 例如 month=3(三月),则取前两个月的天数 (31, 28)
days_before = sum(days_in_month_tup[: month - 1])
total_days = days_before + day
print(f"计算基础天数(按平年算): {days_before}(前几个月) + {day}(当日) = {total_days}天")
# 6. 闰年判断与修正
# 闰年规则:能被400整除 或 (能被4整除 且 不能被100整除)
if (year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0)):
print(f"{year}年是闰年。")
# 只有月份大于2月(即3月及以后),才需要补上加上的那一天
if month > 2:
total_days += 1
print(f"因为月份 > 2,总天数加1,变为: {total_days}天")
else:
print(f"{year}年是平年。")
# 7. 输出最终结果
print(f"结论:{date_str} 是{year}年的第 {total_days} 天。")你输入的日期是: 2012-03-05 00:00:00
解析得到:2012年 3月 5日
计算基础天数(按平年算): 59(前几个月) + 5(当日) = 64天
2012年是闰年。
因为月份 > 2,总天数加1,变为: 65天
结论:2012/03/05 是2012年的第 65 天。我们来验证一下:2012年是闰年,所以1月(31天)+2月(29天)=60天,再加上3月的5天,正好是65天。我们的“侦探”破案成功!
📝 动手练一练
- 修改测试:将上面程序中的
date_str变量值改为你自己的生日(格式如1995/08/23),运行一下,看看你的生日是那年的第几天? - 闰年挑战:分别测试
2000/03/01和1900/03/01,观察程序输出的结果,理解“百年不闰”和“四百年再闰”的规则是如何生效的。 - 元组探索:如果我们想用列表
[31, 28, 31, 30, ...]来代替程序中的元组,程序需要修改吗?哪些地方可以不改,哪些地方必须改?
👉 点击查看第3题思路提示
思路:元组和列表在访问元素和切片操作(如 [: month-1])上的用法是完全一样的。因此,如果只是简单地将定义元组的圆括号 () 换成定义列表的方括号 [],程序很可能不需要任何其他修改就能正常运行。
你可以尝试这样做:
- 找到代码中定义
days_in_month_tup的那一行。 - 把
(31, 28, 31, ...)外面的圆括号()改成方括号[]。 - 运行程序,看看是否还能得到正确结果。
这说明了列表和元组在很多基础操作上是相通的。它们最大的区别,我们之前已经演示过了,就在于能否修改。在这个程序里,月份天数数据不需要修改,所以两者都可以。在下一节2.0版本中,我们会专门探讨如果用列表,还能玩出什么新花样。
本章小结
恭喜你!你已经完成了“日期侦探”项目的1.0版本。你不仅学会了如何用程序判断闰年这个经典问题,还认识了一个新的数据结构——元组(tuple),并把它用在了存储固定数据的场景中。
📋 行动清单
学完立刻可以:
- 运行你的“侦探程序”,算出今天是你今年生活中的第几天。
- 向朋友炫耀一下,用程序快速判断1900年到底是不是闰年。
- 思考一下:你的手机通讯录(姓名-电话)这种数据,适合用列表、元组还是我们以后会学的其他工具来存?
在下一节,我们将对这个侦探程序进行“升级”,看看如果用回我们熟悉的列表,代码会有什么不同,又会带来哪些新的可能性。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载第6章代码包:判断第几天(含全部版本 4 个 .py)ZIP · 3KB