Unpacking keyword arguments, but only the ones that match the function

前端 未结 3 723
执念已碎
执念已碎 2020-12-17 09:07

Let\'s say I have a function:

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

I have a dictionary with some (or

相关标签:
3条回答
  • 2020-12-17 09:49

    @Ashwini Chaudhary has a very pythonic way of solving your problem. However, it requires changing the signature of your foo function.

    If you don't want to change your function signature, you can use introspection to find out what arguments your function expects:

    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)
    
    0 讨论(0)
  • 2020-12-17 09:50
    def foo(a = None, b=None, c=None,**extras):
        return "a:%s, b:%s, c:%s" % (a, b, c)
    

    here the **extras will collect all the extra named/keyword arguments.

    0 讨论(0)
  • 2020-12-17 10:01

    Interesting question. I think that most people in real life use @Ashwini Chaudhary approach.

    I do agree with @Rodrigue that there are times you can't modify the call signature of the function (someone else's module perhaps).

    When that happens, Use a function 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 from functools keeps the __name__ and __doc__ strings in tact. You could also:

    • look at FunctionMaker from the decorators module but this should be a more reusable approach.
    • modify newfoo to allow extra non keyword vars to be not passed through.
    0 讨论(0)
提交回复
热议问题