scipy 在python中动态修复函数参数?

55ooxyrt  于 2022-11-10  发布在  Python
关注(0)|答案(2)|浏览(156)

考虑一些多参数的泛型函数:

def my_fun(x, a, b, c, d, e, f, g):
    return x, a, b, c, d, e, f, g

我想创建一种高阶函数,它可以修复my_fun的任意参数集合。例如:

fixing_function({"a": 100, "e": 200})

应返回如下所示的函数:

def fixed_function(x, b, c, d, f, g):
    return x, 100, b, c, d, 200, f, g

使用exec很容易做到,但我确信一定有更复杂的方法来做这类事情。这个问题的动机是使用scipy.optimize.curve_fit()。我需要多次拟合my_fun,改变哪些参数是固定的,哪些参数是拟合的。据我所知,这排除了在my_fun的定义中使用 *args和**kwargs。

xyhw6mcr

xyhw6mcr1#

我不知道下面的代码是“更像Python”还是更有效,但至少它在这个特定的情况下完成了这项工作:

from inspect import signature

def my_fun(x, a, b, c, d, e, f, g):
    return x, a, b, c, d, e, f, g

def fixing_function(orig_function, fixing_dict):
    orig_params = signature(orig_function).parameters
    remainingArgs = [key for key in orig_params.keys() if key not in fixing_dict]

    def new_function(*pos_args):
        zipped = dict(zip(remainingArgs, pos_args))
        new_args = zipped | fixing_dict
        return orig_function(**new_args)

    return new_function

fixed_function = fixing_function(my_fun, {"a": 100, "e": 200})

print(fixed_function(1, 2, 3, 4, 5, 6))

# output: (1, 100, 2, 3, 4, 200, 5, 6)

然而,它并不符合OP的目的,从print(getfullargspec(fixed_function))如何导致FullArgSpec(args=[], varargs='pos_args', varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})可以看出这一点(尽管如此,它可能对其他人有用)。
如果其他人想知道,下面是我使用eval来满足getfullargspec的尝试:

from inspect import signature, getfullargspec

def my_fun(x, a, b, c, d, e, f, g):
    return x, a, b, c, d, e, f, g

def fixing_function(orig_function, fixing_dict):
    orig_params = signature(orig_function).parameters
    remainingArgs = [key for key in orig_params.keys() if key not in fixing_dict]
    argSubtitute = [str(fixing_dict[key]) if key in fixing_dict else key for key in orig_params.keys()]
    partialF = f"lambda {','.join(remainingArgs)}:{orig_function.__name__}({','.join(argSubtitute)})"
    return eval(partialF)

fixed_function = fixing_function(my_fun, {"a": 100, "e": 200})  

print(fixed_function(1, 2, 3, 4, 5, 6))

# output: (1, 100, 2, 3, 4, 200, 5, 6)

print(getfullargspec(fixed_function))

# output: FullArgSpec(args=['x', 'b', 'c', 'd', 'e', 'g'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={})

应该有一些方法可以改进它。

vtwuwzda

vtwuwzda2#

假设您正在传递命名参数,则可以使用闭包

def outer(**some_params):
    def inner(**more_params):
        return {**some_params,**more_params}
    return inner

如果你正在使用一个旧版本的python,你可能需要一个函数来合并这两个字典

相关问题