调试和编写程序方法

当出现语法错误或者运行错误时

错误信息会很多,但是通常有用部分是:

  • 是哪类错误
  • 在哪儿出现
是应该花一些时间仔细阅读错误信息,但是不要轻易的认为错误信息的提示都是准确的,特别是错误信息的位置,有时候并不是真正的繁盛错误的地方。

增量式开发(incremental)

增量式开发的目标,是通过每次只增加和测试少量代码,来避免长时间的调试。
先建立骨架,具体代码可以不放,然后慢慢增加。

这种开发方式的关键是:

  1. 从一个能运行的程序开始,并且每次只增加少量改动。无论你何时遇到错误,都能够清楚定位错误的源头。
  2. 用临时变量存储中间值,这样你就能显示并检查它们。
  3. 一旦程序正确运行,你要删除一些脚手架代码,或者将多条语句组成复合表达式,但是前提是不会影响程序的可读性。

粗心的使用列表

  • 大多数的列表方法会对参数进行修改,然后返回 None 。这和字符串方法相反,后者保留原始的字符串并返回一个新的字符串。

如果你习惯这样写字符串代码:

word = word.strip()

那么你很可能会写出下面的列表代码:

t = t.sort()           # 错误!

因为 sort 返回 None ,所以你的下一个对 t 执行的操作很可能会失败。


  • 选择一种写法,坚持下去。

列表的一个问题就是有太多方法可以做同样的事情。 例如,要删除列表中的一个元素,你可以使用 pop 、remove 、del 甚至是切片赋值。

要添加一个元素,你可以使用 append 方法或者 + 运算符。假设 t 是一个列表,x 是一个列表元素,以下这些写法都是正确的:

t.append(x)
t = t + [x]
t += [x]

而这些是错误的:

t.append([x])          # 错误!
t = t.append(x)        # 错误!
t + [x]                # 错误!
t = t + x              # 错误!

  • 通过创建拷贝来避免别名.

如果你要使用类似 sort 这样的方法来修改参数, 但同时有要保留原列表,你可以创建一个拷贝。

>>> t = [3, 1, 2]
>>> t2 = t[:]
>>> t2.sort()
>>> t
[3, 1, 2]
>>> t2
[1, 2, 3]

在这个例子中,你还可以使用内置函数 sorted ,它将返回一个新的已排序的列表,原列表将保持不变。

>>> t2 = sorted(t)
>>> t
[3, 1, 2]
>>> t2
[1, 2, 3]

操作大的数据集时


  • 缩小输入:

如果可能,减小数据集合的大小。 例如,如果程序读入一个文本文件,从前10行开始分析,或是找到更小的样例。 你可以选择编辑读入的文件,或是(最好)修改程序使它只读入前 n 行。

如果出错了,你可以将 n 缩小为会导致该错误的最小值,然后在查找和解决错误的同时,逐步增加 n 的值。

  • 检查摘要和类型

考虑打印数据的摘要,而不是打印并检查全部数据集合: 例如,字典中项的数目或者数字列表的总和。

运行时错误的一个常见原因,是值的类型不正确。 为了调试此类错误,打印值的类型通常就足够了。

  • 编写自检代码

有时你可以写代码来自动检查错误。 例如,如果你正在计算数字列表的平均数,你可以检查其结果是不是大于列表中最大的元素,或者小于最小的元素。 这被称 作“合理性检查”,因为它能检测出“不合理的”结果。

另一类检查是比较两个不同计算的结果,来看一下它们是否一致。这被称作“一致性检查”。

  • 格式化输出
格式化调试输出能够更容易定位一个错误。 我们在调试一节中看过一个示例。pprint模块提供了一个 pprint 函数,它可以更可读的格式显示内建类型( pprint 代表 “pretty print”)。












你可能感兴趣的:(python)