开始之前
会定义函数只是开始。可靠的函数还需要清楚的数据边界:哪些变量只在函数内部使用、函数负责哪一个小任务,以及如何证明它对不同输入都有效。
本课把 M3 的边界检查、M4 的循环与累加、M5 的 list 和 dictionary 放进函数中。目标不是写更长的代码,而是把复杂度分成几个可以单独理解和测试的部分。
概念 01
Local variable 通常只在自己的函数内部可用
函数内部的数据不随意散落到程序其他位置,可以减少变量名互相干扰,也让数据从哪里来更清楚。
Local variable 的英文全称是 Local variable,中文叫局部变量,Python 中没有额外关键字;它是在函数内部创建的普通变量。例如 def calculate(): 内的 total = 10 + 5 会创建 local variable total。它的实际用途是在函数内部保存中间结果。
Scope 的英文全称是 Scope,中文叫作用域,描述一个变量可以在哪里使用。函数内部创建的 local variable 通常属于这个函数的 scope;在函数外直接 print(total) 会产生 NameError,因为外部位置找不到内部的 total。
下面的 message = "Hello" 只在 example() 内部可用。调试时看 NameError 的行号,再问:这个变量在哪一行创建?当前使用位置是否在同一个函数内部?本课不使用 global,只通过 parameter 把数据传入、通过 return 把结果传出。
- Local variable 在函数内部创建
- Scope 描述变量可使用的位置
- 函数外不能直接读取内部变量
- NameError 时检查创建与使用位置
- parameter 进入、return value 出来
在函数外读取 local variable 会产生 NameError
message 在 example 的函数 scope 中创建;调用结束后,函数外的 print(message) 不能直接找到它。需要使用时应 return message。
点击“运行”后,程序输出会显示在这里。
概念 02
Decomposition 把大问题拆成职责明确的小函数
读取输入、判断、计算和输出全部挤在一个函数中会很难检查;小函数可以分别理解、测试和复用。
Decomposition 的英文全称是 Decomposition,中文叫程序拆分,表示把较大的问题拆成几个较小任务。Python 没有叫 decomposition 的关键字;实现方式是定义职责清楚的 functions,例如成绩程序拆成 is_passing(score)、calculate_average(scores) 和 show_result(...). 它的实际用途是降低每一部分的认知负担。
Helper function 的英文全称是 Helper function,中文叫辅助函数,是帮助另一个较大任务完成一个小步骤的函数。例如 def is_passing(score): return score >= 50 只负责判断;show_status(score) 调用它并负责显示。
小而明确不代表每行都建函数。一个函数应该能用一句话描述职责,并通过 parameter 接收所需数据、return 需要交出的结果。Helper function 不应偷偷依赖函数外的临时变量。
- Decomposition 把大问题拆成小任务
- 每个函数负责一件清楚的事
- Helper function 帮助完成一个小步骤
- 数据通过 parameter 进入
- 结果通过 return 交出
判断与显示由两个函数分别负责
is_passing 只产生 Boolean 判断结果;show_status 使用这个 return value 决定显示哪条信息。
点击“运行”后,程序输出会显示在这里。
概念 03
Function testing 使用多组输入,也要检查缺少 return
一个输入正确不能证明函数普遍正确;边界值和不同值能暴露比较、循环或返回路径中的错误。
Function testing 的英文全称是 Function testing,中文叫函数测试,Python 中通过多次 function call 完成,例如 is_passing(49)、is_passing(50)、is_passing(80)。实际用途是分别检查普通值、boundary value 和不同值,而不是只选一个容易通过的输入。
对 is_passing(score) 来说,50 是规则改变的 boundary value:49 应为 False,50 和 80 应为 True。测试时先写下预期 return value,再运行调用并比较实际结果,这延续了 M3 的边界检查方法。
Missing return 的英文可以理解为“缺少 return”,本课把它作为调试技能。def add_bonus(score): score + 5 只是计算后丢弃结果;写成 print(score + 5) 也只显示。使用 result = add_bonus(80) 和 print(result) 会看到 None,提醒你检查函数是否把结果交回。
- 至少测试多个不同输入
- Boundary value 检查规则切换点
- 先写预期再比较实际
- 只有计算表达式不会自动返回
- 出现 None 时检查 return 路径
用边界值测试函数
49 检查边界下方,50 检查边界本身,80 是另一个普通值;三组结果一起验证 comparison。
点击“运行”后,程序输出会显示在这里。
概念 04
让 helper function、列表遍历和返回值逐层协作
把旧知识放进职责明确的函数后,可以建立“数据进入 → 小任务协作 → 结果返回 → 动态输出”的完整程序链。
先单独看 is_passing(score):parameter 接收一个分数,comparison 产生 Boolean,return 交回结果。再看 count_passes(scores):parameter 接收 list,Accumulator passed 从 0 开始,for 逐项遍历,if 使用 helper function 的 return value 决定是否累加。
最后,scores 保存实际数据,count_passes(scores) 的 return value 交给 result,f-string 才负责显示。每层只有一个清楚任务,因此可以先测试 is_passing 的 49、50,再测试 count_passes 的普通列表和空列表。
空 list 是重要 boundary case:for 不会执行任何一轮,passed 保持 0,函数仍然 return 0。这说明好的初始值能让循环自然处理没有元素的情况。
- 先理解并测试 helper function
- 主函数遍历 list
- if 使用 helper 的 Boolean 返回值
- Accumulator 保存累计结果
- 空列表自然返回 0
逐层组合判断、循环、累加与输出
helper function 判断单个分数;主函数遍历列表并累加;最终 return value 保存到 result,再由 f-string 显示。
点击“运行”后,程序输出会显示在这里。
常见错误
这些写法为什么不工作
错误不是失败,而是 Python 告诉你“这部分我无法理解”。先找到差异,再一次只改一个问题。
函数完成计算,却没有交回结果
表达式本身不会自动成为 return value。把调用结果保存后输出,若看到 None,就检查函数是否在需要的路径执行 return。
def calculate_area(width, height):
width * height
area = calculate_area(4, 3)
print(area)def calculate_area(width, height):
return width * height
area = calculate_area(4, 3)
print(area)只测试一个远离边界的值
80 通过不能证明 50 的边界写对。至少加入边界下方、边界本身和另一个不同值。
def is_passing(score):
return score > 50
print(is_passing(80))def is_passing(score):
return score >= 50
print(is_passing(49))
print(is_passing(50))
print(is_passing(80))引导修改
修改 helper function 并增加边界测试
这不是正式练习。跟着步骤修改已有代码,观察每次改变如何影响程序。
- 1先运行代码,确认 has_target(60) 的 return value 是 True。
- 2把 helper function 的规则改为 score 至少达到 70。
- 3增加对 69 和 70 的 function call,分别把 return value 保存到变量。
- 4使用 f-string 输出两个变量,确认 69 是 False、70 是 True。
完成后:修改后的 helper function 在 69 返回 False,在边界 70 返回 True,两个结果都保存并输出。
修改这段代码
先运行,再按左侧步骤逐项修改。你的草稿会保存在这个浏览器中。
点击“运行”后,程序输出会显示在这里。
正式练习
现在独立完成 2 道练习
先运行代码观察问题,再点击“检查答案”。检查只关心题目要求的结果,不要求你照抄参考写法。
正式练习
让加分结果真正返回
add_bonus(score) 应该使用 return 把新的分数交回调用位置,让 result 保存 85,并只输出 Result: 85。当前函数可能只是显示了计算结果。先 Run,观察 result 得到什么,再修复;保留 add_bonus function 和调用,不要直接把 result 固定写成 85。
点击“运行”后,程序输出会显示在这里。
需要一点提示?
先自己尝试一次;卡住时再逐级打开提示。
本课总结
本课小结
- 1Local variable 通常只在函数 scope 中使用,NameError 时检查创建位置与使用位置。
- 2Decomposition 把较大问题拆成职责明确的 functions,helper function 负责一个小步骤。
- 3Function testing 应覆盖普通值、boundary value、不同值与适用的空数据。
- 4缺少 return 或只使用 print() 会让调用得到 None;完整程序通过 parameters 和 return values 连接。