Functions in Python allow us to reuse and organize code. For example, say we have some code that calculates the area of a circle:
radius = 5
area = 3.14 * radius * radius
That works! The problem is when we want to calculate the area of other circles, each with its own radius. We could just copy the code and change the variable names like this:
radius = 5
area1 = 3.14 * radius * radius
radius2 = 7
area2 = 3.14 * radius2 * radius2
But we want to reuse our code! Why would we want to redo our work? What if we wanted to calculate the area of thousands of circles??? That’s where functions help.
We’re making all the static content from our Boot.dev courses available for free here on the blog. This one is the “Functions” chapter from Learn to Code in Python. If you want to try the far more immersive version of the course, do check it out!
Instead, we can define a new function called area_of_circle
using the def
keyword.
def area_of_circle(r):
pi = 3.14
result = pi * r * r
return result
Let’s break this area_of_circle
function down:
- It takes one input (aka “parameter” or “argument”) called
r
- The body of the function is indented - this is the code that will run each time we use (aka “call”) the function
- It
return
s a single value (the output of the function). In this case, it’s the value stored in theresult
variable
To “call” this function (fancy programmer speak for “use this function”) we can pass in any number as the argument (in this case, 5
) for the parameter r
, and capture the output into a new variable:
area = area_of_circle(5)
print(area)
# 78.5
5
goes in as the inputr
- The body of the function runs, which stores
78.5
in theresult
variable - The function returns the value
78.5
, which means thearea_of_circle(5)
expression evaluates to78.5
78.5
is stored in thearea
variable and then printed
Because we’ve already defined the function, now we can use it as many times as we want with different inputs!
area = area_of_circle(6)
print(area)
# 113.04
area = area_of_circle(7)
print(area)
# 153.86
Functions are tricky! It takes a minute to get used to them, but after that they’ll be second nature to you. You might find yourself slowing down a bit, and if you do, that’s totally normal.
Subscribe to my YouTube channel if this video was helpful!
Let’s break down this function line by line so you can understand every nook and cranny of it.
def area_of_circle(r):
pi = 3.14
result = pi * r * r
return result
radius = 5
area = area_of_circle(radius)
print(area)
# 78.5
Here’s a chronological explanation of what happens when the above code is executed:
def area_of_circle(r)
: Thearea_of_circle
function is defined for later use, but not called. It accepts a single input, the arbitrarily namedr
. The body of the function (pi = 3.14
… etc) is ignored for now.radius = 5
: A new variable calledradius
is created and set to the value5
.area_of_circle(radius)
: Thearea_of_circle
function is called withradius
(in this case 5) as the input. Finally, we jump back to the function definition.def area_of_circle(r)
: We will now start executing the body of the function, andr
is set to5
.pi = 3.14
: A new variable calledpi
is created with a value of3.14
.result = pi * r * r
: Some simple math is evaluated (3.14 * 5 * 5
) and stored in theresult
variable.return result
: The result variable is returned from the function as output.area = area_of_circle(radius)
: The returned value is stored in a new variable calledarea
(in this case78.5
).print(area)
: The value ofarea
is printed to the console.
Multiple Parameters ๐
Functions can have multiple parameters (“parameter” being a fancy word for “input”). For example, this subtract
function accepts 2 parameters: a
and b
.
def subtract(a, b):
result = a - b
return result
The name of a parameter doesn’t matter when it comes to which values will be assigned to which parameter. It’s position that matters. The first parameter will become the first value that’s passed in, the second parameter is the second value that’s passed in, and so on. In this example, the subtract
function is called with a = 5
and b = 3
:
result = subtract(5, 3)
print(result)
# 2
Here’s an example with four parameters:
def create_introduction(name, age, height, weight):
first_part = "Your name is " + name + " and you are " + age + " years old."
second_part = "You are " + height + " meters tall and weigh " + weight + " kilograms."
full_intro = first_part + " " + second_part
return full_intro
It can be called like this:
my_name = "John"
my_age = "30"
intro = create_introduction(my_name, my_age, "1.8", "80")
print(intro)
# Your name is John and you are 30 years old. You are 1.8 meters tall and weigh 80 kilograms.
Printing vs Returning ๐
Some new developers get hung up on the difference between print()
and return
.
It can be particularly confusing when the test suite we provide simply prints the output of your functions to the console. It makes it seem like print()
and return
are interchangeable, but they are not!
print()
is a function that:- Prints a value to the console
- Does not return a value
return
is a keyword that:- Ends the current function’s execution
- Provides a value (or values) back to the caller of the function
- Does not print anything to the console (unless the return value is later
print()
ed)
Printing to debug your code ๐
Printing values and running your code is a great way to debug your code. You can see what values are stored in various variables, find your mistakes, and fix them. Add print statements and run your code as you go! It’s a great habit to get into to make sure that each line you write is doing what you expect it to do.
In the real world, it’s rare to leave print()
statements in your code when you’re done debugging. Similarly, you need to remember to remove any print()
statements from your code before submitting your work because it will interfere with the tests!
Where to Declare Functions ๐
You’ve probably noticed that a variable needs to be declared before it’s used. For example, the following doesn’t work:
print(my_name)
my_name = 'Lane Wagner'
It needs to be:
my_name = 'Lane Wagner'
print(my_name)
Code executes in order from top to bottom, so a variable needs to be created before it can be used. That means that if you define a function, you can’t call that function until after the definition.
Order of functions ๐
All functions must be defined before they’re used.
You might think this would make structuring Python code hard because the order of the functions needs to be just right. As it turns out, there’s a simple trick that makes it super easy.
Most Python developers solve this problem by defining all the functions in their program first, then they call an “entry point” function last. That way all of the functions have been read by the Python interpreter before the first one is called.
Note: conventionally this “entry point” function is usually called main
to keep things simple and consistent.
def main():
health = 10
armor = 5
add_armor(health, armor)
def add_armor(h, a):
new_health = h + a
print_health(new_health)
def print_health(new_health):
print(f"The player now has {new_health} health")
# call entrypoint last
main()
None Return ๐
When no return value is specified in a function, it will automatically return None
. For example, maybe it’s a function that prints some text to the console but doesn’t explicitly return a value. The following code snippets all return the same value, None
:
def my_func():
print("I do nothing")
return None
def my_func():
print("I do nothing")
return
def my_func():
print("I do nothing")
Multiple return values ๐
A function can return more than one value by separating them with commas.
def cast_iceblast(wizard_level, start_mana):
damage = wizard_level * 2
new_mana = start_mana - 10
return damage, new_mana # return two values
Receiving multiple values ๐
When calling a function that returns multiple values, you can assign them to multiple variables.
dmg, mana = cast_iceblast(5, 100)
print(f"Damage: {dmg}, Remaining Mana: {mana}")
# Damage: 10, Remaining Mana: 90
When cast_iceblast
is called, it returns two values. The first value is assigned to dmg
, and the second value is assigned to mana
. Just like function inputs, it’s the order of the values that matters, not the variable names. We could just as easily call the variables one
and two
:
one, two = cast_iceblast(5, 100)
print(f"Damage: {one}, Remaining Mana: {two}")
# Damage: 10, Remaining Mana: 90
That said, descriptive variable names make your code easy to understand, so use them!
What happened to the variables? ๐
The damage
and new_mana
variables from cast_iceblast
’s function body only exist inside of the function. They can’t be used outside of the function. We’ll explain that more later when we talk about scope.
Parameters vs arguments ๐
Parameters are the names used for inputs when defining a function. Arguments are the values of the inputs supplied when a function is called.
To reiterate, arguments are the actual values that go into the function, such as 42.0
, "the dark knight"
, or True
. Parameters are the names we use in the function definition to refer to those values, which at the time of writing the function, can be whatever we like.
That said, this is all semantics, and frankly, developers are really lazy with these definitions. You’ll often hear the words “arguments” and “parameters” used interchangeably.
# a and b are parameters
def add(a, b):
return a + b
# 5 and 6 are arguments
sum = add(5, 6)
Default values ๐
In Python, you can specify a default value for a function argument. It’s nice for when a function has arguments that are “optional”. You as the function definer can specify a specific default value in case the caller doesn’t provide one.
A default value is created by using the assignment (=
) operator in the function signature.
def get_greeting(email, name="there"):
print("Hello", name, "welcome! You've registered your email:", email)
get_greeting("[email protected]", "Lane")
# Hello Lane welcome! You've registered your email: [email protected]
get_greeting("[email protected]")
# Hello there welcome! You've registered your email: [email protected]
If the second parameter is omitted, the default "there"
value will be used in its place. As you may have guessed, for this structure to work, optional arguments (the ones with defaults) must come after all required arguments.