Make kwargs available

I am refactoring parts of the code, and I ran into the following problem. I have a huge list of parameters, which I now want to convey as kwargs. The code looks like this:

def f(a, b, c, ...):
  print a
  ...

f(a, b, c, ...)

I will reorganize it:

data = dict(a='aaa', b='bbb', c='ccc', ...)
f(**data)

What should I do:

def f(**kwargs):
  print kwargs['a']
  ...

But this is pita bread. I would like to save:

def f(**kwargs):
  # Do some magic here to make the kwargs directly accessible
  print a
  ...

Is there an easy way to make arguments kwargs dictavailable directly, possibly using some helper class / library?

+4
source share
6 answers

There are several ways - but you can also wrap your function as follows:

def f(**kwargs):
    arg_order = ['a', 'b', 'c', ...]
    args = [kwargs.get(arg, None) for arg in arg_order]

    def _f(a, b, c, ...):
        # The main code of your function

    return _f(*args)

Example:

def f(**kwargs):
    arg_order = ['a', 'b', 'c']
    args = [kwargs.get(arg, None) for arg in arg_order]

    def _f(a, b, c):
        print a, b, c

    return _f(*args)

data = dict(a='aaa', b='bbb', c='ccc')
f(**data)

Output:

>>> 
aaa bbb ccc
+7
source

, locals , .

for key, value in kwargs.iteritems(): #Python 2.7 here
    locals()[key] = value

exec, , , .

for key, value in kwargs.iteritems(): #Python 2.7 here
    exec('{} = value'.format(key)

, .

+3

:

for k, v in kwargs.iteritems():
    locals()[k] = v
+1

, kwargs['a'], . bunch , (params.a) . 3 , , , . , ., , .

, dict, ,

In [1]: class Bunch:
   ...:     def __init__(self, **kwds):
   ...:         self.__dict__.update(kwds)

In [2]: params = Bunch(a = 'aaa', b = 'bbb')

In [3]: def f(p):
   ...:     print p.a
   ...:     

In [4]: f(params)
aaa

, , kwargs.

+1

( ) :

class AttributeDict(dict):
    def __getattr__(self, attr):
        return self[attr] if attr in self.keys() else None
    def __setattr__(self, attr, value):
        self[attr] = value 

:

def f(**kwargs):
    kwargs = AttributeDict(kwargs)

:

def f(**kwargs):
    kwargs = AttributeDict(kwargs)
    print kwargs.a, kwargs.b, kwargs.c

data = dict(a='aaa', b='bbb', c='ccc')
f(**data)

:

>>> 
aaa bbb ccc

.. x, , x.a

+1

It seems to me that you are doing redundand work, and the simplest hasb solution is left as it is. Those a, b, care keyword arguments, as well as positional, so you can call your function the way you like:

>>> def f(a, b, c=3):
...     print a, b, c

With all keywords args

>>> f(**{'a':1, 'b':2}) 
1 2 3

With a combination of positional and keywords args

>>> f(5, **{'b':4})
5 4 3

And get the correct error in case of incorrect args keywords

>>> f(**{'d':4, 'a':1, 'b':2}) 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() got an unexpected keyword argument 'd'
0
source

All Articles