RPN评估程序优化而不会丢失可读性 [英] RPN Evaluator optimization without losing readability

查看:100
本文介绍了RPN评估程序优化而不会丢失可读性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现一个需要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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