Saltycrane logo

SaltyCrane Blog

Notes on Python, Django, and web development on Ubuntu Linux

    

How to use *args and **kwargs in Python

Or, How to use variable length argument lists in Python.

The special syntax, *args and **kwargs in function definitions is used to pass a variable number of arguments to a function. The single asterisk form (*args) is used to pass a non-keyworded, variable-length argument list, and the double asterisk form is used to pass a keyworded, variable-length argument list. Here is an example of how to use the non-keyworded form. This example passes one formal (positional) argument, and two more variable length arguments.

def test_var_args(farg, *args):
    print "formal arg:", farg
    for arg in args:
        print "another arg:", arg

test_var_args(1, "two", 3)

Results:

formal arg: 1
another arg: two
another arg: 3

Here is an example of how to use the keyworded form. Again, one formal argument and two keyworded variable arguments are passed.

def test_var_kwargs(farg, **kwargs):
    print "formal arg:", farg
    for key in kwargs:
        print "another keyword arg: %s: %s" % (key, kwargs[key])

test_var_kwargs(farg=1, myarg2="two", myarg3=3)

Results:

formal arg: 1
another keyword arg: myarg2: two
another keyword arg: myarg3: 3

Using *args and **kwargs when calling a function

This special syntax can be used, not only in function definitions, but also when calling a function.

def test_var_args_call(arg1, arg2, arg3):
    print "arg1:", arg1
    print "arg2:", arg2
    print "arg3:", arg3

args = ("two", 3)
test_var_args_call(1, *args)

Results:

arg1: 1
arg2: two
arg3: 3

Here is an example using the keyworded form when calling a function:

def test_var_args_call(arg1, arg2, arg3):
    print "arg1:", arg1
    print "arg2:", arg2
    print "arg3:", arg3

kwargs = {"arg3": 3, "arg2": "two"}
test_var_args_call(1, **kwargs)

Results:

arg1: 1
arg2: two
arg3: 3

See also (updated 2009-04-12):

Reference: Core Python Programming, Second Edition, Section 11.6

45 Comments — feed icon Comments feed for this post


#1 Skawaii commented on 2008-02-13:

Thanks for the succinct explanation of args and *kwargs. You made it nice and easy to understand.


#2 Julien commented on 2008-05-16:

thanks for this explanation. It's pretty cool to have such informations easy to understand.


#3 Dmitry commented on 2008-10-28:

Thanks for your explanation.


#4 mike commented on 2008-10-29:

Thanks just learnt python from Think Python free book, but there was no mention of this. I was seeing it frequently in other peoples code and it was confusing me. Not now. Thanks again!


#5 Eliot commented on 2008-10-29:

Mike, I had not heard of Think Python. It looks like a great free Python resource.


#6 Katja commented on 2008-10-31:

Awesome! This is THE explanation I was looking for :).


#7 Volkan commented on 2008-11-13:

I have newly discovered your blog and it is awsome. Also this is a very good tip. Thanks you!


#8 Richie commented on 2008-11-22:

I too want to thank you for your explanation. Just started Python/Django and blogs like this really speed up the task.


#9 Protector one commented on 2009-01-13:

Excellent explanation, no wonder it's the first google-hit for 'kwargs'. You might mention that the terms 'args' and 'kwargs' are arbitrary, though. I found out later that you can use any non-keyword identifier, as long as you use the asterisks.


#10 Eliot commented on 2009-01-20:

Protector one, you make a good point, the terms "args" and "kwargs" are arbitrary. thank you. i'll try to add a note in the post when i get a chance.


#11 John McCollum commented on 2009-02-16:

Excellent, clear explanation. Thanks for the post.


#12 Emma commented on 2009-04-08:

Thanks a lot! I have a question:

Here is a function: def myfunction(self, a=None, b=None): pass

Is it possible to make sure that the user will call the function like this:

self.myfunction(a=2, b=3)

self.myfunction(a=2)

self.myfunction(b=3),

