查看全课大纲(第 24 / 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周存钱挑战4.0:你的存款计算器能有多灵活?

约 12 分钟

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

上一节我们让程序自动数着周数存钱,是不是感觉轻松多了?但你可能发现了问题:为什么我只能每周存10元、递增10元、存满52周呢?万一我想每周存50元,或者只想存半年呢?

这一节,我们就来解决这个问题!我们将把存款计划变成一个完全由你说了算的定制计算器。你可以输入任何金额、任何递增数、任何周数,程序都能立刻算出总存款。更酷的是,我们还会学习如何把计算逻辑打包成一个“计算器函数”,让代码更整洁、更专业。

💡 核心导读

  • 功能升级:从固定参数到灵活输入,让你的存款计算器真正“活”起来
  • 函数封装:把复杂的计算逻辑装进一个“盒子”(函数),随用随取
  • 变量作用域:理解为什么函数里的变量和外面的变量“互不相识”
  • 全局变量:如何让一个变量在所有地方都能被“看到”和修改

从“固定套餐”到“自助定制”

还记得我们3.0版本的固定参数吗?每周存10元,每周递增10元,存52周。现在我们要把这些“硬编码”的数字,变成可以由你随时调整的输入。

# 52周存钱挑战4.0 - 灵活定制版
import math

# 1. 让用户输入所有参数
money_per_week = 100  # 原程序这里用 input() 输入数字,用固定值代替(参与算术运算,故不加引号)

increase_money = 100  # 原程序这里用 input() 输入数字,用固定值代替(参与算术运算,故不加引号)

total_week = 100  # 原程序这里用 input() 输入数字,用固定值代替(参与算术运算,故不加引号)


# 2. 计算逻辑(和3.0一样,但现在用上面的变量)
money_list = []  # 记录每周存款数的列表
saving = 0       # 总存款金额

for i in range(total_week):
    money_list.append(money_per_week)
    saving = math.fsum(money_list)
    
    # 输出每周信息(暂时注释掉,让输出更简洁)
    # print(f'第{i+1}周,存入{money_per_week}元,账户累计{saving}元')
    
    # 更新下一周的存钱金额
    money_per_week += increase_money

# 3. 输出最终结果
print(f'经过{total_week}周,您的总存款金额为:{saving}元')
经过100周,您的总存款金额为:505000.0元

运行一下试试(你可以把代码复制到Python环境中运行):

  • 输入:每周存10元,每周递增10元,存52周 → 输出:13780元(和之前一样)
  • 输入:每周存100元,每周递增50元,存26周 → 输出:21450元
  • 输入:每周存20.5元,每周递增5元,存12周 → 输出:453.0元

是不是感觉这个计算器突然变得实用了?你可以根据自己的经济状况,制定任何存款计划!

把计算逻辑装进“函数盒子”

现在我们的程序已经能工作了,但代码看起来有点“散”。计算逻辑和输入输出混在一起,如果以后想在其他地方复用这个计算功能,就得把整段代码复制过去。

这时候就需要函数登场了!我们可以把计算存款的核心逻辑打包成一个独立的“计算器函数”。

# 定义一个专门计算N周存款的函数
def save_money_in_n_weeks(money_per_week, increase_money, total_week):
    """
    计算在指定周数内的总存款金额
    
    参数:
    money_per_week: 第一周存入的金额
    increase_money: 每周递增的金额
    total_week: 总共存款的周数
    
    返回:
    总存款金额
    """
    money_list = []
    
    for i in range(total_week):
        money_list.append(money_per_week)
        saving = math.fsum(money_list)
        
        # 更新下一周的存钱金额
        money_per_week += increase_money
    
    return saving  # 把计算结果"返回"给调用者

这个函数就像一个存款计算器:

  • 输入口:三个参数(每周金额、递增金额、总周数)
  • 处理区:内部的for循环计算逻辑
  • 输出口:return saving 把计算结果送出来

调用你的“存款计算器”

定义好函数后,怎么使用它呢?看下面的完整程序:

# 52周存钱挑战4.0 - 函数封装版
import math

def save_money_in_n_weeks(money_per_week, increase_money, total_week):
    """
    计算在指定周数内的总存款金额
    """
    money_list = []
    
    for i in range(total_week):
        money_list.append(money_per_week)
        saving = math.fsum(money_list)
        money_per_week += increase_money
    
    return saving

# 主程序开始
print("=== 52周存钱挑战计算器 ===")

# 1. 获取用户输入
weekly_money = 100  # 原程序用 input() 输入数字,用固定值代替(参与算术运算,故不加引号)

weekly_increase = 100  # 同上

weeks = 100  # 同上(range 需要整数)


# 2. 调用函数进行计算
total_saving = save_money_in_n_weeks(weekly_money, weekly_increase, weeks)

# 3. 输出结果
print(f'\n存款计划总结:')
print(f'- 每周起始金额:{weekly_money}元')
print(f'- 每周递增金额:{weekly_increase}元')
print(f'- 存款总周数:{weeks}周')
print(f'- 最终总存款:{total_saving}元')
print('=' * 30)
=== 52周存钱挑战计算器 ===

存款计划总结:
- 每周起始金额:100元
- 每周递增金额:100元
- 存款总周数:100周
- 最终总存款:505000.0元
==============================

关键点理解:

  • save_money_in_n_weeks(weekly_money, weekly_increase, weeks) 这就是调用函数
  • weekly_money、weekly_increase、weeks 是实参(实际参数)
  • 函数定义里的 money_per_week、increase_money、total_week 是形参(形式参数)
  • 调用时,实参的值会“传递”给形参,顺序要一一对应

变量的“地盘”:局部 vs 全局

这里有个有趣的现象,我们做个实验:

# 实验:理解变量作用域
saving_outside = 0  # 函数外面的变量

def test_function():
    saving_inside = 100  # 函数里面的变量
    print(f"函数内:saving_inside = {saving_inside}")
    print(f"函数内:saving_outside = {saving_outside}")

test_function()
print(f"函数外:saving_outside = {saving_outside}")
# print(f"函数外:saving_inside = {saving_inside}")  # 这行会报错!
函数内:saving_inside = 100
函数内:saving_outside = 0
函数外:saving_outside = 0

运行结果:

函数内:saving_inside = 100
函数内:saving_outside = 0
函数外:saving_outside = 0

发现了什么?

  1. 局部变量:saving_inside 只在函数内部有效,出了函数就“消失”了
  2. 全局变量:saving_outside 在函数内外都能被“看到”

如果想在函数内修改全局变量呢?

# 实验:修改全局变量
total = 0  # 全局变量

def add_money(amount):
    total = total + amount  # ❌ 这行会报错!
    print(f"存入{amount}元,当前总额:{total}")

# add_money(100)  # 取消注释会报错:UnboundLocalError

为什么报错?因为Python看到 total = ... 这行代码,就认为你要在函数内部创建一个新的局部变量叫total,而不是使用外部的全局变量。

正确做法:使用 global 关键字声明

# 正确修改全局变量的方法
total = 0  # 全局变量

def add_money(amount):
    global total  # 声明:我要使用的是全局变量total
    total = total + amount
    print(f"存入{amount}元,当前总额:{total}")

add_money(100)  # 存入100元,当前总额:100
add_money(50)   # 存入50元,当前总额:150
print(f"最终总额:{total}")  # 最终总额:150
存入100元,当前总额:100
存入50元,当前总额:150
最终总额:150

记住这个规则:

  • 函数内读取全局变量 → 可以直接用
  • 函数内修改全局变量 → 必须用 global 声明

为什么用函数?不只是为了好看!

你可能觉得:“把代码装进函数里,好像只是让程序变长了,没什么实际好处啊?”

其实函数有三大好处:

  1. 代码复用:一次定义,多次调用。比如你可以这样:

    # 计算不同存款方案
    方案1 = save_money_in_n_weeks(10, 10, 52)
    方案2 = save_money_in_n_weeks(20, 5, 26)
    方案3 = save_money_in_n_weeks(50, 0, 12)  # 不递增,每周固定50元
    
    print(f"方案1总存款:{方案1}元")
    print(f"方案2总存款:{方案2}元")
    print(f"方案3总存款:{方案3}元")
  2. 逻辑清晰:主程序只关心“输入什么、输出什么”,具体计算细节被隐藏起来

  3. 易于调试:如果计算逻辑有问题,只需要修改函数内部,不影响其他部分

📝 动手练一练

  1. 存款方案对比器 修改程序,让它能同时计算并对比两种不同的存款方案。比如:

    • 方案A:每周存50元,每周递增10元,存26周
    • 方案B:每周存100元,每周递增5元,存13周

    输出两个方案的总存款,并告诉用户哪个方案存款更多。

  2. 月度存款计算 现在的程序是按周计算的,但很多人习惯按月规划。创建一个新函数 save_money_in_n_months(),参数为:每月存款、每月递增金额、总月数。假设每月有4周,计算总存款。

  3. 目标存款计算器 反过来思考:如果我想在一年内(52周)存够2万元,每周递增金额固定为20元,那么第一周需要存多少钱?试着写程序解决这个问题(提示:可能需要尝试不同的起始金额,直到找到合适的)。

👉 点击查看第1题参考答案
# 存款方案对比器
import math

def save_money_in_n_weeks(money_per_week, increase_money, total_week):
    """计算N周存款总额"""
    money_list = []
    for i in range(total_week):
        money_list.append(money_per_week)
        money_per_week += increase_money
    return math.fsum(money_list)

# 方案A
plan_a_total = save_money_in_n_weeks(50, 10, 26)

# 方案B
plan_b_total = save_money_in_n_weeks(100, 5, 13)

print("=== 存款方案对比 ===")
print(f"方案A:每周50元起,每周+10元,存26周 → 总存款:{plan_a_total}元")
print(f"方案B:每周100元起,每周+5元,存13周 → 总存款:{plan_b_total}元")

if plan_a_total > plan_b_total:
    print("✅ 方案A存款更多!")
elif plan_a_total < plan_b_total:
    print("✅ 方案B存款更多!")
else:
    print("💰 两个方案存款一样多!")
=== 存款方案对比 ===
方案A:每周50元起,每周+10元,存26周 → 总存款:4550.0元
方案B:每周100元起,每周+5元,存13周 → 总存款:1690.0元
✅ 方案A存款更多!
👉 点击查看第2题思路提示

思路:

  1. 每月有4周,所以总周数 = 月数 × 4
  2. 每月存款金额需要平均分配到每周:每周存款 = 每月存款 ÷ 4
  3. 每月递增金额也需要平均到每周:每周递增 = 每月递增 ÷ 4
  4. 调用现有的 save_money_in_n_weeks 函数计算

关键代码片段:

import math

saving = 0       # 总存款金额
money_list = []  # 记录每周存款数的列表
total_week = 100  # 原程序这里用 input() 输入数字,用固定值代替(参与算术运算,故不加引号)
increase_money = 100  # 原程序这里用 input() 输入数字,用固定值代替(参与算术运算,故不加引号)
money_per_week = 100  # 原程序这里用 input() 输入数字,用固定值代替(参与算术运算,故不加引号)
def save_money_in_n_weeks(money_per_week, increase_money, total_week):
    """
    计算在指定周数内的总存款金额
    
    参数:
    money_per_week: 第一周存入的金额
    increase_money: 每周递增的金额
    total_week: 总共存款的周数
    
    返回:
    总存款金额
    """
    money_list = []
    
    for i in range(total_week):
        money_list.append(money_per_week)
        saving = math.fsum(money_list)
        
        # 更新下一周的存钱金额
        money_per_week += increase_money
    
    return saving  # 把计算结果"返回"给调用者


def save_money_in_n_months(monthly_money, monthly_increase, total_months):
    """计算N个月存款总额"""
    weeks = total_months * 4
    weekly_money = monthly_money / 4
    weekly_increase = monthly_increase / 4
    
    return save_money_in_n_weeks(weekly_money, weekly_increase, weeks)

# 测试:每月存400元,每月递增40元,存6个月
result = save_money_in_n_months(400, 40, 6)
print(f"6个月总存款:{result}元")
6个月总存款:5160.0元

本章小结

这一节我们完成了存款计算器的“终极进化”:

💪 你做到了什么?

  • ✅ 把固定参数变成灵活输入,让计算器真正实用
  • ✅ 学会了定义和调用函数,把复杂逻辑封装起来
  • ✅ 理解了局部变量和全局变量的区别
  • ✅ 掌握了在函数内修改全局变量的正确方法

📋 行动清单

学完立刻试试这些:

  • 用今天的程序计算你自己的存款计划(比如:每周存多少钱,多久能存到1万元?)
  • 尝试修改函数,让它返回每周的存款列表,而不仅仅是总金额
  • 思考:如果我想在存款过程中,某几周额外多存一些钱,程序该怎么修改?

预告下一节:现在我们的计算器已经很智能了,但还不够“贴心”。如果今天是8月5日,我想知道“到今天为止,我今年已经存了多少钱”,程序能算出来吗?下一节,我们将学习如何处理日期,让程序知道“今天是一年中的第几周”,然后计算出对应的存款金额。到时候,你的存款计算器就真的能“与时俱进”了!

—— 小象教研组

配套资料 · 直接下载

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

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