Pythonic方式传递许多参数

时间:2014-02-03 12:35:56

标签: python arguments

我正在处理一个包含子包和每个子包中的几个模块的包。 大多数函数需要在" main"中启动的几个参数(~10)。功能。通常,所有参数都传递给从函数内调用的方法。传递这些参数的最佳方法是什么?

考虑以下情况:

def func(arg1, arg2, ...., argn):
  do something  
  ext_method(arg1, arg3,...argk) # Note: all the arguments are not passed to ext_method
  cleanup  

PS:函数嵌套可以很深(比如从主函数开始大约10-12个函数)。 我考虑了两种选择:

  1. Inspect方法:使用所有参数构造main函数中所有参数的dict。调用函数:使用inspect包中的方法获取其argspec,并从" global"中过滤出不必要的参数。争论。它看起来像下面的代码片段。

    args = {arg1: obj1, arg2:obj2,...}  
    req_args = dict([(k, v) for k, v in args.items() if k in inspect.getargspec(ext_method).args])
    
  2. 键值方法:使用参数键值对

    调用ext_method()
    ext_method(arg1=val1, arg3=val3,...,argk=valk)
    
  3. 我发现第二种方法无效,因为随着更多功能被添加到包中,ext_method()的签名变得不容易。方法1是更好的选择吗?

2 个答案:

答案 0 :(得分:14)

更多,更好的选择:

  1. **kwargs添加到您的函数中,忽略额外参数:

    ex_method(arg1, arg2, **kw)
    
  2. 将所有参数作为属性传递给对象;一个namedtuple class在这里是理想的。每个函数只使用它需要的那些属性。

  3. 我会选择后者。停止移动10个参数,开始绕过一个

    更好的是,如果所有这些操作都与这些参数所代表的数据真正耦合,那么您可能应该使用类来代替:

    class SomeConcept(object):
        def __init__(self, arg1, arg2, arg3, .., argN):
            self.arg1 = arg1
            # ... etc.
    
        def operation1(self, external_argument):
            # use `self` attributes, return something.
    

    而不是所有这些单独的功能。

答案 1 :(得分:5)

要传递多个参数,请使用*运算符和**运算符。

def foo(*arg, **karg):
    print arg, karg

*运算符包中包含所有有序参数,**运算符包含其中所有不匹配的键参数。

例如:

def foo(a, *arg):
    return a, arg

foo(1,2,3)
>> (1, [2, 3])
foo(1)
>> (1, [])

对于关键参数,它的工作方式相同,

def foo(a=1, b=2, **kargs):
    return a, b, kargs

foo(2, c=10, b=23)
>> (2, 23, {'c': 10})

然后你可以将它们混合起来,那些特殊情况总是在签名的末尾如下:

def foo(a, c, d=4, *arg, **karg):
    return a, c, d, arg, karg

foo(1, 2)
>> (1, 2, 4, [], {})

foo(1,2,3)
>> (1, 2, 3, [], {})

foo(1, 2, 3, 4, 5)
>> (1, 2, 3, [4, 5], {})

foo(1, 2, h=2, f=3, d=4, j=3)
>> (1, 2, 4, [], {'h': 2, 'f': 3, 'j': 3})

foo(1,2,3,4,5, o=2)
>> (1, 2, 3, [4 ,5], {'o': 2})

如果要将dict作为参数或参数列表传递给函数,也可以使用这些运算符:

a = [1,2,3]
b = {'c': 1, 'd': 3}

def foo(a, b, *arg, **karg):
    return a, b, arg, karg

foo(*a, **b)
>> (1, 2, [3], {'c': 1, 'd': 3})