and that he won't be able to call the function without specifying which number is which parameter. I don't want this: self.myfunction(2, 3)

self.myfunction(2)

Emma


#13 Eliot commented on 2009-04-15:

Emma, That's a good question-- I don't know the answer. If you find the answer, let me know.


#14 Michael Arp Sørensen commented on 2009-05-11:

Pretty usefull stuff. I found it usefull for my hobby project.

Python is so cool. :-)


#15 rubixC commented on 2009-05-13:

For Emma

if you define your function like this:

def myfunction(self,**kwargs):pass

then u can call it like this:

self.myfunction()
self.myfunction(a=1)
self.myfunction(a=1,b=2)
self.myfunction(a=1,b=2,c=3)
....

if called like self.myfunction(1,2) it will throw an exception. the problem is that with **kwargs u may specify as many parameters as u want (0 to n). U can check how many parameters the user entered (kwargs length) and then print an error message or whatever.


#16 Ubay Oramas commented on 2009-05-15:

Thanks!


#17 Nicolas commented on 2009-05-19:

I second all that! Thanks for the explanation!


#18 Emma commented on 2009-05-20:

Thanks rubixC,

I'm not sure that's exactly what I need.

If I define the function like this:

def myfunction(self,**kwargs):pass,

I won't be able to make the user call the arguments a and b. I won't be able to refer to them in the function either, like this:

def myfunction(self,**kwargs):print a,

because for all I know the user could have called this a anything I have no way of finding out, right?


#19 Emma commented on 2009-05-21:

Hi Sofeng and rubixC, I have thought of a way to do what I wanted, but it doesn't look particularly elegant:

def myfunc(self, **kwargs):
    kwargsdict = {}
    expected_args = ["a","b","c"]
    for key in kwargs.keys():
        if key in expected_args:
            kwargsdict[key] = kwargs[key]
        else:
            raise Exception("Unexpected Argument")
    self.__myfunc_help(kwargsdict)

def __myfunc_help(self,a=None,b=None,c=None):
    "real code here"
    pass
#(not tested)

But I don't really like this solution... Emma


#20 Eliot commented on 2009-05-22:

Hi Emma,
Thanks for giving us your solution. Have you tried asking on Stack Overflow? They have been helpful to me in the past.


#21 Amit commented on 2009-06-01:

That was easy! Thanks!


#22 Joshua commented on 2009-06-28:

Thanks for the brief explanation. It was really useful. :-)


#23 İbrahim HIDIR commented on 2009-07-27:

Thanks,

I love python magics :)


#24 ces commented on 2009-08-18:

Emma --

First, you have to ask yourself why you raising the error is better than letting the system raise the error.

In other words, self.myfunc could consist of just:

self._myfunc_help(**kwargs)

Or, better, the caller could just call myfunchelp directly.

You don't really need to copy from kwargs to kwargsdict. And you don't need to redundantly specify 'keys' in the for loop:

for key in kwargs:
  if not key in expected:
    raise ...
self._myfnc_help(**kwargs)

You could also play around with things like:

expected = set(['a', 'b', 'c'])
got = set(kwargs.keys())
if bool(got - expected):
   raise ...

#25 Eliot commented on 2009-08-19:

ces,
Thank you for your comment. I fixed the formatting of your comment by putting 4 spaces before each line of your code blocks.


#26 Angelica commented on 2009-08-27:

Good morning everyone, I have an urgent question regarding *args and there is NOWHERE ELSE a discussion around it...

I need to pass TWO non-keyworded, variable-length argument lists to my class and instance. Somebody said that the word 'args' can be different since we use * in front... so my question is: can I pass something like

(someargs, *args, *myotherargs)?

THANKS!! Angelica.


#27 Angelica commented on 2009-08-27:

Excuse me all... the asteriscs * are not apprearing in my previous parenthesis... args should read args, with asterix myotherargs should read myotherargs, with asterix... someargs shouldn't have the asterix though..

