*args and **kwargs

sismex01 at hebmex.com sismex01 at hebmex.com
Wed Nov 27 13:32:17 EST 2002


> From: Dan [mailto:dan at cox.com]
> Sent: Wednesday, November 27, 2002 12:09 PM
> 
> thanks for the answer specifically for "args".  Still I don't quite
> understand the Python syntax.
> 
> *something = encapsulate into a set   ??
> **something = encapsulate into a Dictionary??
> 
> dan
>

Not exactly;

  *args   -> accumulates all excess _positional_ arguments.
  *kw     -> accumulates all excess _keyword_ arguments.

say you have a function definition:

>>> def something(first,second,third):
...   print "first =", first
...   print "second =", second
...   print "third =", third

You can call this function in any number of ways:

>>> something(1,2,3)
first = 1
second = 2
third = 3

>>> something(second=1, third=2, first=3)
first = 3
second = 1
third = 2


This means that Python resolves parameter placement using
both the positional and the keyword arguments used in the
function call.

BUT, what happens with this?

>>> something(1,2,3,4)
---> TypeError: something() takes exactly 3 arguments (4 given)

>>> something(second="a", first=3, third=None, hello="Goodbye")
---> TypeError: something() got an unexpected keyword argument 'hello'

So, sometimes, it's useful to catch any unexpected, or
excess, or a variable number of positional or keyword
arguments.  You use "*args" and "**kwargs" for this.

Lets redefine 'something':

>>> def something(first, second, third, *rest, **others):
...   print "first =", first
...   print "second =", second
...   print "third =", third
...   if rest:
...      print "Rest of positional arguments =", rest
...   if others:
...      print "Other keyword arguments =", others

If no excess positional arguments are present in the function
call, then 'rest' is an empty tuple, otherwise, it contains
the exceeding (positional) arguments found, and are placed
in 'rest' in the same order they're present in the function
call.

The same goes for 'others'; if no excess keyword arguments
are found, 'others' is an empty dictionary; otherwise,
it contains all 'keyword=value' pairs found in the
function call which don't satisfy any of the formal
parameters for the function.

Since both 'rest' and 'others' are containers (the first
a tuple, the second a dictionary), they can be used in
a boolean test; if they're empty, then they're considered
to be "false", else "true".

So, you could now call 'something' like this:

>>> something(1,2,3,4)
first = 1
second = 2
third = 3
Rest of positional arguments = (4,)

A-Ha! A tuple, containing the lone '4' appended to the
argument list.  In the other example:

>>> something(second="a", first=3, third=None, hello="Goodbye")
first = 3
second = a
third = None
Other keyword arguments = {'hello': 'Goodbye'}

Gotcha! A dictionary, containing as key:value pairs, all key=value
parameters in the function call which don't correspond to any
of the function's formal parameters.


>>> something(2,3,4,5,6,hello="Goodbye",stop="GoGoGo")
first = 2
second = 3
third = 4
Rest of positional arguments = (5, 6)
Other keyword arguments = {'stop': 'GoGoGo', 'hello': 'Goodbye'}


And you can mix and match as you need.

This is a very, very useful characteristic of Python which I
hadn't found in any other language (only the positional part,
but never the keywords part).  It can get tricky sometimes,
when you mix both positional and keyword arguments, but
by the time you get used to it, you won't have any troubles.

I suppose others can expand s'more on this, let's see what
a Guru can add....

Good luck :-)

-gustavo




More information about the Python-list mailing list