一、防御性编程与备注
举个例子理解下什么叫做防御性编程的基本思想:比如在温度转换的代码中,我们想通过input()函数从用户那里获得输入,即带有单位的温度值。我们可以在input()函数中写明输入内容的格式要求,但用户很可能漏掉温度单位的输入,或是单位使用错误。此时就需要考虑输入不符合要求的条件下的输出:
TempStr = input("请输入带有符号的温度值:")
if TempStr[-1] in ['F','f']: #判断前者是否与列表中某个元素相同
c = (eval(TempStr[0:-1]) - 32)/1.8
print("转换后的温度是{:.2f}C".format(C))
elif TempStr[-1] in ['C','c']:
F = 1.8*eval(TempStr[0:-1]) + 32
print("转换后的温度是{:.2f}F".format(F))
else:
print("输入格式错误")
当然不仅仅是用户会犯错,代码编写人员也可能犯错。比如想找到某个整数的所有除数,选择在循环中间打印出来:
x = 10
i = 1
if i < x:
if x % i == 0:
print('divisor', i)
i = i + 1
打印结果发现只有1一个除数,显然是不对的。这是因为最外层使用的是if语句,导致无法进入循环(对!就是《开端》里的那种循环),需要改成while循环语句:
x = 10
i = 1
while i < x:
if x % i == 0:
print('divisor', i)
i = i + 1
二、科学分析思维
1. 迭代问题逻辑
1、选择一个可以计数的变量(Choose variable that "count");
2、在外部需要初始化它(Initiative outside the loop);
3、设置正确的最终测试(Setup and test);
4、构建代码块(Conctract block);
5、当结束后,知道该怎么做(What to do when done)。
上述计算除数的例子就可以看作是一个迭代问题,i就是用来计数的变量,同时也是得到正确答案时的输出,在外部给定的初始值为1。
2. 代码效率
目前需要解决的问题的增长速度高于电脑计算速度的增长,在时间空间恒定的情况下,需要考虑:
1、计算需要多少内存;
2、输入大小的函数所需的基本步骤数量是多少。
三、Debugger
首先要发现产生问题的最小输入,然后采用二分法打印测试,这样每次测试都可以排除一半的代码块。
此外,将代码分成几个模块,每个模块负责对应相关的操作,即对代码抽象化、模块化、封装代码的操作,可以方便阅读,同时也可以便于后续的debug。
四、修复他人的代码
我们常常会借鉴(搬运)别人的代码,但受到版本、运行环境等的影响,并不是每一份代码都可以完整复现,所以如何更好的修复他人的代码呐?这要有一个系统性的思考:
1、保持记录你尝试的方式、修改的地方;
2、考虑重新假设;
3、调试代码;
4、放下自己的骄傲,寻找他人的帮助,或者离开一段时间再回来修复,我觉得这一步可以帮助自己换个角度思考问题,也许对问题的解决更有帮助。