thanks!


#28 Eliot commented on 2009-08-27:

Angelica,
I fixed the formatting of your comment.

Regarding your question, I don't think there is a way to have two variable length argument lists. How about passing two lists as regular positional arguments?


#29 Angelica commented on 2009-08-31:

Thanks Eliot, You are right, I tried that option last week. I already created my args as the sum of two lists and it worked... so I use args first as my plain variable length list in one method, and for the next method, I do args = args + moreargs. My class is running now!

Angelica.


#30 Thomas B. Higgins commented on 2009-09-02:

This is great; clear as a bell, and not to be found in my Python book! I would be interested in knowing whether there are any wrinkles to keep in mind when using *args and *kwargs with classes, as opposed to functions.


#31 Sibande commented on 2009-09-06:

Much love man. This is what I needed and you put it so clear. Thank you


#32 mitjak commented on 2009-10-02:

Thanks for the clarification, and I think you've got the most creative and bizarre domain I've seen in a while. Cheerio.


#33 tosh commented on 2009-11-05:

Nice - clear and thorough, very helpful, thanks


#34 John commented on 2009-12-09:

Conventions aside, must they be named "args" and "kwargs"?

What's the significance of the '*' and '**'. Does the former declare a tuple and latter a dictionary?


#35 Eliot commented on 2009-12-09:

John,
"args" and "kwargs" are not the required names-- you can use whatever names you like.

Regarding the significance of * and **, this is the special syntax used to specify variable length arguments.


#36 diman82 commented on 2010-01-17:

Great, concise explanation :)


#37 David Underhill commented on 2010-01-18:

Thanks for the concise tutorial. Perfect.


#38 ikani commented on 2010-01-19:

Thanks, very helpful! Great blog


#39 George Matter commented on 2010-01-29:

great concise explanation. thanks a ton!!


#40 Doug commented on 2010-02-03:

Thanks for the simple explanation!

So, I have a very specific question. I have function definition like this:

def my_func(var1='test', *args, **kwargs):

If I call that function like this:

my_func('arg1', 'arg2', 'arg3')

then 'arg1' seems to always be interpreted as the argument to var1 with only 'arg2' and 'arg3' being added to args. But what I wanted was for all of my arguments to be put in args. Is that possible?

I only want to override the default for var1 by explicitly doing so. I guess I wasn't counting on my keyword definition for var1 to also be positional in this case. Any ideas?


#41 Ryan commented on 2010-02-09:

Doug,

You should probably not mix positional and keyword arguments as you're doing.

When moving a named argument changes the behavior, that's a clue that something is not right. Consider this,

my_func('arg1', 'arg2', 'arg3', var1='var1_arg')

which will throw a TypeError, because there are multiple values for var1. Ambiguity is bad, and Python doesn't know what to do.

How about doing something like

if not var1: var1='default_value'

in the body? That way you can keep a default value, and change it at will. To make this work, don't specify var1 in the function definition.

-Ryan


#42 Paul commented on 2010-02-22:

Thanks. The explanation was very helpful. I had been using my own homebrew method based on function arguments of dictionary (hash) type for passing named arguments. I was forced to do this in Perl as it had nothing of this sort built in. I was glad to find out that Python has this. This is one more reason to switch to Python.


#43 Gurminder commented on 2010-03-16:

Thanks, It helped me!


#44 Kilian commented on 2010-05-16:

Thank you!

Kilian


#45 Jonas commented on 2010-08-27:

Thanks for explaining this; I was getting tired of seeing this all over the Tipfy documentation and not understanding it.

Post a comment

Required
Required, but not displayed
Optional

Format using Markdown. (No HTML.)
  • Code blocks: prefix each line by at least 4 spaces or 1 tab (and a blank line before and after)
  • Code span: surround with backticks
  • Blockquotes: prefix lines to be quoted with >
  • Links: <URL>
  • Links w/ description: [description](URL)
Created with Django | Hosted by Slicehost