每天学习一点Python——3个经典项目带你玩转数据分析
大家好,今天我们通过3个非常有趣的Python项目来巩固下昨天学习的元组、列表与字典。
📊 项目一:大学统计数据分析
项目目标
分析大学数据,计算各种统计指标,让数据说话!
数据结构解析
# universities是一个列表,包含7个子列表
# 每个子列表代表一所大学,包含3个元素:[大学名称, 注册人数, 学费]
universities = [
['California Institute of Technology', 2175, 37704],
['Harvard', 19627, 39849],
# ... 其他大学数据
]
变量解释:
- •
universities:主列表,存储所有大学数据 - • 每个子列表索引:0=学校名,1=学生数,2=学费
核心函数详解
函数1:enrollment_stats(universities)
def enrollment_stats(universities):
# enrollments变量:存储所有大学的注册人数
# 使用列表推导式:从每所大学(uni)中取第2个元素(索引1)
enrollments = [uni[1] for uni in universities]
# tuitions变量:存储所有大学的学费
# 从每所大学(uni)中取第3个元素(索引2)
tuitions = [uni[2] for uni in universities]
# 返回两个列表:注册人数列表和学费列表
return enrollments, tuitions
参数说明:
返回值:
- • 第一个值enrollments:所有大学的学生人数列表
| | |
|---|
| | |
| | |
| return enrollments, tuitions | | ([2175, 19627, ...], [37704, 39849, ...]) |
注意: 只要用逗号分隔两个或多个值,Python就会自动将它们打包成一个元组。
函数2:mean(numbers) - 计算平均值
def mean(numbers):
# 首先检查列表是否为空
if not numbers:
return 0 # 如果空列表,返回0
# 计算平均值 = 总和 ÷ 元素个数
return sum(numbers) / len(numbers)
参数说明:
函数3:median(numbers) - 计算中位数
def median(numbers):
# 检查空列表
if not numbers:
return 0
# sorted_nums:排序后的新列表(原列表不变)
sorted_nums = sorted(numbers)
# n:列表中元素的数量
n = len(sorted_nums)
# middle:中间位置的索引(整除//只取整数部分)
middle = n // 2
if n % 2 == 0: # 如果元素个数是偶数
# 中位数 = 中间两个数的平均值
return (sorted_nums[middle - 1] + sorted_nums[middle]) / 2
else: # 如果元素个数是奇数
# 中位数 = 正中间的那个数
return sorted_nums[middle]
数据处理流程
# 第1步:提取数据(元组解包)
# enrollments得到所有学生数:[2175, 19627, 10566, ...]
# tuitions得到所有学费:[37704, 39849, 40732, ...]
enrollments, tuitions = enrollment_stats(universities)
# 第2步:计算总和
total_students = sum(enrollments) # 所有学生数相加
total_tuition = sum(tuitions) # 所有学费相加
# 第3步:计算平均值和中位数
student_mean = mean(enrollments) # 学生平均数
student_median = median(enrollments)# 学生数中位数
tuition_mean = mean(tuitions) # 学费平均数
tuition_median = median(tuitions) # 学费中位数
额外分析:找出最贵的大学
most_expensive = max(universities, key=lambda x: x[2])
print(f"🏫 学费最贵的大学: {most_expensive[0]} (${most_expensive[2]:,})")
🔑 key=lambda x: x[2] 解释
作用: 告诉Python如何提取比较值
拆解:
- •
x:代表universities中的每个子列表(如 ['Harvard', 19627, 39849])
效果: "请按每个大学的学费进行比较"
执行逻辑
# Python内部处理步骤:
1. 遍历 universities 中的每个大学(每个子列表)
2. 对每个大学应用 lambda 函数提取学费(x[2])
3. 比较所有大学的学费
4. 找到学费最高的大学
5. 返回该大学的完整信息(整个子列表)
🎮 项目二:州首府测验游戏
项目目标
创建一个交互式的地理知识测验游戏!
数据结构
# capitals_dict:字典类型,存储州名和对应首府
# 格式:{'州名': '首府', ...}
capitals_dict = {
'Alabama': 'Montgomery',
'Alaska': 'Juneau',
'Arizona': 'Phoenix',
# ... 更多州数据
}
核心函数解析
函数1:quiz_game()
def quiz_game():
score = 0 # 得分:答对一题加1分
questions_asked = 0 # 已提问问题数
max_questions = 5 # 最多提问5题
# list(capitals_dict.keys()):把字典的所有键转换成一个标准列表,只包含州名。
states = list(capitals_dict.keys())
字典方法对比:
| | | |
|---|
.keys() | | | ['Alabama', 'Alaska', ...] |
.values() | | | ['Montgomery', 'Juneau', ...] |
.items() | | | [('Alabama','Montgomery'), ...] |
游戏逻辑流程
while questions_asked < max_questions: # 条件:还没问完5题
state = random.choice(states) # 随机选一个州
correct_capital = capitals_dict[state] # 根据州名查找对应首府(正确答案)
attempts = 3 # 每道题最多尝试3次
while attempts > 0: # 还有尝试机会
guess = input("你的答案: ").strip() # 获取用户输入
if guess.lower() == 'exit': # 退出命令
return
elif guess.lower() == 'hint': # 提示命令
hint = correct_capital[0] + "*" * (len(correct_capital) - 1)
attempts -= 1
continue
elif guess.lower() == correct_capital.lower(): # 回答正确
score += 1
break
else: # 回答错误
attempts -= 1
🎲 state = random.choice(states) 解释
功能: 随机选择一个州
效果:
states = ['Alabama', 'Alaska', 'Arizona', 'California']
state = random.choice(states)
# 可能得到:'Alaska'
# 或:'California'
# 或:'Alabama' ← 每次运行结果不同
| |
|---|
random.choice() | |
states | |
state | |
注意: 必须导入 random 模块:import random
🔄 random.sample() 方法(不放回随机取多个元素)
功能: 随机选取多个不重复的元素
语法:random.sample(列表, 要选的数量)
与相关方法对比:
| | |
|---|
random.choice() | 取1个 | |
random.sample() | 取多个 | |
random.choices() | 取多个 | |
函数2:practice_mode()
def practice_mode():
while True: # 无限循环,直到用户退出
state_input = input("输入州名: ").strip()
if state_input.lower() == 'quit':
break # 退出循环
# 检查州名是否在字典中
if state_input in capitals_dict:
print(f"✅ {state_input} 的首府是: {capitals_dict[state_input]}")
else:
print(f"❌ 未找到州 '{state_input}',请检查拼写。")
print("可用州名:", ", ".join(sorted(capitals_dict.keys())))
📝 代码解释
", ".join(sorted(capitals_dict.keys()))
功能: 把州名列表变成好看的字符串
效果:
# 原始列表:['Alaska', 'Alabama', 'Arizona']
# 处理后:"Alabama, Alaska, Arizona" ← 排序并用逗号分隔
代码拆解步骤:
- 1.
capitals_dict.keys() - 获取所有键(州名) - 3.
", ".join(...) - 用逗号+空格连接
🔄 .join() 方法详解:
列表 = ["苹果", "香蕉", "橙子"]
print(",".join(列表)) # "苹果,香蕉,橙子"
print(" | ".join(列表)) # "苹果 | 香蕉 | 橙子"
print("\n".join(列表)) # 换行显示
🐱 项目三:戴帽子的猫(逻辑谜题)
问题理解
核心函数解析
函数1:cat_hat_problem(num_cats)
def cat_hat_problem(num_cats=100):
# 创建布尔值列表,表示100只猫的帽子状态
# False = 没帽子,True = 有帽子
cats = [False] * num_cats
# 模拟100轮操作
for round_num in range(1, num_cats + 1):
# 遍历需要操作的猫
for cat_index in range(round_num - 1, num_cats, round_num):
# not cats[cat_index]:取反操作
# True变False,False变True
cats[cat_index] = not cats[cat_index]
# 找出戴帽子的猫
hatted_cats = [index + 1 for index, has_hat in enumerate(cats) if has_hat]
return hatted_cats
📝 代码解释
range(round_num - 1, num_cats, round_num)
功能: 从第round_num只猫(因为列表索引从0开始)开始,每隔round_num只猫,选取一只进行操作,直到处理完所有num_cats只猫。
📚 基本语法
range(起始值, 结束值, 步长)
📝 cats = [False] * num_cats 解释
功能: 创建全是 False 的列表
效果:
num_cats = 5
cats = [False] * num_cats
print(cats) # [False, False, False, False, False]
具体运行示例(简化版:6只猫)
# 初始状态:[猫1:无, 猫2:无, 猫3:无, 猫4:无, 猫5:无, 猫6:无]
# 第1轮:操作索引0,1,2,3,4,5 → 所有猫戴帽子
# 状态:[有, 有, 有, 有, 有, 有]
# 第2轮:操作索引1,3,5 → 猫2,4,6摘帽子
# 状态:[有, 无, 有, 无, 有, 无]
# 第3轮:操作索引2,5 → 猫3摘帽子,猫6戴帽子
# 状态:[有, 无, 无, 无, 有, 有]
# ...继续到第6轮
# 最终状态:[有, 无, 无, 有, 无, 无]
🔍 hatted_cats = [index + 1 for index, has_hat in enumerate(cats) if has_hat] 详解
这是 列表推导式 + enumerate() 的经典用法:
数据示例:
cats = [True, False, False, True, False, False]
# 对应:猫1有帽子, 猫2无, 猫3无, 猫4有, 猫5无, 猫6无
分解步骤:
- 1.
enumerate(cats) - 得到:[(0,True), (1,False), (2,False), (3,True), (4,False), (5,False)] - 2.
for index, has_hat in enumerate(cats) - 遍历每个元组 - 3.
if has_hat - 只保留有帽子的情况 - 4.
index + 1 - 索引转猫编号(索引0→猫1)
💡 重要说明:
for index, has_hat in enumerate(cats) 中的 for 后面跟了两个参数,分别是 index 和 has_hat,它们对应的分别是 enumerate(cats) 返回的每个元组中的索引和值。
等价写法:
# 写法1:列表推导式(简洁)
hatted_cats = [index + 1 for index, has_hat in enumerate(cats) if has_hat]
# 写法2:普通for循环
hatted_cats = []
for index in range(len(cats)):
if cats[index]:
hatted_cats.append(index + 1)
# 写法3:使用enumerate的for循环
hatted_cats = []
for index, has_hat in enumerate(cats):
if has_hat:
hatted_cats.append(index + 1)
可视化函数
def visualize_cats(num_cats=20):
cats = [False] * num_cats # 初始化20只猫
for round_num in range(1, num_cats + 1):
# 操作
for cat_index in range(round_num - 1, num_cats, round_num):
cats[cat_index] = not cats[cat_index]
# 转换为表情符号:🎩表示有帽子,🐱表示没帽子
status = ["🎩" if has_hat else "🐱" for has_hat in cats]
# 显示状态
print(f"第{round_num:2d}轮: {' '.join(status)}")
💡 学习要点总结
- 2. 函数设计:每个函数只做一件事,提高代码可读性
这三个项目从不同角度展示了Python的强大功能:数据分析、游戏开发和逻辑推理。建议你亲自运行并手动编写这些代码,尝试修改参数,看看会产生什么不同的结果。
请记住:编程最好的学习方法就是动手实践!遇到问题不要怕,多尝试、多修改,你会在实践中快速成长。
📦 资源获取提示
关注「码农自习室」,后台回复关键词 Python学习,即可获取本文完整代码,一起动手掌握高效编程的核心技巧!
❤️ 支持我们
如果觉得本文对你有帮助,欢迎点赞 + 关注,您的支持是我们持续创作优质内容的最大动力!
📚 学习资源说明
本文内容是基于《Python Basics: A Practical Introduction to Python 3》(Real Python)一书的学习笔记整理。
这本书是一本非常优秀的Python入门教材,推荐给所有想要系统学习Python的朋友们。
这本书的特点:
跟着这本书学习,配合我的笔记整理,相信你能更快掌握Python编程!
让我们一起坚持学习,每天进步一点点!💪