2012-06-16 4 views
16

Lassen Sie uns übereinstimmen sagen habe ich eine Funktion:Auspacken Schlüsselwort Argumente, sondern nur diejenigen, die die Funktion

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

Ich habe ein Wörterbuch mit einigen (oder keine) der Argumente oben, sondern auch mit den Tasten, die keine Argumente in der Funktion mit dem Namen, zB:

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

Wenn ich folgenden nennen werde ich eine Fehlermeldung erhalten, weil ‚x‘ und ‚y‘ nicht Schlüsselwort Argumente in der foo Funktion sind.

foo(**d) # error 

Gibt es eine elegante Art und Weise die Argumente aus einem Wörterbuch auf eine Funktion vorbei, aber nur die Werte mit den Tasten, die die Funktionsargumente entsprechen.

Bitte korrigieren Sie mich, wenn meine Argument-/Parameterterminologie deaktiviert ist.

Antwort

7

@Ashwini Chaudhary hat eine sehr pythische Art, Ihr Problem zu lösen. Sie müssen jedoch die Signatur Ihrer foo-Funktion ändern.

Wenn Sie wollen nicht Ihre Funktion Signatur ändern, können Sie introspection verwenden, um herauszufinden, welche Argumente Ihre Funktion erwartet:

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) 

Hier sammelt die **extras alle zusätzlichen benannten/Schlüsselwortargumente.

6

Interessante Frage. Ich denke, dass die meisten Menschen im realen Leben @ Ashwini Chaudhary Ansatz verwenden.

Ich stimme @Rodrigue, dass es Zeiten gibt, die Sie nicht ändern können die Anrufsignatur der Funktion (jemand anderes Modul vielleicht).

Wenn das geschieht, eine Funktion decorator

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 von functools Mit __name__ und __doc__ Strings in Takt bleibt. Sie könnten auch:

  • Blick auf FunctionMaker aus dem Dekoratoren-Modul, aber das sollte eine wiederverwendbare Ansatz sein.
  • modifizieren Sie newfoo, um zu erlauben, dass zusätzliche nicht-Schlüsselwort-Variablen nicht durchgelassen werden.
Verwandte Themen