我有以下方法:
def a(b='default_b', c='default_c', d='default_d'):
# …
pass
我有一些命令行界面,可以提供变量user_b
、user_c
、user_d
,也可以将它们设置为None
,即简单的Python argparse
模块。
我想打一个类似的电话:
a(b=user_b if user_b is not None,
c=user_c if user_c is not None,
d=user_d if user_d is not None)
如果变量是None
,我希望使用方法参数中的默认值。
我找到的唯一方法是检查用户变量的所有组合:
if not user_b and not user_c and not user_d:
a()
elif not user_b and not user_c and user_d:
a(d)
…
elif user_b and user_c and user_d:
a(b, c, d)
什么是更有效、更奇特、更Python的方法来解决我的问题?
arg_dict = {}
if user_b is not None:
arg_dict["b"] = user_b
if user_c is not None:
arg_dict["c"] = user_c
if user_d is not None:
arg_dict["d"] = user_d
a(**arg_dict)
不过不太好看。
一个更好的方法是重新编写函数a
,接受None
作为默认答案,然后进行检查。(即if b is None: b = "default_b"
(
下面是tdelaney答案的一个细微变化(对它的+1表示启动(,它通过用另一个函数装饰a
来工作,该函数删除传递给装饰对象的所有值为None
的关键字参数。
from functools import wraps
# You can reuse this decorator for all functions that might be
# invoked in your CLI that should handle their arguments like
# 'a' does.
def scrub_parameters(f):
@wraps(f)
def wrapper(**kwargs):
kwargs = {k: v for k, v in kwargs.items() if v is not None}
return f(**kwargs)
return wrapper
@scrub_parameters
def a(b='default_b', c='default_c', d='default_d'):
print('b={}, c={}, d={}'.format(b, c, d))
if __name__ == '__main__':
arg_dict = {'b': 'user_b', 'c': 'user_c', 'd': None}
a(**arg_dict) # b=user_b, c=user_c, d=default_d
arg_dict = {'b': None, 'c': 'user_c', 'd': None}
a(**arg_dict) # b=default_b, c=user_c, d=default_d
您可以编写一个函数来过滤掉不需要的值,然后使用它来清除目标函数调用。
def scrub_params(**kw):
return {k:v for k,v in kw.items() if v is not None}
some_function(**scrub_params(foo=args.foo, bar=args.bar))
您可以用数据定义一个类,并将对象作为参数传递。
class Args:
def __init__(self, user_b, user_c, user_d):
self.b = user_b
self.c = user_c
self.d = user_d