首页 > 解决方案 > 如何根据用户输入动态定义函数?

问题描述

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

exec如果我定义to的范围,这种技术可以正常工作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 未定义”的错误。同时,在第二种情况下,它说“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

标签: pythonlambdaexec

解决方案


解决方案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']

exec关于和eval这里之间差异的一些好信息: eval、exec 和 compile 之间有什么区别?


顺便说一句,我可以看到你在你的问题中试图做什么,值得注意的是,文档页面和两者 明确警告这不起作用。同上,如果您在交互式解释器中输入,您会收到以下消息:exec()locals()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.

推荐阅读