我想做以下事情:
def func(name, par1=None, par2=None, par3=None, ...):
pars = { 'name': name }
if par1: pars['par1'] = par1
if par2: pars['par2'] = par2
if par3: pars['par3'] = par3
...
do_something(pars)
这太冗长了。我当然可以这样做:
def func(name, **kwargs):
pars = { 'name': name }
pars.update(**kwargs)
do_something(pars)
但这太模糊了:我不知道允许哪些参数。唯一的方法是在docstring中记录它们,但即使这样也不会阻止传递不受支持的参数。防止这种情况会使我的功能同样冗长。
我是否遗漏了一种明显的方法,明确地和明确地执行此操作?
答案 0 :(得分:2)
使用inspect
可以为您提供非常简洁的内容:
#!/usr/bin/env python2.7
import inspect
def args_dict():
outer_frame = inspect.currentframe().f_back
info = inspect.getargvalues(outer_frame)
return {
k: info.locals[k] for k in info.args
if info.locals[k] is not None # or modify for other falsey values
}
def func(foo=None, bar=None, baz=None, qux='42'):
args = args_dict()
args['other'] = 'hello world'
return args
print func(bar="BAR")
# prints: {'qux': '42', 'other': 'hello world', 'bar': 'BAR'}
如果您想要考虑变量和关键字参数,则需要修改此项,但是从getargvalues()
获得的ArgInfo
元组具有其他信息。
答案 1 :(得分:0)
如何填写dict,然后使用dict理解过滤掉无效值:
def func(name, par1=None, par2=None, par3=None,
par4=None, par5=None, par6=None,
...):
pars = {'par1': par1, 'par2': par2, 'par3': par3,
'par4': par4, 'par5': par5, 'par6': par6,
...}
pars = {key, value for key, value in pars.items() if value}
pars['name'] = name
do_something(pars)
你也可以从dict中删除无效元素:
def func(name, par1=None, par2=None, par3=None,
par4=None, par5=None, par6=None,
...):
pars = {'par1': par1, 'par2': par2, 'par3': par3,
'par4': par4, 'par5': par5, 'par6': par6,
...}
for key, value in pars.items():
if not value:
del pars[key]
pars['name'] = name
do_something(pars)
可以从一开始就放入name
,但这会导致更详细的测试:
def func(name, par1=None, par2=None, par3=None,
par4=None, par5=None, par6=None,
...):
pars = {'name': name, 'par1': par1, 'par2': par2,
'par3': par3, 'par4': par4, 'par5': par5,
'par6': par6, ...}
pars = {key, value for key, value in pars.items() if value or key == 'name'}
do_something(pars)
或:
def func(name, par1=None, par2=None, par3=None,
par4=None, par5=None, par6=None,
...):
pars = {'name': name, 'par1': par1, 'par2': par2,
'par3': par3, 'par4': par4, 'par5': par5,
'par6': par6, ...}
for key, value in pars.items():
if not value and key != 'name':
del pars[key]
do_something(pars)
答案 2 :(得分:0)
我失去了优雅和快速的方式,但基于装饰的方法至少可以隐藏血腥的细节:
from functools import wraps
def allowed_kwargs(*args):
allowed = frozenset(args)
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for kwarg in kwargs:
if kwarg not in allowed:
raise TypeError("{} got an unexpected keyword argument '{}'".format(func.func_name, kwarg))
return func(*args, **kwargs)
return wrapper
return decorator
用作
@allowed_kwargs('foo')
def test(**kwargs):
print kwargs
test(bar=1)
这会引发TypeError
,因为带有显式关键字参数的unwrapped函数会。{/ p>
您也可以这样做:
def collect_kwargs(func):
@wraps(func)
def wrapper(*args, **kwargs):
forward_args = kwargs.copy()
forward_args['kwargs_dict'] = kwargs
return func(*args, **forward_args)
return wrapper
@collect_kwargs
def func(par1=None, par2=None, ..., kwargs_dict=None):
do_something(**kwargs_dict)
但我建议不要这样做。看起来更加模糊的是,首先没有明确的参数名称,它仍然使你的功能签名变得混乱。或者在我个人的命名法中,这是绝对邪恶的; - )。