假设我有一个带有一些可选参数的方法。
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 中,我会选择一个工厂,但在这种情况下,这似乎是默认值应该避免的。
假设我有一个带有一些可选参数的方法。
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 中,我会选择一个工厂,但在这种情况下,这似乎是默认值应该避免的。
我会改变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
and ,''
而且0
, False
,[]
等。我个人会收紧界面并使用None
and 仅None
作为默认值。
def foo(a, b=None, c=None, d=None):
if b is None: b = 1
if c is None: c = 2
if d is None: d = 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, ''}
为例如,其含义略有不同(正如其他人所指出的那样)。
如果您只想捕获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
如果您想捕获所有值 v ,例如,bool(v)
那么False
:
def foo(a, b, c, d):
b = b or 1
c = c or 2
d = d or 3
或者您可以使用另一个为您执行断言的函数来装饰该函数(根据您的用例,这可能会也可能不会过分杀伤力)
您可以调用一个函数来过滤掉您不想传递的变量
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=''))
未经过全面测试,但应作为基础:
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!