tags:

views:

900

answers:

8

I come from a background in static languages. Can someone explain (hopefully through example) the real world advantages of using **kwargs over named arguments? To me it they seem to only make the function call more ambiguous. Thanks.

+3  A: 

**kwargs are good if you don't know in advance the name of the parameters. For example the dict constructor uses them to initialize the keys of the new dictionary.

dict(**kwargs) -> new dictionary initialized with the name=value pairs
    in the keyword argument list.  For example:  dict(one=1, two=2)
In [3]: dict(one=1, two=2)
Out[3]: {'one': 1, 'two': 2}
Cristian Ciupitu
It is often used if you want to pass lots of arguments to another function where you don't necessarily know the options. For instance, specialplot(a,**kwargs) can pass plot options in kwargs to a generic plot function that accepts those options as named parameters.
Tristan
Although I'd consider that bad style, since it hinders introspection.
bayer
+9  A: 

Real-world examples:

Decorators - they're usually generic, so you can't specify the arguments upfront:

def decorator(old):
    def new(*args, **kwargs):
        # ...
        return old(*args, **kwargs)
    return new

Places where you want to do magic with an unknown number of keyword arguments. Django's ORM does that, e.g.:

Model.objects.filter(foo__lt = 4, bar__iexact = 'bar')
PiotrLegnica
A: 

One example is implementing python-argument-binders, used like this:

>>> from functools import partial
>>> def f(a, b):
...     return a+b
>>> p = partial(f, 1, 2)
>>> p()
3
>>> p2 = partial(f, 1)
>>> p2(7)
8

This is from the functools.partial python docs: partial is 'relatively equivalent' to this impl:

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc
Dustin Getz
+12  A: 

You may want to accept nearly-arbitrary named arguments for a series of reasons -- and that's what the **kw form lets you do.

The most common reason is to pass the arguments right on to some other function you're wrapping (decorators are one case of this, but FAR from the only one!) -- in this case, **kw loosens the coupling between wrapper and wrappee, as the wrapper doesn't have to know or care about all of the wrappee's arguments. Here's another, completely different reason:

d = dict(a=1, b=2, c=3, d=4)

if all the names had to be known in advance, then obviously this approach just couldn't exist, right? And btw, when applicable, I much prefer this way of making a dict whose keys are literal strings to:

d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

simply because the latter is quite punctuation-heavy and hence less readable.

When none of the excellent reasons for accepting **kwargs applies, then don't accept it: it's as simple as that. IOW, if there's no good reason to allow the caller to pass extra named args with arbitrary names, don't allow that to happen -- just avoid putting a **kw form at the end of the function's signature in the def statement.

As for using **kw in a call, that lets you put together the exact set of named arguments that you must pass, each with corresponding values, in a dict, independently of a single call point, then use that dict at the single calling point. Compare:

if x: kw['x'] = x
if y: kw['y'] = y
f(**kw)

to:

if x:
  if y:
    f(x=x, y=y)
  else:
    f(x=x)
else:
  if y:
    f(y=y)
  else:
    f()

Even with just two possibilities, and of the very simplest kind!!!, the lack of **kw is aleady making the second option absolutely untenable and intolerable -- just imagine how it plays out when there half a dozen possibilities, possibly in slightly richer interaction... without **kw, life would be absolute hell under such circumstances!

Alex Martelli
+1 - surprisingly useful to be able to do this but something of a paradigm shift if you're used to (say) java.
ConcernedOfTunbridgeWells
+3  A: 

There are two common cases:

First: You are wrapping another function which takes a number of keyword argument, but you are just going to pass them along:

def my_wrapper(a, b, **kwargs):
    do_something_first(a, b)
    the_real_function(**kwargs)

Second: You are willing to accept any keyword argument, for example, to set attributes on an object:

class OpenEndedObject:
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

foo = OpenEndedObject(a=1, foo='bar')
assert foo.a == 1
assert foo.foo == 'bar'
Ned Batchelder
+5  A: 

Another reason you might want to use **kwargs (and *args) is if you're extending an existing method in a subclass. You want to pass all the existing arguments onto the superclass's method, but want to ensure that your class keeps working even if the signature changes in a future version:

class MySubclass(Superclass):
    def __init__(self, *args, **kwargs):
        self.myvalue = kwargs.pop('myvalue', None)
        super(MySubclass, self).__init__(*args, **kwargs)
Daniel Roseman
+1: Do this very, very frequently.
S.Lott
A: 

Here's an example, I used in CGI Python. I created a class that took **kwargs to the __init__ function. That allowed me to emulate the DOM on the server-side with classes:

document = Document()
document.add_stylesheet('style.css')
document.append(Div(H1('Imagist\'s Page Title'), id = 'header'))
document.append(Div(id='body'))

The only problem is that you can't do the following, because class is a Python keyword.

Div(class = 'foo')

The solution is to access the underlying dictionary.

Div(**{'class':'foo'})

I'm not saying that this is a "correct" usage of the feature. What I'm saying is that there are all kinds of unforseen ways in which features like this can be used.

Imagist
+1  A: 

And here's another typical example:

MESSAGE = "Lo and behold! A message {message!r} came from {object_} with data {data!r}."

def proclaim(object_, message, data):
    print(MESSAGE.format(**locals()))
ilya n.