使用逆波兰表示法构建具有 x,y 参数的函数
Building a function with x,y parameters using Reverse Polish notation
我正在尝试根据以逆波兰表示法给出的输入构建一个 python 函数。我的函数应该能够接受 x
和 y
值作为参数,并且 return 函数的值分别为 x
和 y
。
我的输入例如:
"x 1 + y 3 * +"
我的预期结果是一个函数对象类似于:
fun = lambda x,y: x+1+y*3
这样我就可以调用 fun(1,2)
并得到 9
作为结果。
到目前为止,我可以评估没有变量的输入并给出结果。
bin_ops = {
"+": (lambda a, b: a + b),
"-": (lambda a, b: a - b),
"*": (lambda a, b: a * b),
"/": (lambda a, b: a / b),
}
def eval(expression):
tokens = expression.split()
stack = []
for token in tokens:
if token in bin_ops:
arg2 = stack.pop()
arg1 = stack.pop()
result = bin_ops[token](arg1, arg2)
stack.append(result)
else:
stack.append(float(token))
return stack.pop()
txt = '2 1 + 2 3 * +'
print(eval(txt)) # prints 9.0
你能帮我构建一个函数而不是直接生成结果吗
以及如何正确处理变量(例如 x
和 y
)?
您可以将解析代码从创建 values 更改为创建 functions ,可以使用关键字参数调用以进行最终评估:
bin_ops = {
"+": lambda a, b: lambda **namespace: a(**namespace) + b(**namespace),
"-": lambda a, b: lambda **namespace: a(**namespace) - b(**namespace),
"*": lambda a, b: lambda **namespace: a(**namespace) * b(**namespace),
"/": lambda a, b: lambda **namespace: a(**namespace) / b(**namespace),
}
def eval(expression):
tokens = expression.split()
stack = []
for token in tokens:
if token in bin_ops:
arg2 = stack.pop()
arg1 = stack.pop()
result = bin_ops[token](arg1, arg2)
stack.append(result)
else:
try:
num = float(token)
except ValueError:
stack.append(lambda *, _token=token, **namespace: namespace[_token])
else:
stack.append(lambda *, _num=num, **namespace: _num)
return stack.pop()
txt = "x 1 + y 3 * +"
fun = eval(txt)
print(fun(x=2, y=4)) # prints 15.0
Python 范围的工作方式使得生成使用循环变量的函数有点棘手。这就是为什么我使用 token
和 num
为生成的 lambda
函数中的参数设置默认值,而不是直接使用它们的名称。如果您只是执行 lambda **namespace: namespace[token]
,您会发现 token
在循环保持 运行 时改变了值。 bin_ops
代码没有这个问题,因为最终函数已经嵌套在一个额外的范围内,因为 lambda a, b
函数是我们构建内部 lambda
的地方。
我正在尝试根据以逆波兰表示法给出的输入构建一个 python 函数。我的函数应该能够接受 x
和 y
值作为参数,并且 return 函数的值分别为 x
和 y
。
我的输入例如:
"x 1 + y 3 * +"
我的预期结果是一个函数对象类似于:
fun = lambda x,y: x+1+y*3
这样我就可以调用 fun(1,2)
并得到 9
作为结果。
到目前为止,我可以评估没有变量的输入并给出结果。
bin_ops = {
"+": (lambda a, b: a + b),
"-": (lambda a, b: a - b),
"*": (lambda a, b: a * b),
"/": (lambda a, b: a / b),
}
def eval(expression):
tokens = expression.split()
stack = []
for token in tokens:
if token in bin_ops:
arg2 = stack.pop()
arg1 = stack.pop()
result = bin_ops[token](arg1, arg2)
stack.append(result)
else:
stack.append(float(token))
return stack.pop()
txt = '2 1 + 2 3 * +'
print(eval(txt)) # prints 9.0
你能帮我构建一个函数而不是直接生成结果吗
以及如何正确处理变量(例如 x
和 y
)?
您可以将解析代码从创建 values 更改为创建 functions ,可以使用关键字参数调用以进行最终评估:
bin_ops = {
"+": lambda a, b: lambda **namespace: a(**namespace) + b(**namespace),
"-": lambda a, b: lambda **namespace: a(**namespace) - b(**namespace),
"*": lambda a, b: lambda **namespace: a(**namespace) * b(**namespace),
"/": lambda a, b: lambda **namespace: a(**namespace) / b(**namespace),
}
def eval(expression):
tokens = expression.split()
stack = []
for token in tokens:
if token in bin_ops:
arg2 = stack.pop()
arg1 = stack.pop()
result = bin_ops[token](arg1, arg2)
stack.append(result)
else:
try:
num = float(token)
except ValueError:
stack.append(lambda *, _token=token, **namespace: namespace[_token])
else:
stack.append(lambda *, _num=num, **namespace: _num)
return stack.pop()
txt = "x 1 + y 3 * +"
fun = eval(txt)
print(fun(x=2, y=4)) # prints 15.0
Python 范围的工作方式使得生成使用循环变量的函数有点棘手。这就是为什么我使用 token
和 num
为生成的 lambda
函数中的参数设置默认值,而不是直接使用它们的名称。如果您只是执行 lambda **namespace: namespace[token]
,您会发现 token
在循环保持 运行 时改变了值。 bin_ops
代码没有这个问题,因为最终函数已经嵌套在一个额外的范围内,因为 lambda a, b
函数是我们构建内部 lambda
的地方。