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
*args and **kwargs when calling a functionThis 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 = (1, "two", 3)
test_var_args_call(*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", "arg1": 1}
test_var_args_call(**kwargs)
Results:
arg1: 1 arg2: two arg3: 3
Reference: Core Python Programming, Second Edition, Section 11.6
Thanks for the succinct explanation of args and *kwargs. You made it nice and easy to understand.
thanks for this explanation. It's pretty cool to have such informations easy to understand.
Thanks for your explanation.
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!
Mike, I had not heard of Think Python. It looks like a great free Python resource.
Awesome! This is THE explanation I was looking for :).
I have newly discovered your blog and it is awsome. Also this is a very good tip. Thanks you!
I too want to thank you for your explanation. Just started Python/Django and blogs like this really speed up the task.
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.
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.
Excellent, clear explanation. Thanks for the post.
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
Emma, That's a good question-- I don't know the answer. If you find the answer, let me know.
Pretty usefull stuff. I found it usefull for my hobby project.
Python is so cool. :-)
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.
Thanks!
I second all that! Thanks for the explanation!
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?
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
Hi Emma,
Thanks for giving us your solution. Have you tried asking on Stack Overflow? They have been helpful to me in the past.
That was easy! Thanks!
Thanks for the brief explanation. It was really useful. :-)
Thanks,
I love python magics :)
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 ...
ces,
Thank you for your comment. I fixed the formatting of your comment by putting 4 spaces before each line of your code blocks.
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.
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!
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?
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.
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.
Much love man. This is what I needed and you put it so clear. Thank you
Thanks for the clarification, and I think you've got the most creative and bizarre domain I've seen in a while. Cheerio.
Nice - clear and thorough, very helpful, thanks
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?
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.
Great, concise explanation :)
Thanks for the concise tutorial. Perfect.
Thanks, very helpful! Great blog
great concise explanation. thanks a ton!!
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?
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
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.
I'm Eliot and this is my notepad for programming topics such as Python, Django, Ubuntu, Emacs, etc... more »