RPN评估程序优化而不会丢失可读性 [英] RPN Evaluator optimization without losing readability
问题描述
我正在实现一个需要RPN计算器功能的程序,但只有一个,但是对于python来说是新手,我想知道我是否可以在不损失可读性的情况下对其进行优化.
I'm implementing a program that needs a RPN calculator function, I've got the one bellow, but being new to python I wonder if I can optimize it without losing the readability.
使用字典等找到了一些解决方案,但是我迷失在"pythonesque"部分中,列表对我来说仍然有些困惑……
Found some solutions using dictionaries and so on, but I got lost in the 'pythonesque' parts, the lists are still somewhat of a mistery to me...
我的功能是:
def parseRPN(expression):
"""Parses and calculates the result fo an RPN expression
takes a list in the form of ['2','2','*']
returns 4
"""
try:
stack = []
for val in expression:
if val in ['-', '+', '*', '/']:
op1 = stack.pop()
op2 = stack.pop()
if val=='-': result = op2 - op1
if val=='+': result = op2 + op1
if val=='*': result = op2 * op1
if val=='/':
if op1==0:
result=1
else:
result = op2 / op1
stack.append(result)
elif val in ['sin','cos']:
op1 =stack.pop()
if val=='sin': result = sin(op1)
if val == 'cos': result = cos(op1)
stack.append(result)
else:
stack.append(float(val))
return stack.pop()
except:
print('error parse RPN fn:parse_rpn :' + str(expression))
return 10*10**10
预先感谢
推荐答案
原始实现很好,也很清楚.这是另一个使用更多Pythonic功能的应用程序:
The original implementation is fine, and clear. Here's another that uses more Pythonic features:
-
使用py.test(< 3)
tests using py.test (<3)
解析错误已被保留,因为它们已经表明发生了什么情况
parse errors are left alone, as they already indicate what's going on
operator
模块直接用于许多两个参数的函数,例如乘法
the operator
module is used directly for many two-argument functions, like multiply
同样,像sin
/cos
这样的单参数数学函数只需调用math
库
likewise, single-argument math functions like sin
/cos
just call the math
library
为方便起见,可以将表达式指定为单个字符串,例如"2 3 /"
for convenience, the expression can be specified as a single string, like "2 3 /"
计算器非常有趣,并且很好地介绍了诸如编译和解析之类的很酷的主题.玩得开心!
Calculators are a lot of fun, and are a great introduction to cool topics like compiling and parsing. Have fun!
import math
import operator
import pytest
ERROR_VALUE = -1.
def safe_divide(darg1, darg2):
try:
return darg1/darg2
except ZeroDivisionError:
return ERROR_VALUE
def parseRPN(expression):
"""Parses and calculates the result of a RPN expression
takes a list in the form of ['2','2','*']
returns 4
"""
# allow simple string: "2 3 /"
if isinstance(expression, basestring):
expression = expression.split()
function_twoargs = {
'*': operator.mul,
'/': safe_divide,
'+': operator.add,
'-': operator.sub,
}
function_onearg = {
'sin': math.sin,
'cos': math.cos,
}
stack = []
for val in expression:
result = None
if val in function_twoargs:
arg2 = stack.pop()
arg1 = stack.pop()
result = function_twoargs[val](arg1, arg2)
elif val in function_onearg:
arg = stack.pop()
result = function_onearg[val](arg)
else:
result = float(val)
stack.append(result)
return stack.pop()
def test_happy_paths():
assert parseRPN([2, 3, '*']) == 6.
assert parseRPN('0 sin') == 0.
assert parseRPN([2, 3, '/']) == 2./3
def test_safe_divide():
assert parseRPN([2, 0, '/']) == ERROR_VALUE
def test_parse_error():
with pytest.raises(ValueError) as excinfo:
parseRPN('gin')
assert str(excinfo.value) == 'could not convert string to float: gin'
这篇关于RPN评估程序优化而不会丢失可读性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!