我正在重构一段代码,我遇到了以下问题。我有一个巨大的参数列表,现在我希望将其作为kwargs
传递。代码是这样的:
def f(a, b, c, ...):
print a
...
f(a, b, c, ...)
我正在重构它:
data = dict(a='aaa', b='bbb', c='ccc', ...)
f(**data)
这意味着我必须这样做:
def f(**kwargs):
print kwargs['a']
...
但这是皮塔饼。我想保留:
def f(**kwargs):
# Do some magic here to make the kwargs directly accessible
print a
...
有没有直接的方法可以直接访问kwargs
dict
中的参数,也许是通过使用一些帮助类/库?
答案 0 :(得分:7)
有some ways - 但你也可以像这样包装你的函数:
def f(**kwargs):
arg_order = ['a', 'b', 'c', ...]
args = [kwargs.get(arg, None) for arg in arg_order]
def _f(a, b, c, ...):
# The main code of your function
return _f(*args)
样品:
def f(**kwargs):
arg_order = ['a', 'b', 'c']
args = [kwargs.get(arg, None) for arg in arg_order]
def _f(a, b, c):
print a, b, c
return _f(*args)
data = dict(a='aaa', b='bbb', c='ccc')
f(**data)
输出:
>>>
aaa bbb ccc
答案 1 :(得分:3)
好吧,您可以手动更新locals
,但文档会特别警告它。
for key, value in kwargs.iteritems(): #Python 2.7 here
locals()[key] = value
另一种选择是使用exec
,虽然通常不赞成,但至少可以保证正常工作。
for key, value in kwargs.iteritems(): #Python 2.7 here
exec('{} = value'.format(key)
虽然我不会向任何人承认你实际上做过其中任何一项。
答案 2 :(得分:1)
功能内部:
for k, v in kwargs.iteritems():
locals()[k] = v
答案 3 :(得分:1)
我必须在类似情况下重构我的代码,并且我不同意使用kwargs['a']
,这感觉有点尴尬。有时我使用bunch
对象而不是字典,这允许您通过属性访问(params.a
)而不是字典查找来访问字段。每次使用参数时,它只为您节省3个字符,但我发现它更好看,因为您不需要参数名称周围的引号。有各种各样的食谱来实现一个,参见例如these ones。
所以不要像你的情况那样使用dict,而是像
一样使用它In [1]: class Bunch:
...: def __init__(self, **kwds):
...: self.__dict__.update(kwds)
In [2]: params = Bunch(a = 'aaa', b = 'bbb')
In [3]: def f(p):
...: print p.a
...:
In [4]: f(params)
aaa
我知道这不是你问题的直接答案,但它只是使用kwargs的另一种选择。
答案 4 :(得分:1)
另一种可能的方法(基于您的评论here)是使用属性字典:
class AttributeDict(dict):
def __getattr__(self, attr):
return self[attr] if attr in self.keys() else None
def __setattr__(self, attr, value):
self[attr] = value
要像这样使用:
def f(**kwargs):
kwargs = AttributeDict(kwargs)
样品:
def f(**kwargs):
kwargs = AttributeDict(kwargs)
print kwargs.a, kwargs.b, kwargs.c
data = dict(a='aaa', b='bbb', c='ccc')
f(**data)
输出:
>>>
aaa bbb ccc
注意:如果您想要更短的变量名称,则可以随时为其命名x
,然后访问权限只有x.a
答案 5 :(得分:0)
在我看来,你正在做冗员和最简单的解决方案。那些a, b, c
是关键字参数和位置,因此您可以按照自己喜欢的方式调用函数:
>>> def f(a, b, c=3):
... print a, b, c
使用所有关键字参数
>>> f(**{'a':1, 'b':2})
1 2 3
混合使用位置和关键字args
>>> f(5, **{'b':4})
5 4 3
如果错误的关键字args
,则会收到正确的错误>>> f(**{'d':4, 'a':1, 'b':2})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() got an unexpected keyword argument 'd'