递归计算表达式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您的答案帮了大忙!非常感谢你!!