

*args and **kwargs in python explained - yasoob
http://freepythontips.wordpress.com/2013/08/04/args-and-kwargs-in-python-explained/

======
ghc
I find it interesting to see all of the comments on HN about the dislike of
args and kwargs, especially given their necessity for higher order
programming.

If you are making functions that modify other functions (like decorators),
these are highly useful. In Python you can't guarantee that all functions you
will want to modify are going to have the same type signature, so you need to
be able to gracefully handle all possible combinations and pass them on to
your function body. Sometimes you'll just pass args and kwargs on to a wrapped
function...other times you'll do things like pick out a single argument from
kwargs and use it to do something useful. But make no mistake, in Python these
come in handy to have!

~~~
pixie_
Personally it feels like spaghetti code. Tornado for instance is a web server
written in Python and there are classes that have many parents and kwargs is
used everywhere to pass named arguments up to each parent class in the
constructor. The problem is it's hard to get a grasp by looking at the
constructor as to what arguments should actually be passed to a class to
initialize it. There's no contract or spec enforced in python so it's easy to
see how errors can crop up by missing a random argument a certain parent class
is expecting. It also makes it difficult to understand what a class does when
the arguments a function expects are not declared.

------
rdtsc
They are also easy to abuse and make APIs hard to figure out. You could see
stuff like:

    
    
      process_payment_data(**kwargs)
    

In the docs and then have to go find out what possible values kwargs could
take.

~~~
kghose
The thing that I love about python is keyword arguments. It makes the code so
much more readable. The wildcards, while powerful, reduce readability.

For me, a equally powerful AND readable way is to have named arguments with
defaults. So when you change the function definition to add more arguments you
can insert defaults so as not to break existing code.

~~~
nostrademons
I find the wildcards most useful when implementing decorators or other cross-
cutting metaprogramming features. For example, you could easily do a tracing
decorator like this:

    
    
      def trace(fn):
        def worker(*args):
          logging.info('Called %s with args %r', fn.__name__, args)
          return fn(*args)
        worker.__name__ = fn.__name__
        # other decorator boilerplate
        return worker
    
      @trace
      def foo(bar, baz):
        ...
    
      @trace
      def foo2(x1, x2, x3):
        ...
    

(Note that logging.info itself takes args & kwargs as its arguments, and
passes them along as formatting arguments for the string.)

If you've ever looked at AspectJ or even Haskell, this sort of functionality
is virtually impossible in a statically-typed language. You go through all
sorts of contortions to be able to say "I want to operate on any type of
function, and I don't care how many or what type of arguments it has", and
then come out with something insanely complicated that satisfies nobody. For
certain use-cases, you really _don 't_ care what type of arguments it takes,
you just want to pass it through to some other function.

I do wonder if there's some other language feature that could be used to
achieve this without breaking documentation or static analysis, though.

~~~
lclarkmichalek
You can use the `functools.wraps` decorator to deal with copying all (most)
metadata from the wrapped function:

    
    
        def trace(fn):
            @functools.wraps(fn)
            def worker(*args):
                logging.info('Called %s with args %r', fn.__name__, args)
                return fn(*args)
            return worker
    

