如何动态创建非可变函数(没有eval或类似)?

时间:2017-10-21 14:38:41

标签: python arguments

概述

在运行时的某个时刻,我想创建一个完全获取给定数量的参数的函数(仅在运行时知道)。 完全这里意味着它不能是一个可变函数。有没有办法在不使用eval或类似方法将字符串解释为代码的情况下执行此操作?

我的问题(略有减少)

我想创建一个函数,该函数接受其参数并将它们作为可迭代函数传递给另一个函数。通常,我可以这样做:

my_function = lambda *args: other_function(args)

不幸的是,my_function将被一些无法正确处理可变函数的例程调用¹。但是,始终会使用相同数量的参数my_function调用n_args。所以,如果我知道n_args为3,我可以使用:

my_function = lambda a,b,c: other_function((a,b,c))

问题是我只是在创建n_args之前的运行时才知道my_function。因此,我需要概括上述内容。

到目前为止我找到了什么

  • 我使用eval(或exec或类似内容)实现了我的目标:

    arg_string = ",".join( "arg_%i"%i for i in range(n_args) )
    my_function = eval(
            "lambda %s: other_function((%s))" % (arg_string,arg_string),
            {"other_function":other_function}
        )
    

    这样做的缺点是我必须使用evalwhich is ugly and bad。如果您愿意,我的问题是如何在不使用eval或获取可变参数函数的情况下创建与上述内容相同的内容。

  • SymPy’s lambdify允许我在运行时动态创建具有固定数量参数的函数(在我的上下文中工作),但是查看源代码,它似乎使用{{1在引擎盖下也是如此。

¹这是用F2Py创建的编译例程。我现在无法通过合理的努力改变这一点。是的,这很难过,从长远来看,我会发现尝试解决这个问题或者解决这个问题,但是现在让我们接受这个。

1 个答案:

答案 0 :(得分:1)

创建如下所示的功能。你可以编写一个脚本来动态生成代码,只要你想要它,但仍然将结果静态保存在普通的python文件中,以避免使用eval / exec。

def function_maker(n_args, other_function):
    return [
        lambda: other_function(),
        lambda arg_0: other_function(arg_0),
        lambda arg_0, arg_1: other_function(arg_0, arg_1),
    ][n_args]

然后按如下方式使用:

function_maker(2, other_function)(a, b)