将函数列表及其相应参数传递给另一个函数

时间:2021-05-06 18:02:45

I am struggling to pass a list of functions with a list of corresponding parameters. I also checked here, but it wasn't very helpful. for example (a naive approach which doesn't work):

我正在努力传递一系列具有相应参数列表的函数。我也在这里查了一下,但是没有用。例如(一种不起作用的天真方法):

def foo(data, functions_list, **kwarg):
    for func_i in functions_list:
        print func_i(data, **kwarg)

def func_1(data, par_1):
    return some_function_1(data, par_1)

def func_2(data, par_2_0, par_2_1):
    return some_function_2(data, par_2_0, par_2_1)

foo(data, [func_1, func_2], par_1='some_par', par_2_0=5, par_2_1=11)

Importantly, par_1 cannot be used in func_2, so each function consumes a unique set of parameters.

重要的是,par_1不能在func_2中使用,因此每个函数都使用一组唯一的参数。

7 个解决方案

#1


3  

You could use the function's name as the keyword arguments. When indexing kwargs, you'd use func_i.__name__ as the key.

您可以使用函数的名称作为关键字参数。索引kwargs时,你会使用func_i .__ name__作为键。

def foo(data, function_list, **kwargs):
    for func_i in function_list:
        print(func_i(data, kwargs[func_i.__name__]))

And now,

现在,

foo(data, [func_1, func_2], func_1='some_par', func_2=[5, 11])

#2


3  