Docs:
[http://docs.python.org/3/library/functools.html#functools.wr...](http://docs.python.org/3/library/functools.html#functools.wraps)

~~~
darth_aardvark
I've been looking for something exactly like this. It's so tedious trying to
remember what metadata needs to be copied from a function when making a
decorator. Thanks!

------
zanny
I've always felt like the args and kwargs syntax in python is a blemish on an
otherwise beautiful language. I'm wondering why not just let any function
accept variable args, and reserve the keywords args and kwargs (without
stars), where in a function body they refer to non-specified / explicitly
defined arguments?

The only downside I see to that is the ability to write code poorly by passing
junk arguments into functions that never get used. But you can do that with
any function that declares kwargs or args right now.

Or just reserve args and kwargs and have it so functions with them in their
arguments list have the same behavior as args an kwargs (just without the ugly
stars). Maybe even denote them as __args__ and __kwargs__ in the same way you
access special member functions of objects through __foo__ syntax, that would
at least (to me) be consistent. I did a cursory google search if there is any
language wide syntax surrounding star + variable name, and I couldn't find
any, which seems to mean the name was just a hack using the syntax of a
pointer dereference from C.

Am I wrong here and just missing some grand logic behind it? The rest of the
language is really sensible so I probably am.

~~~
agentultra
I work on Hy, a Lisp that compiles to Python AST, and my intuition tells me
that it's a bit of a wart too. Particularly how the syntax for calling is
conflated with the definition and partly in how the arguments are filled in
the Call node (basically, left to right). It lets you do things like:

    
    
      >>> def foo(a, b="Default"):
      ...     print(a, b)
      ...
      >>> foo(1, 2)
      (1, 2)
      >>> foo(1)
      (1, 'Default')
      >>> foo(1, b="bar")
      (1, 'bar')
      >>> def baz(*args, **kwargs):
      ...     print(args, kwargs)
      ...
      >>> args = (1, 2, 3)
      >>> kwargs = {'foo': "bar"}
      >>> baz(*args, **kwargs)
      ((1, 2, 3), {'foo': 'bar'})
    

It's the first example that kind of seems 'off'. It's probably just cross-
polination from my CL experience (which seems 'more correct'):

    
    
      ?> (defun foo (a &key (b "Default")) (list a b))
      FOO
      ?> (foo 1 2)
      Error: Incorrect keyword arguments
    

For the most part it hasn't been an issue when I'm writing the code. But when
I read code that does this stuff on the call side frequently (or isn't
consistent in its use over time) it can be a little frustrating.

~~~
johnsoft
Python 3 lets you define functions with keyword-only arguments:

    
    
        >>> def foo(a, *, b="Default"):
        ...     print((a, b))
        ...
        >>> foo(1, b="bar")
        (1, 'bar')
        >>> foo(1, 2)
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
        TypeError: foo() takes 1 positional argument but 2 were given

~~~
agentultra
Right, I should've specified the Python version. Python 3's grammar for
argument lists changed a bit and added kwonlyargs to the mix. IIRC the call
node's arglist isn't just filled in left-to-right and handed names for keyword
arguments anymore.

Python 3 is definitely a step in the right direction. I wish adoption was a
little more rapid.

------
mtrn
After a couple of years with Python I had a first use case for an ordered
version of __kwargs. I haven 't really dived into the problem yet, but could
this be done with a metaclass or is __kwargs rooted deeper in the stack?

~~~
andrewcooke
you can't do it. see the comments in the constructor for OrderedDict (if i am
remembering correctly - _somewhere_ there's _something_ in the python source
that basically says "rats, need an ordered kwargs but that's not possible").

here you go -
[http://svn.python.org/view/python/trunk/Lib/collections.py?v...](http://svn.python.org/view/python/trunk/Lib/collections.py?view=markup)
\- line 32.

probably you need to pass in an OrderedDict instance.

~~~
mtrn
Yes, I thought so. Otherwise there would be much more ordered kwargs
decorators or hacks floating around. Thanks for the link to the source.

------
gpsarakis
I found this article [http://freepythontips.wordpress.com/2013/08/03/a-url-
shorten...](http://freepythontips.wordpress.com/2013/08/03/a-url-shortener-in-
python/) also interesting and well-written.

------
tlarkworthy
that has explained the mechanics of kwargs, but not explained _why_ we would
use kwargs. I hardly ever use kwargs because I think they make the source code
hard to read.

I think they are useful for systems with big configurations (that grow with
features during development). I give every customizable function a reference
to the big master config dict. Still not sure if that's a good design or not
...

~~~
gizmo686
I've used a couple of times for high-order functions. For example, I was
playing around with sound generation and decided to create a 'stream' object.
Instances of this object were defined by a function that generates the sound
wave. This meant that the constructor took a parameter a somewhat generic
function. I also found that some of my generator functions could take
arguments themselves, such as pitch. Having _args and_ *kwargs allows you to
pass these arbitrary variables through.

