调试
找出程序为什么不对,再把它修好。
它是什么
调试 就是找错和改错。 程序出错时会说话。 先看最后一行的错误名字。 再看它指出的行号。
调试不是惩罚。 它更像体检:哪里红肿,就去哪里看。 会调试的人,不是从不犯错的人,而是能把错找出来的人。
程序也许能跑,结果却不对。 那也要调试。 这时没有红红的报错,要对着 算法 步骤,一行行走。
名字从哪来
debug 的意思是「去掉虫子」。 bug 在英语里是虫子,也用来指故障。
1947 年 9 月 9 日,哈佛大学的 Mark II 计算机出了故障。 工作人员在继电器里发现一只被夹住的飞蛾,把它贴进了日志本。 旁边写着:第一次真正找到虫子(First actual case of bug being found)。 格蕾丝·霍珀(Grace Hopper)的团队把这个故事传开了。 那本贴着飞蛾的日志,后来收藏在美国史密森尼博物馆。
「故障叫 bug」其实更早就有人用。 霍珀他们让这个词在计算机世界里出了名。
还有一个有名的办法叫橡皮鸭调试法(rubber duck debugging)。 1999 年的书《程序员修炼之道》讲过:有人把一只小黄鸭放在桌上,把自己的程序一行行讲给鸭子听。 讲着讲着,自己就听见哪里说不通了。 鸭子不会写代码。 它只是逼你把步骤说清楚。
它怎么工作
常见报错
SyntaxError:语法错。常忘冒号、括号或引号不配对。IndentationError:缩进 不对。NameError:名字还没定义。TypeError:类型不匹配。例如文字加整数。IndexError:列表 下标超出范围。ValueError:转换 失败。例如int("hello")。
for n in range(3) # 少了冒号,SyntaxError
print(n)print(score) # 还没赋值,NameErrorprint(3 + "2") # TypeError修 bug 的步骤
- 读报错最后一行
- 看行号
- 对照 注释 想本来要做什么
- 改一处,再运行一次
不要一次改十处。 改太多会迷路。
可以插入 print,把盒子里的值显示出来。 看见实际是什么,才知道和想象差在哪。
补全残缺代码时,先读注释。 注释写了目标,就按目标填。 保持 4 空格缩进。 名字用小写加下划线。
例如顺序查找缺一行「找到就停」。
最合适的常常是 break,不是 continue,也不是 pass。
pass 什么也不做。
continue 只跳过本圈。
return 用在 函数 里送结果。
讲给橡皮鸭听,也是合法步骤。 没有鸭子,讲给铅笔、讲给同学、讲给自己听,同样有效。
生活里在哪里
- 作业算错:从最后一步往回看,哪一行开始不对。
- 乐高缺一块:对照说明书,找到漏装的那一步。
- 灯不亮:先看插头,再看开关,一次查一处。
- 作文病句:老师圈出行号,你对那一行改。
- 迷路:回到上一个路牌,而不是随便再走十个路口。
科学家做实验失败,也会查步骤。 调试是同一种态度:证据,而不是碰运气。
和相近概念的差别
报错是信号。 调试是读信号、做修改的过程。
算法错了,程序可能完全不报错。 那叫逻辑错误。 语法错误通常跑都跑不起来。
注释 帮助调试,因为它写下了「本来要干什么」。 目标和实际一对照,错处会跳出来。
测试是先准备例子,看结果对不对。 调试是已经发现不对,去找原因。 先有例子,调试才有靶子。
常见误会
误会 1:报错就是失败。
报错更像老师批改。 它在帮你指出行号和类型。
误会 2:只看第一行英文,不看最后一行类型。
真正的错误名字,常常在最后一行。
误会 3:乱加引号或括号「碰运气」。
一次改一处。 改完立刻再跑。
误会 4:缩进用眼睛估。
按 4 的倍数对齐。 混用空格和 Tab 会更难查。
误会 5:能跑就一定对。
结果还要用人的标准检查。 尤其是 查找 和枚举,边界最容易悄悄出错。
想知道更多
- 书:潘洪波《小学生 Python 趣味编程》、埃里克·马瑟斯《Python 编程:从入门到实践》里的练习,做不出来时正好练「读报错、改一处」。
- 电影:《隐藏人物》(Hidden Figures)。和家长一起看:算错了怎样回头检查步骤——那正是调试的态度。
未登录时不会保存学习进度