将无效的key=value对作为kwargs传递给函数
以下代码:
def f(a=1):
pass
kwargs = {}
kwargs['a'] = 1
kwargs['b'] = 2
f(**kwargs)
(正确地)引发了一个异常:
Traceback (most recent call last):
File "tt.py", line 8, in <module>
f(**kwargs)
TypeError: f() got an unexpected keyword argument 'b'
有没有办法,比如用functools或者其他方法,来绕过这个问题,找出哪些参数没有被函数使用,以便可以把它们传递给另一个函数?比如,我可能还有另一个函数:
def g(a=None, b=None):
pass
我想在之后调用它,比如:
g(**kwargs)
但我只想传递 b
,因为 a
在之前的函数中已经被“用掉”了。
我知道这样写代码并不是最理想的,但有些情况下这样做会很方便,而且其实也很容易向用户解释,比如“额外的参数会传递给f,而没有传递给f的参数会传递给g”。
3 个回答
1
你可以使用一个装饰器来去掉多余的关键字参数(kwargs)键:
def remove_args(fx):
def wrap(**kwargs):
kwargs2 = copy.copy(kwargs)
ret = None
done = False
while not done:
try:
ret = fx(**kwargs2)
done = True
except TypeError, ex:
key = re.findall("\'(\w+)\'", ex.message)[0]
del kwargs2[key] # Remove offending key
# print "%s removing %s" % (fx.__name__, key)
return ret
return wrap
@remove_args
def f1(a=1):
return "f1-ret"
@remove_args
def f2(b=1):
return "f2-ret"
kwargs = {"a": 1, "b": 2, "c": 3}
print f1(**kwargs)
print f2(**kwargs)
4
这是不是你想表达的意思?
def g(**kwargs):
a=kwargs.pop('a',None)
b=kwargs.pop('b',None)
print(a,b)
def f(**kwargs):
a=kwargs.pop('a',None)
print(a)
g(**kwargs)
kwargs = {'a':1,'b':2}
f(**kwargs)
# 1
# (None, 2)
5
我有点惊讶你会问这个问题,担心你可能会做出让自己后悔的事情。
你是不是想用同一个字典来调用不同的方法,并且这个字典里包含了所有的参数?如果是这样的话,处理这种情况的复杂性应该在调用的代码中解决,而不是在被调用的方法里。比如说,可以根据要调用的方法来调整 kwargs
。
def f(a=1):
pass
call_tailored_args(f, kwargs)
这个辅助函数可以这样实现:
import inspect
def tailored_args(f, kwargs):
relevant_args = {k: v in kwargs if k in inspect.getargspec(f).args}
f(**relevant_args)