大家好,欢迎来到IT知识分享网。
前两次课程,我们实现了在计算器软件中的整数和浮点的数的输入功能。这节课我们修改一下软件界面,增加回退的功能。并对代码做一定程度的重构(代码重构,是在一个项目开发过程中必不可少的工作)。
回退功能分析
从软件用户的角度来说,希望所做的操作如果有回退功能,使用起来会更加放心。现在的计算器大都有这种功能。一个功能的详细需求究竟应该是怎样的,经常来自一般的合理性分析。我们以计算器的回退功能为例,尝试进行合理性分析:
- 如果回退没有超过小数点,再次输入的数字理应继续在小数点之后;
- 即使恰好回退到最后一个小数位,我们认为小数点的作用仍然存在;
- 但再按一下,则直接消除个位,即小数点本身不应占一位,因为它始终显示;
- 一旦消除到个位,后面继续点击数字按钮的输入,都应当是整数了;
- 一个负数在回退的过程中,符号始终不变;
- 一旦回退到只剩个位的情况,继续回退则变为0;
- 变为0之后的继续输入,数字理应是正数,而不是负数;
根据实现方式的不同,这其中,有些功能是自动体现在代码中的,有些则必须做一些特别的处理才能做到。
回退功能实现
对于整数来说,我们的回退操作,可以通过除以10忽略余数的方法来实现。在python有这样的内置算符//(两个除号相连)。它的功能与%是对应的,%的功能是整数除法中只保留余数。
value= value// 10
对于浮点数来说,回退机制的表达很简单,就是保留的小数位减一。但实现的代码相对来说复杂一些。首先,保留的小数位,我们用了一个独立的变量来记录(decNum),把它减一是容易的。但同时也必须把我们现有的value值做一个截断小数位的操作,在python的数学库(math)中有这样的功能(floor),英文直译是地板,表达了向下取整的含义。朋友们可以会想,那么向上取整,会不会是ceiling(英文质疑是天花板)呢?还真差不多,向上取整的函数在python中是ceil。
decNum-= 1
value= math.floor(value*10**(decNum-1))/10**(decNum-1)
麻烦在于,我们这里不是取整,而是保留到N位。标准的做法是先把value扩大10的N次方倍,向下取整后,再缩写10的N次方倍。于是代码显得就长了一些。
下一个问题,什么时候用整数回退逻辑,什么时候用浮点数回退逻辑呢?我们用decNum作为判断标准,按了小数点后,decNum变成1,但我们前面约定:仅仅按小数点,不能“保护”最后一位被回退。所以我们以decNum<=1作为整数与小数的分界判断标准。
这部分的完整代码如下:
if decNum<=1:
decNum= 0
value= value// 10
if value==0:
sign=1
else:
decNum-= 1
value= math.floor(value*10**(decNum-1))/10**(decNum-1)
我们注意到,这里加了判断:如果value为0,则把sign标志设为1。这个变量是哪里来的呢?
负数功能的修改
我们前面代码,对于负数的处理是
value= -value
同时,在处理数字输入时,先把value取绝对值,当作正数来处理,之后再把符号传回去。如果仅仅是数字输入多了这一道手续,倒也无妨。可是现在增加了数字回退功能,为了操作上的正确,我们也必须做这个转换,出现了两次,这就显得重复了。
编程上有一个所谓的DRY原则(英文:Don’t Repeat Yourself. 的字头缩写,句子的含义为:别重复,提炼单词的直译为干燥)。为什么编程反对重复呢?一个最大的原因是怕修改,如果一个逻辑在两个地方出现,一旦它发生了变化,我们就必须记得修改两个地方。增加了工作量不说,还很容易出现这边改了,那边没改的问题,造成程序的运行错误。
elif event == '±':
sign= -sign
所以,在这里,我们宁可增加一个变量(sign),来单独标记运算符号。这样无论是输入数字还是回退,都无须再考虑正负数的问题,减少了代码量(即减少了出错机会)。在显示的时候,再考虑符号的问题。而且特别有意义的一点是:减少了符号与数字处理纠缠,分离了复杂性。这种修改我们总是欢迎的。
初始化功能
现在我们已经使用了三个内部变量来表示完整的状态:
- value:计算器内部数字的绝对值,初始=0
- decNum:下次输入数字时,对应的数字位权值,初始=0
- sign:计算器内部数字的正负号,初始=1
这三个变量都有初始值,应该在窗口启动前设置。点击了按钮后会发生变化,而在点击C按钮(清空按钮)后则应当重新设置为初始值。
根据DRY原则,我们不希望在两个地方都去设置这三个变量(由于我们还有很多功能没有实现,估计后面还会增加新的内部变量)。所以我们增加一个初始化函数init,这样在使用时只需调用这个函数即可。
这里,注意三个变量被注明为global,这样就可以在所有的地方使用。如果没有这个global的标记,这三个变量将被理解为仅是函数内的变量,在函数外就没有含义了。
课程小结
最后贴一下目前为止的完整代码,供参考:
由于代码已经比较长,用贴图的视觉效果比较好。如果朋友希望获得源代码,请直接联系一声索取即可。
希望朋友从本次课程中体会到根据软件开发的推进,随时进行重构的感觉。这种操作,在我们后面的开发实践中会经常遇到。Dry原则在本次课程中第一次出现,代码的重构也就是依据这个原则的精神(提高代码的复用程度)在进行。它的本质是减少未来必然会出现的代码修改的麻烦。正如前面课程中提到过的,现在的编程优先考虑的不是功能的实现,而是将来出现功能修改时,开发者怎样能够更主动。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/54383.html