2007-08-23

 

Python Cookbook 3.14 将Python做为简易计算器

需求:

你想将Python做为一个简易的计算器,计算十进制小数(非float),并能整齐的将结果显示出来.

讨论:

为了实现计算,我们可以使用decimal模块,我们接收输入行,用计算符号将它们连接起来,接收空行来显示当前结果,q来结束程序.
import decimal, re, operator
parse_input = re.compile(r'''(?x) # allow comments and whitespace in the RE
(\d+\.?\d*) # number with optional decimal part
\s* # optional whitespace
([-+/*]) # operator
$''') # end-of-string
oper = { '+': operator.add, '-': operator.sub,
'*': operator.mul, '/': operator.truediv,
}
total = decimal.Decimal('0')
def print_total( ):
print '== == =\n', total
print """Welcome to Adding Machine:
Enter a number and operator,
an empty line to see the current subtotal,
or q to quit: """
while True:
try:
tape_line = raw_input( ).strip( )
except EOFError:
tape_line = 'q'
if not tape_line:
print_total( )
continue
elif tape_line == 'q':
print_total( )
break
try:
num_text, op = parse_input.match(tape_line).groups( )
except AttributeError:
print 'Invalid entry: %r' % tape_line
print 'Enter number and operator, empty line for total, q to quit'
continue
total = oper[op](total, decimal.Decimal(num_text))
Python的交互式解析器经常可以用于计算器,不过我们写的计算器也能达到相同的目的.比如,对于一个类似表达式2345634+2894756-2345823 来说,要保证你输入的数字都是正确的也很不容易.我们的计算器用简单的,整齐的方式显示数字,让你更清楚自己都输入了什么数字.另外,decimal模块计算数字的方式和我们真实生活中是一样的,而不是使用float计算.
当你在一个shell中运行这个脚本的时候(这个脚本不能在交互式解析器中使用),脚本提示你输入, 然后就等待.输入一个数字(可以是小数),一个运算符(+,-,*,/),然后回车.这个脚本开始累加数字.要看当前的计算结果,输入回车就可以了.要退出程序,输入q就可以了.这个脚本实现了最简单的计算器,并提供了简易的界面.
本节的代码相当简单,所以可以有很多加强的地方.一个比较有用的就是记录下输入.实现起来很简单,在循环前处理就好了:

tapefile = open(' tapefile.txt', 'a')

然后输入用户输入就可以了,注意使用try/except:

tapefile.write(tape_line+'\n')

你也可以在输出结果的时候,同时将结果写入文件中去:
 def print_total( ):
print '== == =\n', total
tapefile.write('== == =\n' + str(total) + '\n')
file对象的write方法并不自己添加回车,所以我们需要自己写入回车符.另外我们也可以使用别的方式来实现这个功能:

print >>tapefile, '== == =\n', total

有些人不喜欢print >> somefile的写法,不过在这里真的很方便.
另外的优化比如缓冲输入,或者添加clear方法,甚至添加一个GUI界面,当然,有兴趣的读者可以自己实现.
本节中使用的一个要点就是oper字典,它将字符(+,-,*,/)和内建的operator方法关联起来,如果没有使用这个,就要使用一堆if/elif语句了,比如:
if op == '+':
total = total + decimal.Decimal(num_text)
elif op == '-':
total = total - decimal.Decimal(num_text)
elif op == '*':
<line_annotation>... and so on ...</line_annotation>
Python的字典是很灵活和强大的,可以让代码更简洁,可维护,并去掉重复代码.

标签:


Comments: 发表评论



<< Home

This page is powered by Blogger. Isn't yours?