Single and double asterisks preceding variables in function arguments

Peter Otten __peter__ at web.de
Mon Jan 26 17:24:04 EST 2004


Stephen Boulet wrote:

> <<
> a={'c1':'red','c2':'blue','c3':'fusia'}
> def bar(**params):
> ....for k in params.keys():
> ........print k, params[k]
> bar(a)
> Traceback (most recent call last):
>    File "<input>", line 1, in ?
> TypeError: bar() takes exactly 0 arguments (1 given)
>  >>
> 
> Why does bar take zero arguments?

The error message is not as clear as it should should be. bar() takes 0
mandatory, 0 positional and an arbitrary number of keyword arguments, e.
g.:

>>> def bar(**params):
...     print params
...
>>> bar(color="blue", rgb=(0,0,1), name="sky")
{'color': 'blue', 'rgb': (0, 0, 1), 'name': 'sky'}

That's the standard way of passing optional keyword arguments, but you can
also pass them as a dictionary preceded by **:

>>> adict = {'color': 'blue', 'rgb': (0, 0, 1), 'name': 'sky'}
>>> bar(**adict)
{'color': 'blue', 'rgb': (0, 0, 1), 'name': 'sky'}

This is useful, if you want to compose the argument dict at runtime, or pass
it through to a nested function.

> 
> Hmm, but:
> 
> <<
> def bar2(*params,**moreparams):
> ....print "params are ", params,'\n'
> ....for k in moreparams.keys():
> ........print k, moreparams[k]
> ....print "moreparams are ", moreparams

bar2() accepts 0 mandatory, as many positional and keyword arguments as you
like. For the expected result, try 

>>> def bar2(*args, **kwd):
...     print args
...     print kwd
...
>>> bar2(1,2,3)
(1, 2, 3)
{}
>>> bar2(1, name="sky", color="blue")
(1,) # tuple of optional positional args
{'color': 'blue', 'name': 'sky'} # dict of optional keyword args
>>>

And now a bogus example that shows how to compose the arguments:

>>> def bar3(x, *args, **kwd):
...     print "x=", x
...     print "args=", args
...     print "kwd=", kwd
...     if "terminate" not in kwd:
...             kwd["terminate"] = None # avoid infinite recursion
...             bar3(x*x, *args + ("alpha",), **kwd)
...
>>> bar3(2, "beta", color="blue")
x= 2
args= ('beta',)
kwd= {'color': 'blue'}
x= 4
args= ('beta', 'alpha')
kwd= {'color': 'blue', 'terminate': None}
>>>

To further complicate the matter, a mandatory arg may also be passed as a
keyword argument:

bar3(x=2, color="blue") # will work, args is empty
bar("beta", # will not work; both "beta" and 2 would be bound to x
            # and thus create a conflict                
    x=2, color="blue")


Peter




More information about the Python-list mailing list