使用可选参数调用方法的最pythonic方法是什么?

时间:2013-08-26 21:42:03

标签: python python-2.7 optional-parameters

假设我有一个带有一些可选参数的方法。

def foo(a, b=1, c=2, d=3)

如何调用它以便如果我的变量为None或空字符串,则使用默认值?

以下条件似乎是一个可怕的解决方案:

if b and not c and d:
    foo(myA, b = myB, d = myD)
elif b and not c and not d:
    ...

在Java中我会跳转到一个工厂,但看起来这就是默认情况下应该避免的情况。

5 个答案:

答案 0 :(得分:7)

我会更改foo,因此它会将默认值替换为空值。

def foo(a, b=None, c=None, d=None):
    if not b: b = 1
    if not c: c = 2
    if not d: d = 3

请注意,这会将所有“false-y”值视为默认值,这不仅意味着None'',还意味着0False,{{1}个人我会收紧界面并使用[]并仅使用None作为默认值。

None

答案 1 :(得分:3)

虽然我同意更改方法是一个更好的主意,但是这里有一个替代方法,通过使用dict参数来更改调用部分,这些参数被过滤然后解压缩:

d = {'b': myB, 'd': myD}
foo(myA, **{k: d[k] for k in d if d[k]})

当然,if d[k]可以替换为if d[k] not in {None, ''},其含义略有不同(正如其他人所指出的那样)。

答案 2 :(得分:2)

如果您只想抓住None''

def foo(a, b, c, d):
    blacklist = set([None, ''])
    if b in blacklist:
        b = 1
    if c in blacklist:
        c = 2
    if d in blacklist:
        d = 3

如果您希望捕获bool(v)False的所有值v,则:

def foo(a, b, c, d):
    b = b or 1
    c = c or 2
    d = d or 3

或者您可以使用另一个为您执行断言的函数来装饰该函数(根据您的使用情况,可能会或可能不会过度杀伤)

答案 3 :(得分:2)

您可以调用一个过滤掉您不想传递的变量的函数

def arg_filter(**kw):
    return dict((k,v) for k,v in kw.items() if v not in (None, ''))

foo(**arg_filter(a=1,b=None,c=''))

答案 4 :(得分:1)

未完全测试,但应作为基础:

import inspect
from functools import wraps

def force_default(f):
    @wraps(f)
    def func(*args, **kwargs):
        ca = inspect.getcallargs(f, *args, **kwargs)
        da = inspect.getargspec(f)
        dv = dict(zip(reversed(da.args), reversed(da.defaults)))
        for k, v in ca.iteritems():
            if v is None or v == '':
                ca[k] = dv[k]
        return f(**ca)
    return func

@force_default
def foo(a, b=1, c=2, d=3):
    print a, b, c, d

foo(6, '', None, 'rabbit!')
# 6 1 2 rabbit!