Tags

I am going to explain this in most basic terms. No jargon. No theory. Nothing. Just examples (and you should run all of them). But, to understand this, you should be familiar with user defined functions, tuples and dictionaries. Just a bit of familiarity, nothing more. So here we go.

(Note – Python 2.7 assumed. Four dots (….) indicates indentation. )

Here is how you define a function which doesn’t take any argument: –

def func():
....print 'Hi'

When you call this function, without any argument, it just prints ‘Hi’ which it should. If you try running this function with some argument, it produces TypeError warning you that the said function takes no argument.

Now let us modify the above function in a way that it should now take some argument. Here is the modified program: –

def func(n):
....print n

This function essentially just prints out the argument you give it. Try calling this function with: –

1- no argument given
2- n = 2
3- n = 2,3
4- n= ‘Peter’
5- replace n with name = 'Peter'
(See below to see how to call func(n) for each of above cases)

func()
func(2)
func(2,3)
func('Peter')
func(name = 'Peter')

Here is what you are going to see.
when you run func(), you’d see an error message telling you to provide a argument.
When you run func(2) or func('Peter'), it just prints out 2 or Peter.
However, running func(name='Peter') would produce an error telling you that func() got an unexpected keyword argument ‘name’.

Just give a quick read to above paragraphs. You’ll notice that: –

1- When you define a function, you also decide whether your function is going to take any argument.
2- If your function is going to take any argument, you also have to explicitly declare the number of arguments your function is supposed to take. If you give any more (or any less) arguments, your function won’t run.
3- Normally, your function can take only non-keyword arguments, not keyword arguments (as you saw when you tried to run above function by calling func(name='Peter'))

So far so good. But what if your function is supposed to take variable number of arguments and keyword arguments? When you define function in above manner, your program is inflexible in the sense of number (and type) of arguments it can take. Very often this is fine. In yet many other cases, this is a big no-no. You need flexibility.

Enter *args and **kwargs. args stands for (non-keyword) arguments and kwargs stands for keyword arguments. Now modify again above function like this:

def func(*args, **kwargs):
....print args
....print kwargs

Run it again in following ways –

func()
func(2)
func(2,3)
func('Peter')
func(name = 'Peter')
func(2,3, name = 'Peter', age = 20)
func(name = 'Peter', 2)

Output for func()

()
{}

Output for func(2)

(2,)
{}

Output for func(2,3)

(2,3)
{}

Output for func('Peter')

('Peter',)
{}

Output for func(name = 'Peter')

()
{'name' : 'Peter'}

Output for func(2,3,name = 'Peter', age = 20)

(2,3)
{'name' : 'Peter', 'age' : 20}

But this func(name = 'Peter', 2) won’t run at all. Why? Because we placed non-keyword argument after keyword argument. You have to place non-keyword arguments before keyword arguments.

In case you didn’t notice, our function prints out non-keyword arguments as a tuple and keyword arguments as a dictionary. If there is no argument at all, it will simply print out empty tuple and dictionary as you saw above.

Now define a function func() like this:

def func(foo, bar):
....print foo, bar

And run this func() like these:

func(*[1, 'two'])
func(**{'bar':2, 'foo': 'one'})

Your outputs should be:

1 two
one 2

Now think about what you did and what outputs you got. Don’t worry if it was too much for you. You can leave it for the time being.

I hope you now understand *args and **kwargs a little better.

Advertisements