Python Function Arguments: A Definitive Guide

Learn all about positional and keyword arguments, default and variable number of arguments in Python functions.



Python Function Arguments: A Definitive Guide
Image by Author

 

Like all programming languages, Python lets you define functions. After you’ve defined a function, you can call it wherever you need in the script, and also import a function from a specific module inside another module. Functions make your code modular and reusable. 

In Python, you can define functions to take in different types of arguments. And this guide will teach you all about function arguments in Python. Let's begin.

 

A Quick Review of Python Functions

 

To define a  Python function, you can use the def keyword followed by the name of the function in parentheses. If you’d like the function to take in arguments, then the names of the arguments should be specified as parameters inside parentheses. After defining a function, you can call it with values for the parameters, called arguments. 

For example, consider the definition of the add() function: num1 and num2 are the parameters and the values used for these parameters in the function call are the arguments.

 

Python Function Arguments: A Definitive Guide
Parameters vs. Arguments | Image by Author

 

Positional Arguments

 

Consider the following function meet(). It takes in three strings and prints out the info of the person.

def meet(name,job_title,city):
    return f"Meet {name}, a {job_title} from {city}."

 

You can call the function with arguments, as shown below:

meet1 = meet('James','Writer','Nashville')
print(meet1)

 

Output >> Meet James, a Writer from Nashville.

 

In calling the function like this, the arguments are passed in as positional arguments. Positional arguments get mapped to the function parameters in the same order in which they appear in the function call.

Therefore, the first, second, and third arguments in the function call are used as the values of name, job_title, and city, respectively.

Here’s an example.

meet2 = meet('Artist','John','Austin')
print(meet2)

 

Output >> Meet Artist, a John from Austin.

 

In this case, the output, 'Meet Artist, a John from Austin.', does not make sense. Here is where keyword arguments can help.

 

Keyword Arguments

 

When using keyword arguments in the function call, you should specify the name of the parameter and the value it takes.

You can specify the keyword arguments in any order so long as the names of the parameters are correct. Let’s call the same function meet(), but this time with keyword arguments.

meet3 = meet(city='Madison',name='Ashley',job_title='Developer')
print(meet3)

 

Output >> Meet Ashley, a Developer from Madison.

 

What if you’d like to use a mix of positional and keyword arguments? This will make your code less readable and is not recommended. But if you’re using both positional and keyword arguments in the function call, the positional arguments should always precede the keyword arguments. Otherwise, you’ll run into errors.

 

Calling Functions with a Variable Number of Arguments

 

So far, we knew the number of arguments beforehand and defined the function accordingly. However, it may not always be the case. What if you'd like your function to take on a variable number of arguments each time it is called?

 

Python Function Arguments: A Definitive Guide
Image by Author

 

When working with Python code bases, you’ll have likely come across function definitions of the following form:

def some_func(*args, **kwargs):
	# do something on args and kwargs

 

Using *args and **kwargs in the function definition, you can make the function take in a variable number of positional and keyword arguments, respectively. They work as follows:

  • args collects a variable number of positional arguments as a tuple, which can then be unpacked using the * unpacking operator.
  • kwargs collects all the keyword arguments in the function call as a dictionary. These keyword arguments can then be unpacked using the ** operator. 

 

Note: Using *args and **kwargs is not a strict requirement. You can use any name of your choice.

 

Let's take examples to understand this better.

 

Variable Number of Positional Arguments

 

The function reverse_strings takes in a variable number of strings and returns a list of reversed strings. 

def reverse_strings(*strings):
    reversed_strs = []
    for string in strings:
        reversed_strs.append(string[::-1])
    return reversed_strs

 

You can now call the function with one or more arguments as needed. Here are a few examples:

def reverse_strings(*strings):
    reversed_strs = []
    for string in strings:
        reversed_strs.append(string[::-1])
    return reversed_strs

 

Output >> ['nohtyP']

 

rev_strs2 = reverse_strings('Coding','Is','Fun')
print(rev_strs2)

 

Output >> ['gnidoC', 'sI', 'nuF']

 

Variable Number of Keyword Arguments

 

The following function running_sum() takes in a variable number of keyword arguments:

def running_sum(**nums):
    sum = 0
    for key,val in nums.items():
        sum+=val
    return sum

 

As nums is a Python dictionary, you can call the items() method on the dict object to get a list of tuples. Each tuple is a key-value pair.

Here are a couple of examples:

sum1 = running_sum(a=1,b=5,c=10)
print(sum1)

 

Output >> 16

 

sum2 = running_sum(num1=7,num2=20)
print(sum2)

 

Output >> 27

 

Note: When using *args and **kwargs, the positional and keyword arguments are not required. Therefore, this is one way you can make your function arguments optional.

 

Using Default Values for Arguments

 

When defining Python functions, you can provide default values for one or more parameters. If you provide a default value for a specific parameter, you don’t have to use the argument in the function call.

  • If the argument corresponding to the parameter is provided in the function call, that value is used.
  • Else, the default value is used.

In the following example, the function greet() has a parameter, name, set to a default value of "there". 

def greet(name='there'):
    print(f"Hello {name}!")

 

So when you call greet() with a specific string as the argument, its value is used.

greet('Jane')

 

Output >> Hello Jane!

 

When you don’t pass in the name string, the default argument "there" is used.

greet()

 

Output >> Hello there!

 

Mutable Default Arguments - The Curious Case

 

When using default arguments, you should be careful to not set the default value to a mutable object. But why? Let's take an example to understand.

 

Python Function Arguments: A Definitive Guide
Image by Author | Created on imgflip

 

The following function append_to_list() takes in an element and a list as the arguments. It appends the element to the end of the list and returns the resultant list. 

# def_args.py
def append_to_list(elt,py_list=[]):
    py_list.append(elt)
    return py_list

 

You’d expect the following behavior:

  • When the function is called with both the element and the list, it returns the list containing the element appended to the end of the original list.
  • When you call the function with only the elements the argument, then it returns a list containing only that element. 

But let’s see what happens.

Open up your terminal, run python -i to start a Python REPL. I’ve defined the append_to_list() function in the def_args.py file.

>>> from def_args import append_to_list

 

When you call the function with the number 4 and the list [1,2,3] as the arguments, we get [1,2,3,4], which is expected.

>>> append_to_list(4,[1,2,3])
[1, 2, 3, 4]

 

Now, let us make a series of function calls with only the element to be appended to the list:

>>> append_to_list(7)
[7]
>>> append_to_list(9)
[7, 9]
>>> append_to_list(10)
[7, 9, 10]
>>> append_to_list(12)
[7, 9, 10, 12]

 

Wait, this isn’t what we expected. The first time the function is called with 7 as the argument (without the list), we get [7]. However, in the next calls, we see that the elements are appended to this list. 

This is because default arguments are bound to the function definition only once—at the time of defining the function. The list is first modified during the function call append_to_list(7). The list is not empty anymore. And all subsequent calls to the function—without the list—will modify the original list.

Therefore, you should avoid using mutable default arguments. A possible workaround is to set the default value to None, and initialize an empty list whenever the function call does not contain the list.

 

Conclusion

 

Here’s a summary of what you’ve learned in this tutorial. You’ve learned how to call Python functions with positional and keyword arguments, and how to use *args and **kwargs to pass in a variable number of positional and keyword arguments, respectively. You then learned how to set default values for certain parameters and the curious case of mutable default arguments. I hope you found this tutorial helpful. Keep coding!
 
 
Bala Priya C is a technical writer who enjoys creating long-form content. Her areas of interest include math, programming, and data science. She shares her learning with the developer community by authoring tutorials, how-to guides, and more.