递归计算表达式python

递归计算表达式python,python,recursion,Python,Recursion,我正在做一个表达式解析器。我从字符串开始: s = 'abs(multiply(4,add(-4,2)))' 最终将达到 s = 8 目前,当我测试代码时,我到达print语句并得到 'abc(multiply(4,-2))' 但是,如果我想递归地执行此操作并继续该函数,则会出现以下错误: Traceback (most recent call last): File "test.py", line 44, in <module> print eval_expr(s

我正在做一个表达式解析器。我从字符串开始:

s = 'abs(multiply(4,add(-4,2)))'
最终将达到

s = 8
目前,当我测试代码时,我到达print语句并得到

'abc(multiply(4,-2))'
但是,如果我想递归地执行此操作并继续该函数,则会出现以下错误:

Traceback (most recent call last):
  File "test.py", line 44, in <module>
    print eval_expr(s)
  File "test.py", line 41, in eval_expr
    return eval_expr(new_expr)  
  File "test.py", line 37, in eval_expr
    new_expr = str(rest + _2 + value + arg1[arg1.find(')') + 1:])
  UnboundLocalError: local variable 'value' referenced before assignment
更新

现在我的代码在第二次迭代时被卡住了。第一次迭代的结果是

op = 'abs(multiply(4,add'
_1 = '('
arg1 = '-4,2)))'

rest = 'abs(multiply(4'
_2 = ','
thisop = 'add'

args = ['4','-2']
j = [4,-2]    
第二次迭代是(使用新表达式“abc(乘法(4,-2))”


我认为这是由于运算符内部的运算符或运算符内部有2个整数。

我假设您了解“eval”函数,编写它是为了好玩,或者是为了通过手工创建解析器来学习

local variable 'value' referenced before assignment
表示您在声明“value”之前尝试使用它。我知道,您在if…elseif…中声明了它,但显然这些条件都不起作用,因此没有执行对“value”的赋值。最后,本地命名空间中没有“value”!您应该检查“thisop”值,以了解它包含的内容,您可能遗漏了一些括号ipping或smth之类的


祝你好运。

我假设你知道“eval”函数,你写它是为了好玩,或者是为了学习手工创建解析器

local variable 'value' referenced before assignment
表示您在声明“value”之前尝试使用它。我知道,您在if…elseif…中声明了它,但显然这些条件都不起作用,因此没有执行对“value”的赋值。最后,本地命名空间中没有“value”!您应该检查“thisop”值,以了解它包含的内容,您可能遗漏了一些括号ipping或smth之类的


祝你好运。

你的
值是未定义的,你说
如果elif elif elif
,但是你没有最后的选择,(在这种情况下,你会得到错误,因为你没有说在那种情况下的值是什么)

你的
值是未定义的,你说
如果elif elif elif elif
,但是你没有最后的选择,(在这种情况下,您将得到该错误,因为在这种情况下您没有说明值是什么)

另一种方法:如果您的每个函数都有固定数量的参数,您可以删除所有括号和逗号,并使用堆栈来处理它。无需递归、搜索逗号和括号等:

def parse (s):
    #Just throwing away all parentheses and commata
    s = s.replace ('(', ' ').replace (')', ' ').replace (',', ' ')
    #Return reversed polish notation
    return s.split () [::-1]

def evaluate (ops):
    stack = []
    while ops:
        op = ops [0]
        ops = ops [1:]
        try:
            stack.append (int (op) )
            continue
        except: pass
        try:
            stack.append (float (op) )
            continue
        except: pass
        if op == 'add':
            arg1, arg2 = stack.pop (), stack.pop ()
            stack.append (arg1 + arg2)
            continue
        if op == 'multiply':
            arg1, arg2 = stack.pop (), stack.pop ()
            stack.append (arg1 * arg2)
            continue
        if op == 'abs':
            arg1 = stack.pop ()
            stack.append (abs (arg1) )
            continue
        raise Exception ('Unkown instruction "{}".'.format (op) )
    return stack [0]

ops = parse ('abs(multiply(4,add(-4,2)))')
print (evaluate (ops) )
ops = parse ('multiply add 1 2 add add 3 4 5')
print (evaluate (ops) )
即使您有var adic函数,这些函数也可以转录成n adic函数。例如,
add(1,2,3,4)
可以使用并矢
add
作为
add 1 2 3 4
编写


我将对此示例进行一点扩展。在某些情况下,所有的
if
-语句都会使代码难以辨认。但是您可以为运算符定义一个类,定义其参数数量及其结果:

class Operator:
    def __init__ (self, argc, f):
        self.argc = argc
        self.f = f

    def __call__ (self, *args):
        return self.f (*args)
现在,您可以将
求值
函数简化一点。下面是一个计算斐波那契数的工作示例:

#! /usr/bin/python3

from random import randrange

class Operator:
    def __init__ (self, argc, f):
        self.argc = argc
        self.f = f

    def __call__ (self, *args):
        return self.f (*args)

def parse (s):
    s = s.replace ('(', ' ').replace (')', ' ').replace (',', ' ')
    return s.split () [::-1]

def evaluate (ops):
    stack = []
    while ops:
        op = ops [0]
        ops = ops [1:]
        try:
            stack.append (int (op) )
            continue
        except: pass
        try:
            stack.append (float (op) )
            continue
        except: pass
        try:
            operator = operators [op]
        except:
            raise Exception ('Unkown operator {}'.format (op) )
        args = [stack.pop () for _ in range (operator.argc) ]
        stack.append (operator (*args) )
    return stack [0]

operators = {
    'add': Operator (2, lambda a, b: a + b),
    'sub': Operator (2, lambda a, b: a - b),
    'mul': Operator (2, lambda a, b: a * b),
    'div': Operator (2, lambda a, b: a / b),
    'pow': Operator (2, lambda a, b: a ** b),
    'floor': Operator (1, lambda a: int (a) ),
    'abs': Operator (1, lambda a: abs (a) ),
    }

n = int (input ('Which fibonacci number do you want: ') )
fib = 'floor add div pow div add 1 pow 5 .5 2 {} pow 5 .5 .5'.format (n)
#or if you like parentheses: 'floor(add(div(pow(div(add(1,pow(5,.5)),2),{}),pow(5,.5)),.5))'
ops = parse (fib)
print ('F({}) = {}'.format (n, evaluate (ops) ) )

另一种方法是:如果每个函数都有固定数量的参数,则可以去掉所有括号和逗号,并使用堆栈进行处理。无需递归、搜索逗号和括号等:

def parse (s):
    #Just throwing away all parentheses and commata
    s = s.replace ('(', ' ').replace (')', ' ').replace (',', ' ')
    #Return reversed polish notation
    return s.split () [::-1]

def evaluate (ops):
    stack = []
    while ops:
        op = ops [0]
        ops = ops [1:]
        try:
            stack.append (int (op) )
            continue
        except: pass
        try:
            stack.append (float (op) )
            continue
        except: pass
        if op == 'add':
            arg1, arg2 = stack.pop (), stack.pop ()
            stack.append (arg1 + arg2)
            continue
        if op == 'multiply':
            arg1, arg2 = stack.pop (), stack.pop ()
            stack.append (arg1 * arg2)
            continue
        if op == 'abs':
            arg1 = stack.pop ()
            stack.append (abs (arg1) )
            continue
        raise Exception ('Unkown instruction "{}".'.format (op) )
    return stack [0]

ops = parse ('abs(multiply(4,add(-4,2)))')
print (evaluate (ops) )
ops = parse ('multiply add 1 2 add add 3 4 5')
print (evaluate (ops) )
即使您有var adic函数,这些函数也可以转录成n adic函数。例如,
add(1,2,3,4)
可以使用并矢
add
作为
add 1 2 3 4
编写


我将对此示例进行一点扩展。在某些情况下,所有的
if
-语句都会使代码难以辨认。但是您可以为运算符定义一个类,定义其参数数量及其结果:

class Operator:
    def __init__ (self, argc, f):
        self.argc = argc
        self.f = f

    def __call__ (self, *args):
        return self.f (*args)
现在,您可以将
求值
函数简化一点。下面是一个计算斐波那契数的工作示例:

#! /usr/bin/python3

from random import randrange

class Operator:
    def __init__ (self, argc, f):
        self.argc = argc
        self.f = f

    def __call__ (self, *args):
        return self.f (*args)

def parse (s):
    s = s.replace ('(', ' ').replace (')', ' ').replace (',', ' ')
    return s.split () [::-1]

def evaluate (ops):
    stack = []
    while ops:
        op = ops [0]
        ops = ops [1:]
        try:
            stack.append (int (op) )
            continue
        except: pass
        try:
            stack.append (float (op) )
            continue
        except: pass
        try:
            operator = operators [op]
        except:
            raise Exception ('Unkown operator {}'.format (op) )
        args = [stack.pop () for _ in range (operator.argc) ]
        stack.append (operator (*args) )
    return stack [0]

operators = {
    'add': Operator (2, lambda a, b: a + b),
    'sub': Operator (2, lambda a, b: a - b),
    'mul': Operator (2, lambda a, b: a * b),
    'div': Operator (2, lambda a, b: a / b),
    'pow': Operator (2, lambda a, b: a ** b),
    'floor': Operator (1, lambda a: int (a) ),
    'abs': Operator (1, lambda a: abs (a) ),
    }

n = int (input ('Which fibonacci number do you want: ') )
fib = 'floor add div pow div add 1 pow 5 .5 2 {} pow 5 .5 .5'.format (n)
#or if you like parentheses: 'floor(add(div(pow(div(add(1,pow(5,.5)),2),{}),pow(5,.5)),.5))'
ops = parse (fib)
print ('F({}) = {}'.format (n, evaluate (ops) ) )

请将答案标记为“已接受”,以便@FilipMalczak获得信誉:-)请将答案标记为“已接受”,以便@FilipMalczak获得信誉:-)请查看我的答案的最后一次编辑,这简化了代码。@Hyperboreus您的答案帮了大忙!非常感谢你!!请看我的答案的最后一次编辑,它简化了一点代码。@Hyperboreus您的答案帮了大忙!非常感谢你!!