2012-06-16 15 views
16

powiedzmy mam funkcję:Rozpakowanie argumenty słów kluczowych, ale tylko te, spełniające funkcję

def foo(a = None, b=None, c=None): 
    return "a:%s, b:%s, c:%s" % (a,b,c) 

Mam słownik z niektórych (lub brak) z argumentów powyżej, ale również z kluczami, które są nie nazwane argumenty funkcji, np

d = {'a':1, 'x':4, 'b':2, 'y':5} 

Jeśli zgłoszę następujących będę się błąd, ponieważ „x” i „y” nie są argumenty kluczowych w funkcji foo.

foo(**d) # error 

Czy istnieje elegancki sposób przekazywania argumentów ze słownika do funkcji, ale tylko te wartości z kluczami, które pasują do argumentów funkcji.

Proszę poprawić mnie, jeśli moja argumentacja/parametrologia jest wyłączona.

Odpowiedz

7

@Ashwini Chaudhary ma bardzo pytonowy sposób na rozwiązanie problemu. Wymaga to jednak zmiany sygnatury funkcji foo.

Jeśli nie chcesz, aby zmienić swój podpis funkcji, można użyć introspection aby dowiedzieć się, jakie argumenty czynność oczekuje:

arg_count = foo.func_code.co_argcount 
args = foo.func_code.co_varnames[:arg_count] 

args_dict = {} 
for k, v in d.iteritems(): 
    if k in args: 
     args_dict[k] = v 

foo(**args_dict) 
28
def foo(a = None, b=None, c=None,**extras): 
    return "a:%s, b:%s, c:%s" % (a, b, c) 

tutaj **extras zbierze wszystkie dodatkowe argumenty o nazwie/słowa kluczowego.

6

ciekawe pytanie. Myślę, że większość ludzi w prawdziwym życiu używa podejścia @Ashwini Chaudhary.

Zgadzam się z @Rodrigue, że czasami nie można zmodyfikować sygnatury połączenia funkcji (prawdopodobnie moduł innej osoby).

Kiedy tak się dzieje, Użyj dekorator funkcja

from inspect import getargspec 
from funtools import wraps 

def allow_kwargs(foo): 
    argspec = getargspec(foo) 
    # if the original allows kwargs then do nothing 
    if argspec.keywords: 
     return foo 
    @wraps(foo) 
    def newfoo(*args, **kwargs): 
     #print "newfoo called with args=%r kwargs=%r"%(args,kwargs) 
     some_args = dict((k,kwargs[k]) for k in argspec.args if k in kwargs) 
     return foo(*args, **some_args) 
    return newfoo 


# with your function: 
@allow_kwargs 
def foo(a = None, b=None, c=None): 
    return "a:%s, b:%s, c:%s " % (a,b,c) 

# with someone_elses function: 
from some_place import foo 
foo = allow_kwargs(foo) 

@wraps z functools utrzymuje __name__ i __doc__ strun w takcie. Można również:

  • spojrzeć na FunctionMaker z modułu dekoratorów, ale powinno to być bardziej wielokrotnego użytku podejście.
  • zmodyfikuj newfoo, aby nie przepuszczać dodatkowych zmiennych niebędących słowami kluczowymi.
Powiązane problemy