The following code:
def f(a=1):
pass
kwargs = {}
kwargs['a'] = 1
kwargs['b'] = 2
f(**kwargs)
(correctly) raises an Exception:
Traceback (most recent call last):
File "tt.py", line 8, in <module>
f(**kwargs)
TypeError: f() got an unexpected keyword argument 'b'
Is there a way, with functools or other, to get around this and figure out which arguments didn't get used by t开发者_Go百科he function in order to be able to pass them to another function? For example, I might have another function:
def g(a=None, b=None):
pass
which I want to call after, with e.g.
g(**kwargs)
but I only want b
to be passed because a
was already 'used up' in the previous function.
Now I know that this is not ideal coding, but there are cases where it can come in handy, and it is actually easy to explain to the user, e.g. "Additional parameters will be passed to f, and any parameters not passed to f will be passed to g".
I am a bit astonished that you ask this question and fear that you are doing something you may regret.
Are you trying to call different methods with the same dictionary providing all arguments combined?
If so, then the complexity required to handle this case shouldn't be dealt with in the called methods but the calling code, e.g. by tailoring the kwargs
to the specific method to be called:
def f(a=1):
pass
call_tailored_args(f, kwargs)
The helper function would be implemented like this:
import inspect
def tailored_args(f, kwargs):
relevant_args = {k: v in kwargs if k in inspect.getargspec(f).args}
f(**relevant_args)
Is this what you mean?
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)
You can use a decorator to remove the extra kwargs keys:
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)
精彩评论