SaltyCrane Blog — Notes on JavaScript and web development

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)


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)


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)


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)


arg1: 1
arg2: two
arg3: 3

See also (updated 2009-04-12)

Reference: Core Python Programming, Second Edition, Section 11.6


#1 Skawaii commented on :

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

#2 Julien commented on :

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

#3 Dmitry commented on :

Thanks for your explanation.

#4 mike commented on :

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 :

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

#6 Katja commented on :

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

#7 Volkan commented on :

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

#8 Richie commented on :

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 :

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 :

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 :

Excellent, clear explanation. Thanks for the post.

#12 Emma commented on :

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)



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)



#13 Eliot commented on :

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 :

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

Python is so cool. :-)

#15 rubixC commented on :

For Emma

if you define your function like this:

def myfunction(self,**kwargs):pass

then u can call it like this:


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 :


#17 Nicolas commented on :

I second all that! Thanks for the explanation!

#18 Emma commented on :

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 :

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]
            raise Exception("Unexpected Argument")

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

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

#20 Eliot commented on :

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 :

That was easy! Thanks!

#22 Joshua commented on :

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

#23 İbrahim HIDIR commented on :


I love python magics :)

#24 ces commented on :

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:


Or, better, the caller could just call _myfunc_help 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 ...

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 :

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 :

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 :

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..


#28 Eliot commented on :

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 :

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!


#30 Thomas B. Higgins commented on :

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 :

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

#32 mitjak commented on :

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 :

Nice - clear and thorough, very helpful, thanks

#34 John commented on :

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 :

"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 :

Great, concise explanation :)

#38 ikani commented on :

Thanks, very helpful! Great blog

#39 George Matter commented on :

great concise explanation. thanks a ton!!

#40 Doug commented on :

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 :


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.


#42 Paul commented on :

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 :

Thanks, It helped me!

#44 Kilian commented on :

Thank you!


#45 Jonas commented on :

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

#46 dancebert commented on :

Two thumbs up. Thanks.

#47 James Phillips commented on :

This was very helpful in my work on fitting statistical distributions using scipy, thank you for helping me by posting this. Excellent explanation, well done.


#48 Simon Smith commented on :

Thank you for this, your explanation was very useful.

#49 Alfredo commented on :

Wonderful post. Straight to the point! I wish the python doc were that clear.

Thank you

#50 sevalad commented on :

cool. nice and helpfull. thanks.

#51 floerspr4 commented on :

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..

#52 star_p commented on :

I was glad to find out that Python has this. This is one more reason to switch to Python.

#53 ramber commented on :

This is the perfect tutorial that I have read in my experience!Thanks

#54 Rafe Kettler commented on :

Nice post, very helpful. This was definitely the refresher on this piece of syntax that I needed.

#56 Haiyang commented on :

Thanks for the clear explanation. I was puzzled by this for quite a while.

#57 Tabfugnic commented on :

Thank you so much for the clear explanation. It's been a real life saver.

#58 Dave S commented on :

great description! thanks.

#59 Marcus commented on :

short and clearly, thx!

#60 Naveen.iiit commented on :

Thanks for very Good explanation.

#61 Roman commented on :

Thanks for kwargs...!

#62 Joe commented on :

I'm trying to handle default values for this system, and I've got two ideas, wondering what others think.

defaults = {s0 : v0, s1 : v1} def test(**kwargs): defaults.update(kwargs) do_stuff(defaults)

And then another idea:

defaults = {s0 : v0, s1 : v1} def test(**kwargs): kwargs.setdefault(*defaults.items()) do_stuff(kwargs)

Is there a prettier way?

#64 Eric commented on :

Seriously, awesome. I keep forgetting and keep coming back to this site for the same old explanation.

Thanks for doing this.

#65 Wyatt commented on :

Thanks for all this help. I have been to this site a few times now. This won't be the last.

#66 Alfonso commented on :

Hi, thanks for this great help. Very valuable.

#67 Ken commented on :

Very helpful. Thanks.

#68 Oscar commented on :

You are very good teacher! Thanks!

#69 weigang wei commented on :

thanks a lot

#70 K commented on :

Thanks a lot

#71 jim4499 commented on :

Thank you for the clear & concise explanation.

#72 rekveld commented on :

thanks for the clear explanation, but why do you say **kwargs passes 'a keyworded, variable-length argument list'?

What is that ? It took me some time to figure out that that is actually a Python dictionary. Why not call it that ?

#73 Jeff commented on :

Great explanation! I find myself coming to your blog often.

#74 Bart J commented on :

Great explanation, thank you so much.

#75 Joni j commented on :

Thx, This explanation are real cool!

#76 Bernardo commented on :

Thanks, really helpful.

#77 Travis commented on :

brilliant, thanks a bunch!

#78 Cyril commented on :


#79 Chad commented on :

I love straight-to-the-point explanations like this. Thanks!

#81 Weigang commented on :

thanks. excellent explanation!

#82 jeff (different than above) commented on :

I love you. Too much? Then thank you very, very much. I've been trying to find a good explanation for a while now...

#83 bastien commented on :

Just another thanks here :)

It looks like this is one of the basic concepts that many people seem to have a hard time finding either in docs or tutorials.

Beautifully explained here!

#84 Nikhil commented on :

This is the best way to explain any topic. Thanks!

#85 andi commented on :

Very nice explanation of /*, the best i've ever found on the net.

#86 Dave commented on :

Thanks for the explanation, very easy to understand and exactly what I was looking for.

#87 pablo commented on :

Amazing how this post remains so useful even though it has been four years since it saw the light of day.

Thanks, I gained more insight into the use of the kargs argument even though I had already used them. The concepts are similar to the ones used in the command line parsing module argparse for giving instant POSIX behaviour to your python 2.7.x scripts:

#88 Piotr commented on :

thanks for this!!! Super easy to understand!

#89 Christopher Paulin commented on :

This article was easy to understand. I saved it for my own reference.

#90 John McCormick commented on :

Must be good to know an article 4 years old is still helping Python novices to this day.

Thanks for this, really useful!

#91 myro commented on :

thank you! simple and neat!

#92 Kyle commented on :

Helpful explanation. Thank you.

#93 Aidan commented on :

Thank you, easy and helpful)

#94 _JF commented on :

Thanks for explanation, I liked your blog and added to my feeds, best regards!

#95 Helen Neely commented on :

This for this simply -yet, comprehensive tutorial on kwargs. Although there are lots of examples all over the web, but none comes close to explaining it as much as you did here.

Nice work.

#96 Deep S commented on :

Hey thanks for the amazing explanation.

#97 Alcides Apaza commented on :

Very easy and straightforward explanation. Thanks! ps: I came here because cs253 on Udacity course

#98 zell08v commented on :

Thanks so much. You have made our lives much easier.


#99 sri commented on :

Thank you so much. You made it easy.


#100 grubenm commented on :

It makes sense now!


#101 izar commented on :

I just wonder if the order in which the arguments ({"arg3": 3, "arg2": "two"})are passed unordered to the function in the keyworded form example. Is it just to underline that you are calling the arg by their name so order doesn't matter... or I am getting it wrong?


#103 david gladson commented on :

You should point out, that the keys in mydict have to be exactly named like the parameters of function. Otherwise it will throw a typeError


#105 Meggan commented on :

going through a python bootcamp now. 9 and 5 years on, your post is still helpful =) thanks!