2011-08-27 9 views
6

następujący kod:Pass kwargs z nieprawidłowymi pary klucz = wartość funkcjonować

def f(a=1): 
    pass 

kwargs = {} 
kwargs['a'] = 1 
kwargs['b'] = 2 

f(**kwargs) 

(poprawnie) podnosi wyjątek:

Traceback (most recent call last): 
    File "tt.py", line 8, in <module> 
    f(**kwargs) 
TypeError: f() got an unexpected keyword argument 'b' 

czy istnieje sposób, z functools lub inne, aby uzyskać wokół tego i dowiedzieć się, które argumenty nie zostały wykorzystane przez funkcję, aby móc przekazać je do innej funkcji? Na przykład mogę mieć inną funkcję:

def g(a=None, b=None): 
    pass 

, z którą chcę zadzwonić później, np.

g(**kwargs) 

ale chcę tylko b być przekazywane ponieważ a zostało już „zużyte” w poprzedniej funkcji.

Teraz wiem, że nie jest to idealne kodowanie, ale są przypadki, w których może się przydać, a użytkownik jest łatwy do wytłumaczenia użytkownikowi, np. "Dodatkowe parametry zostaną przekazane do f, a wszelkie parametry nieprzekazane do f zostaną przekazane do g".

Odpowiedz

4

Czy to masz na myśli?

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

Jestem trochę zaskoczony, że zadajesz to pytanie i boisz się, że robisz coś, czego możesz żałować.

Czy próbujesz wywołać różne metody za pomocą tego samego słownika, pod warunkiem, że wszystkie argumenty są połączone? Jeśli tak, to złożoność wymaganą do obsługi tego przypadku nie powinna być rozpatrywana w wywołanych metodach, ale kod wywołujący, np. dostosowując się kwargs do konkretnego sposobu na miano:

def f(a=1): 
    pass 

call_tailored_args(f, kwargs) 

Funkcja pomocnika będą realizowane tak:

import inspect 

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

Można użyć dekorator aby usunąć dodatkowe kwargs klawiszy:

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) 
Powiązane problemy