Python has a special syntax, * (single asterisk) and ** (double asterisks), that lets you pass a variable number of arguments to a function. By convention, these are written as *args and **kwargs, but only the asterisks are important; you could equally write *vars and **vars to achieve the same result.

*args is used to pass a non-keyworded variable-length argument list to your function. **kwargs lets you pass a keyworded variable-length of arguments to your function.

Python functions

In a traditional Python function, you must explicitly define the number of arguments and parameters.

def func_one(x):
    print(x)

func_one(5)
# 5

But what if the number of parameters does not match the number of arguments? For example, if we define one parameter but pass in none we get an error:

func_one()
# func_one() missing 1 required positional argument: 'x'

And if we pass in two arguments but only define one parameter we have another error:

func_one(5, 10)
# TypeError: func_one() takes 1 positional argument but 2 were given

In Python a function only works if the number of arguments matches the number of parameters.

*args example

By using *args we can attach a variable-length number of arguments into our function.

For example:

def func_var_args(*args):
    print(args)

func_var_args(1, 2, '3')
# (1, 2, '3')

This is useful when we don’t know in advance how many arguments we need to pass in.

**kwargs example

If we want to pass a keyworded variable length of arguments to a function, we use **kwargs. It lets us handle named arguments in our function.

As an example:

def func_keyword_arg(**kwargs):
    print(kwargs)

func_keyword_arg(keyword1=10, keyword2='foo')
# {'keyword2': 'foo', 'keyword1': 10}

If we wanted to return just the key/value we can use the items() method.

def func_keyword_arg_dict(**kwargs):
    for key, value in kwargs.items():
        print(key,":",value)

func_keyword_arg_dict(keyword1=10, keyword2='foo')
# ('keyword2', ':', 'foo')
# ('keyword1', ':', 10)

*args and **kwargs together

Often *args and **kwargs are used together in a function where we have at least one required argument. In these instances, order matters. Positional-only parameters must come first, so ``args and **kwargs` are placed *after any required arguments.

def one_required_arg(required_arg, *args, **kwargs):
    print(required_arg)
    if args:
        print(args)
    if kwargs:
        print(kwargs)

All three of the following will work with this function:

func("required argument")
func("required argument", 1, 2, '3')
func("required argument", 1, 2, '3', keyword1=4, keyword2="foo")

Final thoughts

*args and **kwargs are powerful Python features that can make writing functions a much more enjoyable task. They are also common when extending an existing method in a subclass.

Just remember, normal, positional-only parameters come first. A simple way to remember this is always add *args and **kwargs at the end of your required arguments.

So if we have one required argument, write:

def some_func(required_arg, *args, **kwargs):
    pass

If there are two required arguments:

def some_func(required_arg1, required_arg2, *args, **kwargs):
    pass

And so on!




Want to improve your Python? I have a list of recommended Python books.