Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中参数变化的高阶函数_Python - Fatal编程技术网

Python中参数变化的高阶函数

Python中参数变化的高阶函数,python,Python,我一遍又一遍地重复以下代码: def foo(data): result = (0, 0, 0) var1, var2, var3 = init_variables(data) for i in xrange(var1): result[0] += variable_func_1(data, var2, var3) result[1] += variable_func_2(data, var3) result[2] += f

我一遍又一遍地重复以下代码:

def foo(data):
    result = (0, 0, 0)
    var1, var2, var3 = init_variables(data)
    for i in xrange(var1):
        result[0] += variable_func_1(data, var2, var3)
        result[1] += variable_func_2(data, var3)
        result[2] += fixed_func()
return result
在所有重复过程中,所有函数都是固定的,除了
variable\u func\n
可以接受可变数量的参数外,这些函数的数量也会变化

我想找出所有这些函数的通用代码,因此首先想到的是使用高阶函数,如:

def foo(data, func_list):
    var1, var2, var3 = init_variables(data)
    results = (len(func_list) + 1) * [0]
    for i in xrange(var1):
        for j, func in enumerate(func_list):
            results[j] += (func(data, var1, var2, var3))
        results[len(func_list)] += fixed_func()
    return results

这个解决方案的问题是,它需要修改所有变化函数的签名,以便它们可以接受更多的参数。有没有一个更干净的解决方案不需要我修改所有传入函数的签名?

我认为最简单的方法就是传递一个包含所有数据的列表


您也可以为每个函数提供可选参数,但这不会有多大帮助

也许您正在寻找
inspect
模块

In [11]: import inspect

In [12]: def f(a, b): pass

In [13]: inspect.getargspec(f)
Out[13]: ArgSpec(args=['a', 'b'], varargs=None, keywords=None, defaults=None)
这个库可以告诉您每个函数中的参数数量以及每个参数的名称,这样您就可以添加自己的逻辑来确保正确调用该函数


真正的答案是您可能需要重构代码,老实说,这种模式对我来说有点奇怪。

假设您的函数数量有限,创建一个参数查找表怎么样?它确实插入了一个额外的重定向层并复制了一些信息,但如果我理解正确的话,它还可以替换许多其他复制粘贴的功能:

func_sigs = {
    func1: ['data', 'var2', 'var3'],
    func2: ['data', 'var3']
}

def call_func(f, data, var1, var2, var3):
    args = [locals()[key] for key in func_sigs[f]]
    return f(*args)


def foo(data, func_list):
    var1, var2, var3 = init_variables(data)
    results = (len(func_list) + 1) * [0]
    for i in xrange(var1):
        for j, func in enumerate(func_list):
            results[j] += (call_func(func, data, var1, var2, var3))
        results[len(func_list)] += fixed_func()
    return results

更大的问题是为什么要保持签名的原样:是保持API兼容性还是不想重构?

也许可以使用关键字参数(kwargs)kwargs将要求我修改传入的每个函数的签名。不幸的是,不同函数的参数是否有规律性?就像任何可检查的规则一样,它说它应该是
variable\u func\u 1(数据,var2,var3)
而不是
variable\u func\u 1(数据,var3,var2)
?如果没有这样的规定,那么我相信你所要求的是不可能的。即使是
inspect
也无法判断哪个值应该指向哪个位置。有这样一个规则,但我认为依赖它会导致代码脆弱<代码>检查可能是不进行重构的最佳解决方案。这是一个很酷的功能:o不知道这个。请接受我的投票!我同意这种模式有点奇怪。对于上下文,不同的函数是计算密集型的,所以我不想在不必要的时候全部调用它们,它们也会返回不同的值,所以我不想将它们都放在一个函数中的一个大if/elif语句中,并让该函数返回不同的值。使用inspect是一种不好的做法,是一种黑客行为。如果可能的话,你应该努力使你的函数API在没有黑客攻击的情况下是有用的,特别是如果你想在你的代码上使用inspect的话。我愿意重构,我只是没有想到一个引人注目的解决方案。所有不同的函数都需要来自init_变量的信息,但返回不同的值,不需要同时调用。(我正在研究一种优化参数子集的机器学习算法,变化的函数实际上是用于计算这些参数子集梯度的函数。)