如何根据用户输入动态定义函数?

How can I dynamically define a function from user input?

我正在尝试根据用户输入动态生成函数。用户提供一个函数作为字符串输入,给出不同的参数,我想编写一个函数,将这个字符串变成一个可用的函数。到目前为止,我的想法是使用 exec 函数创建一个 lambda 函数,该函数使用如下字符串构造:exec("f = lambda {}:{}".format(', '.join(['x'] + parameter_list), function_string))。例如,这会给 exec 函数一个类似 "f = lambda x, a:x+a" 的字符串。

如果我将 exec 的范围定义为 globals(),此技术工作正常,但我希望我的函数是本地的,以便我可以执行如下操作:

def define_function(function_string, parameter_list):
    exec("f = lambda {}:{}".format(', '.join(['x'] + parameter_list), function_string))
    return f

或者像这样:

def define_function(function_string, parameter_list):
    exec("return lambda {}:{}".format(', '.join(['x'] + parameter_list), function_string))

但是,在第一种情况下,它给出了类似“f is not defined”的错误。同时,在第二种情况下,它表示“return 只能在函数中使用”。我明白为什么会出现第二个错误,但我想知道为什么我的第一次尝试没有成功。使用 globals() 可以使它工作,但我不想使用它。

如果您对实现相同结果的其他方法有任何建议,我也很感兴趣。

编辑

使用 eval 也会引发错误:

line 9, in define_function
    eval("f = lambda {}:{}".format(', '.join(['x'] + parameter_list), function_string))
  File "<string>", line 1
    f = lambda x, a:x+a
      ^
SyntaxError: invalid syntax

解决方案 1:使用 eval():

def get_func(param_list, result_str):
    return eval("lambda {}: {}".format(', '.join(['x'] + param_list), result_str))

解决方案 2:如果您真的想使用 exec(),请执行以下操作:

def get_func(param_list, result_str):
    exec("f = lambda {}: {}".format(', '.join(['x'] + param_list), result_str))
    return locals()['f']

这里有一些关于 execeval 之间区别的有用信息:What's the difference between eval, exec, and compile?


顺便说一句,我可以看到你在问题中试图做什么,值得注意的是 exec()locals()documentation pages 都明确警告这是行不通的。同上,如果您在交互式解释器中键入 help(locals),您会收到此消息:

Help on built-in function locals in module builtins:

locals()
    Return a dictionary containing the current scope's local variables.

NOTE: Whether or not updates to this dictionary will affect name lookups in
the local scope and vice-versa is *implementation dependent* and not
covered by any backwards compatibility guarantees.