用于条件参数传递的Pythonic解决方案

时间:2012-06-25 08:03:52

标签: python

我有一个带有两个可选参数的函数:

def func(a=0, b=10):
    return a+b

我的代码中的其他地方我正在做一些条件参数传递,如:

if a and b:
   return func(a, b)
elif a:
   return func(a)
elif b:
   return func(b=b)
else:
   return func()

无论如何都要简化这种模式中的代码吗?

修改

我们假设 不允许func内实现默认参数逻辑。

我可能有多个功能,例如funcfunc1func2func3都会包含

a = a or 0
b = b or 10

语句。

但是我正在调用这些系列函数来消除重复。 (使用装饰器)

9 个答案:

答案 0 :(得分:20)

如果你不想改变func中的任何内容,那么明智的选择就是将一个参数的dict传递给函数:

>>> def func(a=0,b=10):
...  return a+b
...
>>> args = {'a':15,'b':15}
>>> func(**args)
30
>>> args={'a':15}
>>> func(**args)
25
>>> args={'b':6}
>>> func(**args)
6
>>> args = {}
>>> func(**args)
10

或只是:

>>>func(**{'a':7})
17

答案 1 :(得分:1)

为什么不将该逻辑传递给函数?

def func(a, b):
    a = a or 0
    b = b or 10
    return a + b

答案 2 :(得分:1)

解决您的具体问题:

args = {'a' : a, 'b' : b}
for varName, varVal in args.items():
    if not varVal:
        del args[varName]
f(**args)

但最pythonic的方法是使用None作为函数的默认值:

f(a=None, b=None):
    a = 10 if a is None else a
    ...

然后致电f(a, b)

答案 3 :(得分:1)

通过现在删除的注释来查看检查对于变量None而不是假的问题,更改func以便它处理参数{{1 }}:

None

然后每次只调用def func(a=None, b=None): if a is None: a = 0 if b is None: b = 10

答案 4 :(得分:1)

默认情况下,Python中的所有方法都采用variable arguments

当您在方法的签名中定义参数时,您明确地要求它。在你的代码片段中,你正在做的是给它一个默认值 - 而不是让它们成为可选的。

请考虑以下事项:

>>> def func(a,b):
...    a = a if a else 0
...    b = b if b else 10
...    return a+b
...
>>> a = b = None
>>> func(a,b)
10
>>> a = 5
>>> b = 2
>>> func(a,b)
7
>>> func()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() takes exactly 2 arguments (0 given)

在此代码段中,ab都是必需,因为我没有定义任何默认值。它们不是可选

但是在你的代码片段中,因为你已经在方法签名中给出了默认值,它们看起来像它们是可选的,但实际上它们只是分配了默认值。

>>> def func(a=0,b=10):
...    return a+b
...
>>> func()
10

您可以通过检查方法正文中的参数列表来确认:

>>> def func(a=b,b=10):
...    print locals().keys()
...
>>> func()
['a', 'b']

让你的函数接受任何个参数的一种方法(换句话说,使它们都是可选的):

>>> def func(*args,**kwargs):
...    print len(args),args
...    print len(kwargs),kwargs
...
>>> func("hello","world",a=5,b=10)
2 ('hello', 'world')
2 {'a': 5, 'b': 10}
>>> func()
0 ()
0 {}
>>> func(1,2)
2 (1, 2)
0 {}
>>> func(a)
1 (5,)
0 {}
>>> func(foo="hello")
0 ()
1 {'foo': 'hello'}

答案 5 :(得分:1)

您可以添加一个可以消除None个参数的装饰器:

def skip_nones(fun):
    def _(*args, **kwargs):
        for a, v in zip(fun.__code__.co_varnames, args):
            if v is not None:
                kwargs[a] = v
        return fun(**kwargs)
    return _

@skip_nones
def func(a=10, b=20):
    print a, b

func(None, None) # 10 20
func(11, None)   # 11 20
func(None, 33)   # 10 33

答案 6 :(得分:0)

回答你的字面问题:

func(a or 0, b or 10) 

修改 请参阅评论为什么这不能回答这个问题。

答案 7 :(得分:0)

这可能有效:

def f(**kwargs):
    a = get(kwargs, 0)
    b = get(kwargs, 10)
    return a + b

答案 8 :(得分:0)

您可以使用三元if-then运算符将条件论证传递给函数 https://www.geeksforgeeks.org/ternary-operator-in-python/

例如,如果要在传递密钥之前检查密钥是否确实存在,可以执行以下操作:

 spreadsheet