You could use inspect.getargspec (I assume you use Python 2, you shouldn't use that function in Python 3 because it has been deprecated) to find out which argument names a function has and build a new dictionary based on those:

您可以使用inspect.getargspec(我假设您使用Python 2,您不应该在Python 3中使用该函数,因为它已被弃用)以找出函数具有哪些参数名称并基于以下内容构建新字典:

import inspect

def foo(data, functions_list, **kwargs):
    for func_i in functions_list:
        newkwargs = {name: kwargs[name] 
                     for name in inspect.getargspec(func_i).args 
                     if name in kwargs}
        print(func_i(data, **newkwargs))

def func_1(data, par_1):
    return data, par_1

def func_2(data, par_2_0, par_2_1):
    return data, par_2_0, par_2_1

>>> data = 10
>>> foo(data, [func_1, func_2], par_1='some_par', par_2_0=5, par_2_1=11)
(10, 'some_par')
(10, 5, 11)

But a better way would be to simply associate parameters with functions that doesn't rely on introspection.

但更好的方法是简单地将参数与不依赖于内省的函数相关联。

#3


2  

If you want to keep the foo function with that exact same declaration and you don't mind each function receiving the whole set of parameters you could do it like this:

如果你想保持foo函数与完全相同的声明,你不介意每个函数接收整个参数集,你可以这样做:

You just need to add to each 'my_*' function the **kwargs parameter.

您只需要在每个'my_ *'函数中添加** kwargs参数。

def foo(data, functions_list, **kwargs):
    for my_function in functions_list:
        print(my_function(data, **kwargs))


def my_sum(a, b, **kwargs):
    return a + b


def my_sub(a, c, **kwargs):
    return a - c


foo(0, [my_sum, my_sub], b=3, c=10)

Python automatically parses kwargs setting the b and c parameters where it has the value.

Python自动解析kwargs设置它具有值的b和c参数。

#4


1  

Another approach can be like this:

另一种方法可以是这样的:

def foo(data, function_list, **kwargs):
    function_dict = {
        "func_1": func_1,
        "func_2": func_2        
    }
    for func_i in function_list:
        print function_dict[func_i](data, **kwargs)

def func_1(data, **arg):
    filtered_argument = {key: value for key, value in arg.items() if key.startswith('par_1')}
    return list([data, filtered_argument])

def func_2(data, **arg):
    filtered_argument = {key: value for key, value in arg.items() if key.startswith('par_2_')}
    return list([data, filtered_argument])


data = [1,2,3]  
foo(data, ['func_1', 'func_2'], par_1='some_par', par_2_0=5, par_2_1=11)

Output:

输出:

[[1, 2, 3], {'par_1': 'some_par'}]
[[1, 2, 3], {'par_2_0': 5, 'par_2_1': 11}]

I am sure that you can improvise your current code as it gets ugly in this way.

我确信您可以即兴创作当前的代码,因为它会以这种方式变得丑陋。

#5


1  

I like @COLDSPEED's approach, but want to present yet another solution. Pass always 3 values: function, args, keyword args:

我喜欢@ COLDSPEED的方法,但想提出另一个解决方案。总是传递3个值:function,args,keyword args:

Usage:

用法:

foo(
    func_1, ('some_par',), {},
    func_2, (5, 11), {},
)

Implementation (Python3 syntax):

实现(Python3语法):

def foo(*args3):
    while args3:
        func, args, kwargs, *args3 = args3
        func(*args, **kwargs)

#6


1  

An approach would be making the 3rd argument of foo a positional argument and pass in a list of args with functions list:

一种方法是使foo的第三个参数成为位置参数,并传入一个带有函数列表的args列表:

def foo(data, functions_list, args):
    for func, arg in zip(functions_list, args):
        print(func(data, arg))


def func1(data, par_1):
    return 'func1 called with {}'.format(par_1)


def func2(data, par_2):
    return 'func2 called with {}'.format(par_2)

foo('some_data', [func1, func2],
    [
        {'par_1_1': 11, 'par_1_2': 12},
        {'par_2_1': 21, 'par_2_2': 22}
    ])

zip() is used to map each function with the corresponding args.

zip()用于将每个函数与相应的args映射。

Output:

输出:

func1 called with {'par_1_1': 11, 'par_1_2': 12}
func2 called with {'par_2_1': 21, 'par_2_2': 22}

#7


1  

You can do it something like that, "close" each parameters for function in a list item and then let "foo" split it backwards:

您可以这样做,“关闭”列表项中的函数的每个参数,然后让“foo”向后拆分:

def foo(data, functions_list, kwarg):
    for func_i, args in zip(functions_list, kwarg):
        func_i(data, **args)


def func_1(data, par_1):
    print("func_1 %s %s" % (data, par_1))


def func_2(data, par_2_0, par_2_1):
    print("func_2 %s "
          "%s %s" % (data, par_2_0, par_2_1))

data = "Some Data"

foo(data, [func_1, func_2], [{"par_1":'some_par'}, {"par_2_0":5, "par_2_1":11}])

#1


3  

You could use the function's name as the keyword arguments. When indexing kwargs, you'd use func_i.__name__ as the key.

您可以使用函数的名称作为关键字参数。索引kwargs时,你会使用func_i .__ name__作为键。

def foo(data, function_list, **kwargs):
    for func_i in function_list:
        print(func_i(data, kwargs[func_i.__name__]))

And now,

现在,

foo(data, [func_1, func_2], func_1='some_par', func_2=[5, 11])

#2


3  

You could use inspect.getargspec (I assume you use Python 2, you shouldn't use that function in Python 3 because it has been deprecated) to find out which argument names a function has and build a new dictionary based on those:

您可以使用inspect.getargspec(我假设您使用Python 2,您不应该在Python 3中使用该函数,因为它已被弃用)以找出函数具有哪些参数名称并基于以下内容构建新字典:

import inspect

def foo(data, functions_list, **kwargs):
    for func_i in functions_list:
        newkwargs = {name: kwargs[name] 
                     for name in inspect.getargspec(func_i).args 
                     if name in kwargs}
        print(func_i(data, **newkwargs))

def func_1(data, par_1):
    return data, par_1

def func_2(data, par_2_0, par_2_1):
    return data, par_2_0, par_2_1

>>> data = 10
>>> foo(data, [func_1, func_2], par_1='some_par', par_2_0=5, par_2_1=11)
(10, 'some_par')
(10, 5, 11)

But a better way would be to simply associate parameters with functions that doesn't rely on introspection.

但更好的方法是简单地将参数与不依赖于内省的函数相关联。

#3


2  

If you want to keep the foo function with that exact same declaration and you don't mind each function receiving the whole set of parameters you could do it like this:

如果你想保持foo函数与完全相同的声明,你不介意每个函数接收整个参数集,你可以这样做:

You just need to add to each 'my_*' function the **kwargs parameter.

您只需要在每个'my_ *'函数中添加** kwargs参数。

def foo(data, functions_list, **kwargs):
    for my_function in functions_list:
        print(my_function(data, **kwargs))


def my_sum(a, b, **kwargs):
    return a + b


def my_sub(a, c, **kwargs):
    return a - c


foo(0, [my_sum, my_sub], b=3, c=10)

Python automatically parses kwargs setting the b and c parameters where it has the value.

Python自动解析kwargs设置它具有值的b和c参数。

#4


1  

Another approach can be like this:

另一种方法可以是这样的:

def foo(data, function_list, **kwargs):
    function_dict = {
        "func_1": func_1,
        "func_2": func_2        
    }
    for func_i in function_list:
        print function_dict[func_i](data, **kwargs)

def func_1(data, **arg):
    filtered_argument = {key: value for key, value in arg.items() if key.startswith('par_1')}
    return list([data, filtered_argument])

def func_2(data, **arg):
    filtered_argument = {key: value for key, value in arg.items() if key.startswith('par_2_')}
    return list([data, filtered_argument])


data = [1,2,3]  
foo(data, ['func_1', 'func_2'], par_1='some_par', par_2_0=5, par_2_1=11)

Output:

输出:

[[1, 2, 3], {'par_1': 'some_par'}]
[[1, 2, 3], {'par_2_0': 5, 'par_2_1': 11}]

I am sure that you can improvise your current code as it gets ugly in this way.

我确信您可以即兴创作当前的代码,因为它会以这种方式变得丑陋。

#5


1  

I like @COLDSPEED's approach, but want to present yet another solution. Pass always 3 values: function, args, keyword args:

我喜欢@ COLDSPEED的方法,但想提出另一个解决方案。总是传递3个值:function,args,keyword args:

Usage:

用法:

foo(
    func_1, ('some_par',), {},
    func_2, (5, 11), {},
)

Implementation (Python3 syntax):

实现(Python3语法):

def foo(*args3):
    while args3:
        func, args, kwargs, *args3 = args3
        func(*args, **kwargs)

#6


1  

An approach would be making the 3rd argument of foo a positional argument and pass in a list of args with functions list:

一种方法是使foo的第三个参数成为位置参数,并传入一个带有函数列表的args列表:

def foo(data, functions_list, args):
    for func, arg in zip(functions_list, args):
        print(func(data, arg))


def func1(data, par_1):
    return 'func1 called with {}'.format(par_1)


def func2(data, par_2):
    return 'func2 called with {}'.format(par_2)

foo('some_data', [func1, func2],
    [
        {'par_1_1': 11, 'par_1_2': 12},
        {'par_2_1': 21, 'par_2_2': 22}
    ])

zip() is used to map each function with the corresponding args.

zip()用于将每个函数与相应的args映射。

Output:

输出:

func1 called with {'par_1_1': 11, 'par_1_2': 12}
func2 called with {'par_2_1': 21, 'par_2_2': 22}

#7


1  

You can do it something like that, "close" each parameters for function in a list item and then let "foo" split it backwards:

您可以这样做,“关闭”列表项中的函数的每个参数,然后让“foo”向后拆分:

def foo(data, functions_list, kwarg):
    for func_i, args in zip(functions_list, kwarg):
        func_i(data, **args)


def func_1(data, par_1):
    print("func_1 %s %s" % (data, par_1))


def func_2(data, par_2_0, par_2_1):
    print("func_2 %s "
          "%s %s" % (data, par_2_0, par_2_1))

data = "Some Data"

foo(data, [func_1, func_2], [{"par_1":'some_par'}, {"par_2_0":5, "par_2_1":11}])