Python函数指针具有不同的参数大小

时间:2014-03-03 22:03:56

标签: python arguments function-pointers

我的问题是如何与this question相关,我有一个函数字典,其中有不同数量的参数,我怎么能以自动方式调用它们?

funcdict = {
  'mypackage.mymodule1.myfunction1': mypackage.mymodule.myfunction,
  'mypackage.mymodule2.myfunction2': mypackage.mymodul2.myfunctio2,
    ....
}

funcdict[0](parameter1, parameter2)
funcdict[1](parameter1, parameter2, parameter3)
funcdict[1](parameter1, parameter2, parameter3,parameter4,parameter5)
.........

而不是像上面那样调用他们中的每一个想要像这样的东西

for i in range(len(funcdict)):
     funcdict[i](......)

不知道我应该如何填充参数,因为每个函数的参数数量在2到6之间变化。

3 个答案:

答案 0 :(得分:2)

如果您想以自动方式调用所有功能,特别是一次性调用所有功能,那么您可以通过某些特定名称(例如您引用的问题中)调用它们并不重要。您可以将这些功能保留在列表中并依次调用每个功能。

至于处理可变数量的参数,Python有一个你在一些方法声明中看到的“splat”运算符:def __init__(self, *args, **kwargs)。此运算符可用于解压缩参数列表。 (有关详细信息,请参阅this SO answer

如果将参数存储在另一个列表中,您可以遍历您的函数列表,并使用相同的语法逐个将参数应用于其相应的函数,而不指定参数的数量:

funclist = [lambda x,y: x+y, lambda x,y,z: x+y+z, lambda x: -x]
paramlist = [(1,2), (1,2,3), (1,)]

for index, func in enumerate(funclist):
    print func(*paramlist[index])

如何将函数链接到默认参数是另一回事:您可以将它们保存在两个列表中,或者将它们作为另一个列表或字典中的元组保存在一起,或者定义一个轻量级类来保存它们......这取决于您的问题。无论如何,听起来对你来说重要的部分是*符号。

修改

如果要将关键字参数传递给函数,可以使用double- *表示法传递字典并将其扩展为所需的关键字参数:

def func1(n_samples, noise, factor, random_state):
    print locals()

def func2(n_samples, ratio, noise):
    print locals()

def func3(my_key, default_key='world!'):
    print locals()

funclist = [func1, func2, func3]
paramlist = [
        dict(
            n_samples=1000,
            noise=0.3,
            factor=0.5,
            random_state=1
        ),
        dict(
            n_samples=1000,
            ratio=0.5,
            noise=0.1
        ),
        dict(
            my_key='hello',
        )
]

for index, func in enumerate(funclist):
    func(**paramlist[index])

答案 1 :(得分:1)

好的,我们假设您将参数放在元组中。您还需要优化表,以便了解每个函数需要多少个参数,这意味着修改数据结构(您可以使用inspect模块来确定这一点,但这是目前不必要的复杂因素:

如果函数必须被调用任何特定的顺序,顺便说一下,dict不是一个好的结构,因为它以不可预测的顺序线性化,但我们现在忽略了。这是一段代码,使用*表示法将元组作为单独的参数传递。我正在使用记者功能来证明你有参数传输工作。

parameters = ("one", "two", "three", "four", "five")

def reporter(*args):
    print("Called with", len(args), "arguments")
    print("args are:", args)

funcdict = {
  'mypackage.mymodule1.myfunction1': (reporter, 1),
  'mypackage.mymodule2.myfunction2': (reporter, 5),
}

for name, (function, arg_ct) in funcdict.items():
    print("Testing", name)
    function(*parameters[:arg_ct])

输出结果为:

Testing mypackage.mymodule1.myfunction1
Called with 1 arguments
args are: ('one',)
Testing mypackage.mymodule2.myfunction2
Called with 5 arguments
args are: ('one', 'two', 'three', 'four', 'five')

我希望能为你提供足够的东西。

答案 2 :(得分:0)

作为第一种可能性,可以通过获取func_code属性然后查询此代码对象的co_argcount来尝试使用函数的代码对象。

这是一个小例子,它通过名称调用存储在字典中的函数,对于一组输入参数,在这种情况下为2, 3, 4

#!/usr/bin/env python

def f1(a, b):
    print "executing f1 with %d, %d" % (a, b)
    return a*b

def f2(a, b, c):
    print "executing f2 with %d, %d, %d" % (a, b, c)
    return a*b+c

def call_functions(arg1, arg2, arg3):
    funcdict = {
        "add" : f1,
        "madd" : f2
        }
    for f in funcdict.itervalues():
        if f.func_code.co_argcount == 2:
            f(arg1, arg2)
        elif f.func_code.co_argcount == 3:
            f(arg1, arg2, arg3)
        # and so on

if __name__=="__main__":
    call_functions(2, 3, 4)

另一种稍微冗长的可能性(你不需要明确地检查每个函数的参数数量,函数只是使用他们需要的函数)就是使用Python的变量参数语法。这看起来如下:

#!/usr/bin/env python

def f1(*args):
    print "executing f1 with %d, %d" % (args[0], args[1])
    return args[0]*args[1]

def f2(*args):
    print "executing f2 with %d, %d, %d" % (args[0], args[1], args[2])
    return args[0]*args[1]+args[2]

def call_functions(*args):
    funcdict = {
        "add" : f1,
        "madd" : f2
        }
    for f in funcdict.itervalues():
        f(*args)

if __name__=="__main__":
    call_functions(2, 3, 4)