*args and **kwargs in Python

·

5 min read

In this article you will learn how to use the single and double asterisk operators, to define functions that can take an arbitrary number of arguments. But before we dive on that, we first need to understand how arguments works in Python.

There are two two types of arguments,

  1. Positional arguments

  2. Keyword arguments.

Positional arguments are the arguments passed to a function in a specific order or position. The number of arguments and the order in which they are written is important. The following example shows a function that takes positional argument.

Example
#a function that defines 3 parameters
def greatest(a, b, c):
    if a > b:
        if a > c:
             num = a
    elif a > c:
         num = b
    else:
         num = c

    return num

#Calling the function using positional arguments.
result = greatest(18, 23, 4)
print(result)
Output:

23

In the above example we defined a function, greatest(), that is meant to get the largest of 3 values. We used the function to illustrate how positional arguments works. Note that when calling the function, we simply passed 3 arguments to the function without explicitly specifying which argument is a, which one is b or which one is c. The arguments are assigned to the parameters in the same order they were passed. So in the example, the first argument(18) is assigned to the parameter a, the second one(23) is assigned to b, and the third one(4) is assigned to c.

Keyword arguments on the other hard, expects the values to be explicitly assigned to the corresponding parameters using parameter = value syntax. This way the order of arguments is not relevant. Consider the following example.

Example
#a function that defines 3 parameters
def greatest(a, b, c):
    if a > b:
        if a > c:
             num = a
    elif a > c:
         num = b
    else:
         num = c

    return num

#Calling the function using keyword arguments.
result = greatest(b = 23, a = 18, c = 4)
print(result)
Output:

23

In the above example, we used keyword arguments when calling the greatest() function. In keyword arguments we are specifying which values belongs to which parameter. The order in which the arguments are passed is not important because we are explicitly specifying the parameter name.

Starred parameters

Starred parameters allows us to define functions that can take arbitrary number of positional or keyword arguments. For example, with the builtin print() function, we can pass in as many arguments as we want, and the function will print out each argument separately.

Exampleopen in editor
print('Hello', 'World', 'Welcome', 'to', 'Pynerds')
Output:

Hello World Welcome to Pynerds

In case with positional arguments, we use a single asterisk (*) followed by the name, while for keyword arguments, we use double asterisks(**) followed by the name of the parameter.

Arbitrary positional arguments( *args)

The single asterisk operator(*) is used in function parameters so as the function can takes an arbitrary number of positional arguments. By convention, the name "args" is used alongside the operator, however, this is just a convention, any other valid variable name can be used instead. Consider the following example:

Example
def myfunc(*args):
    print(args)
    for i in args:
        print(i)

myfunc(7, 3, 1, 4, 10, 0)
Output:

(7, 3, 1, 4, 10, 0) 7 3 1 4 10 0

As shown in the above example, specifying the single asterisk parameter makes a function to effectively take in arbitrary number of positional arguments.

The arbitrary positional arguments are received inside the function as a standard tuple. We can, therefore, perform all tuple operations on them.

In the following example, we define the greatest() function, so that it takes any number of positional arguments rather than just three.

Example
def greatest(*args):
     return max(args)

result = greatest(7, 11, 2, 10, 3)
print(result)
Output:

11

Arbitrary keyword arguments( **kwargs)

The double asterisk parameter(**) is used to define a function that can take an arbitrary number of keyword arguments. Similarly, the convention is to use the name "kwargs" to refer to the arguments but any other valid name can also be used.

Example
def func(**kwargs):
    print(kwargs)

func(a = 10, b = 20, c = 50, d = 120)
Output:

{'a': 10, 'b': 20, 'c': 50, 'd': 120}

The arguments are received inside the function as a standard dictionary. To access an element, we can use the name of the argument as the key.

Example
def func(**kwargs):
    #access individual arguments
    print(kwargs['a'])
    print(kwargs['b'])
    print(kwargs['c'])
    print(kwargs['d'])

func(a = 10, b = 20, c = 50, d = 120)
Output:

10 20 50 120

*args and **kwargs together

We can use both the single asterisk(*args) and the double asterisks **kwarga operators in the same function so that the function can handle arbitrary positional and keyword arguments at the same time. However, we must make sure that the parameter with the single asterisk(*args) always comes before the double asterisk parameter(**kwargs) in the function definition, otherwise, a SyntaxError exception will be raised.

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

func(10, 20, 30, a = 100, b = 300, c = 500)
Output:

(10, 20, 30) {'a': 100, 'b': 300, 'c': 500}

In the above example, we passed to the function both positional and keyword arguments. The positional arguments are received in the args tuple while the keyword arguments are received in the kwargs dictionary.

*args and **kwargs alongside other parameters

It is also possible to have other positional or keyword parameters alongside the *args and **kwargs parameters. This way, the *args parameters should come after all positional parameters and the **kwargs after all keyword parameters.

Example
def func(a, b, *args, x = None, y = None, **kwargs):
      print(a, b)
      print(args)
      print(x, y)
      print(kwargs)

func(1, 2, 3, 4, 5, x = 10, y = 20, i = 100, j = 200, k = 300)
Output:

1 2 (3, 4, 5) 10 20 {'i': 100, 'j': 200, 'k': 300}

As you can see above, the function knows where each argument belongs, whether it is a regular arguments or it belongs to the arbitrary positional or keywords arguments. It is upon the user to ensure that the arguments are correctly passed in accordance with the parameters specifications.