{ Function Parameters. }

Objectives

By the end of this chapter, you should be able to:

  • Define what a parameter is and why they are essential when writing functions
  • Understand what keyword arguments are
  • Use default arguments in python functions
  • Define functions that accept an unknown number of arguments

Functions with arguments

Here is an example of a function that takes two arguments:

def pet_names(cat_name, dog_name):
    return f"I have a cat named {cat_name} and a dog named {dog_name}."

In this case, our function takes two arguments (a cat_name and a dog_name), and returns a message about the pets.

Keyword arguments

One nice thing about Python is that if you know the names of the arguments that you will pass to a function, you can pass them into the function in any order. All you need to do is provide the name (or keyword) for the argument, then the value you want to pass in. Check it out:

def pet_names(cat_name, dog_name):
    return f"I have a cat named {cat_name} and a dog named {dog_name}."

# no keyword arguments - order matters!
pet_names("Mittens", "Fido") # "I have a cat named Mittens and a dog named Fido."

pet_names("Fido", "Mittens") # "I have a cat named Fido and a dog named Mittens." -- uh oh, the names are the opposite of what we want, because we passed them to the function in the wrong order.

# keyword arguments
pet_names(cat_name="Mittens", dog_name="Fido")
# "I have a cat named Mittens and a dog named Fido."

# keyword arguments - order doesn't matter!
pet_names(dog_name="Fido", cat_name="Mittens")
# "I have a cat named Mittens and a dog named Fido."

When you call a function by passing in a keyword=value pair, you're said to be using keyword arguments. This can be especially useful if you have a function that accepts many parameters.

Default argument values

Sometimes you may want to set default values for parameters you pass into your function. In Python, the syntax looks the same as when you use keyword arguments, with one crucial difference: you use keyword arguments when you call a function, but you use default argument values when you define a function. Here's an example:

def add(a=5,b=15):
    return a + b

In this case, if we don't pass in any values when we call add, the first parameter will be 5 and the second parameter will be 15. But we can overwrite these defaults by simply passing numbers into the function when we call it:

add(15,1) # 16
add(4) # 19 - a is set to 4, b is set to 15
add() # 20
add(b=30) # 35 - a is set to 5 by default and b is 30 using keyword arguments

Variable number of function arguments

Sometimes we might want to write a function that can be called with an unknown number of arguments. There are two ways we can do this. The first is by using *, in the function definition which allows us to pass in an unknown number of arguments:

def foo(*args):
   print(args)

foo(1,2,3) # (1,2,3)
foo(1,2) # (1,2)
foo([1,2,3]) # ([1,2,3])

Inside of the function, the named parameter after the * corresponds to a tuple of the arguments passed in.

This can be helpful if we want to iterate through all of the arguments or apply some other function on a tuple:

def add(*nums):
    return sum(nums)

add(1,2,3,4) # 10

We can also use the * operator when invoking a function. In that case, the * will take an iterable like a list and split it up into separate parameters. Here is an example:

def add_three_nums(n1, n2, n3):
    return n1 + n2 + n3

add_three_nums(*[5,6,4]) # same as add_three_nums(5,6,4)

Unpacking an argument

The same way that we can include a * before a parameter, we can also do this for values passed to a function. If you're coming from JavaScript, this is going to look very similar to the spread operator. We unpack arguments when we need to convert a collection (tuple / list) to comma separated values. The idea here would be, we want to invoke a function, but all we have is a collection - let's see an example.

def add_and_multiply_numbers(a,b,c):
    return a + b * c

numbers = [1,2,3]
more_numbers = (4,5,6)

add_and_multiply_numbers(numbers) # TypeError
add_and_multiply_numbers(*numbers) # 7

add_and_multiply_numbers(more_numbers) # TypeError
add_and_multiply_numbers(*numbers) # 34

When there is a * as a parameter to a function, that parameter will be a tuple of values when the function is invoked. When you find a * that is not a parameter to a function, we are unpacking a value.

Variable number of keyword arguments

What if you want to pass in an unknown number of keyword arguments? In this case, we can use **, which allows us to access all of the keyword arguments inside of a function as a dictionary when we do not know how many keyword arguments will be passed.

def print_kwargs(a,b,**kwargs):
    print(a,b,kwargs)

print_kwargs(1,2,awesome='sauce', test='yup') # 1 2 {'test': 'yup', 'awesome': 'sauce'}

Unpacking a dictionary into keyword arguments

The same way that we can include a ** before a parameter, we can also do this for values passed to a function. Previously, we saw that * will unpack a collection (list / tuple), so what about **? That's for dictionary unpacking! What the ** operator will do is turn a dictionary into keyword arguments so that if we have one single dictionary, we can pass it to a function and unpack it into keyword arguments! Since dictionaries do not guarantee any kind of order, it's useful that they become keyword arguments since a function that uses keyword arguments can accept those keyword arguments in any order!

def add_and_multiply_numbers(a,b,c):
    return a + b * c

data = dict(a=1,b=2,c=3)

add_and_multiply_numbers(data) # TypeError
add_and_multiply_numbers(**data) # 7

When there is a * as a parameter to a function, that parameter will be a tuple of values when the function is invoked. When you find a * that is not a parameter to a function, we are unpacking a value.

You can read more about multiple function arguments here.

When you're ready, move on to Function Scope

Continue

Creative Commons License