2011-08-27 69 views
6

下面的代码:通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”。

回答

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具体方法被调用:

import inspect 

def tailored_args(f, kwargs): 
    relevant_args = {k: v in kwargs if k in inspect.getargspec(f).args} 
    f(**relevant_args) 
1

您可以使用一个装饰删除多余的kwargs键:

def f(a=1): 
    pass 

call_tailored_args(f, 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)