2011-08-27 79 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)