使用逆波兰表示法构建具有 x,y 参数的函数

Building a function with x,y parameters using Reverse Polish notation

我正在尝试根据以逆波兰表示法给出的输入构建一个 python 函数。我的函数应该能够接受 xy 值作为参数,并且 return 函数的值分别为 xy

我的输入例如:

"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

你能帮我构建一个函数而不是直接生成结果吗 以及如何正确处理变量(例如 xy)?

您可以将解析代码从创建 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 范围的工作方式使得生成使用循环变量的函数有点棘手。这就是为什么我使用 tokennum 为生成的 lambda 函数中的参数设置默认值,而不是直接使用它们的名称。如果您只是执行 lambda **namespace: namespace[token],您会发现 token 在循环保持 运行 时改变了值。 bin_ops 代码没有这个问题,因为最终函数已经嵌套在一个额外的范围内,因为 lambda a, b 函数是我们构建内部 lambda 的地方。