Copying a few lines of code may seem harmless.
But what happens when the same instructions appear three, five, or ten times throughout your program?
A small change suddenly requires editing several places. One forgotten copy may behave differently from the others, and the program becomes harder to understand and maintain.
This is one of the problems that functions help us solve.
If a task appears several times, it probably needs a name.
A function turns a group of related instructions into a reusable solution that we can execute whenever we need it.
The problem with repeated code
Imagine that we need to calculate the total price of several purchases:
product_1 = "notebook"
price_1 = 8500
quantity_1 = 3
total_1 = price_1 * quantity_1
print(f"{quantity_1} units of {product_1} cost ${total_1}")
product_2 = "pencil"
price_2 = 2000
quantity_2 = 5
total_2 = price_2 * quantity_2
print(f"{quantity_2} units of {product_2} cost ${total_2}")
The program works, but the same procedure is repeated:
- Receive a product.
- Receive its price.
- Receive a quantity.
- Calculate the total.
- Display the result.
Instead of copying that procedure every time, we can create a function and give the task a descriptive name.
Creating a function with def
In Python, a function definition begins with the def keyword:
def greet():
print("Hello! Welcome to Python.")
This definition contains several important parts:
-
deftells Python that we are defining a function. -
greetis the function name. -
()contains the function parameters. -
:marks the beginning of the function body. - The indented instructions belong to the function.
Defining a function does not execute it automatically.
To run its instructions, we must call it:
def greet():
print("Hello! Welcome to Python.")
greet()
greet()
Each call executes the function body again.
This distinction is essential:
A function definition describes a task. A function call asks Python to perform it.
Parameters and arguments
Our first function always displays the same message.
To make it work with different values, we can add a parameter:
def greet(name):
print(f"Hello, {name}. Welcome to Python.")
greet("Laura")
greet("Carlos")
greet("Sofia")
In this example:
-
nameis a parameter. -
"Laura","Carlos", and"Sofia"are arguments.
A parameter represents the information that a function expects to receive.
An argument is the actual value provided when the function is called.
The same function can therefore process different data without changing its internal instructions.
Using multiple parameters
A function can receive more than one value:
def show_total(product, price, quantity):
total = price * quantity
print(f"{quantity} units of {product} cost ${total}")
show_total("notebook", 8500, 3)
show_total("pencil", 2000, 5)
Python matches positional arguments with parameters according to their order:
"notebook" → product
8500 → price
3 → quantity
For this reason, both the number and order of the arguments matter.
The calculation logic now exists in only one place. We can reuse it with as many products as necessary.
Returning results with return
The previous function displays the calculated total.
But what happens when another part of the program needs to use that value?
This is where return becomes important:
def calculate_total(price, quantity):
total = price * quantity
return total
The returned value can be stored in a variable:
notebook_total = calculate_total(8500, 3)
pencil_total = calculate_total(2000, 5)
print(notebook_total)
print(pencil_total)
It can also participate in another operation:
grand_total = notebook_total + pencil_total
print(grand_total)
A returned value is not limited to being displayed.
The program can store it, compare it, transform it, send it to another function, or use it in a larger calculation.
print() and return are not the same
This is one of the most important distinctions when learning Python functions.
Consider these two examples:
def show_double(number):
print(number * 2)
def calculate_double(number):
return number * 2
Both functions calculate the same value, but they do different things.
show_double() displays the value:
show_double(5)
Its output is:
10
calculate_double() returns the value:
result = calculate_double(5)
print(result + 4)
Its output is:
14
A useful way to remember the difference is:
print()communicates a value to the user.
returngives the value back to the program.
Use print() when the main purpose is to display information.
Use return when the result must continue participating in the program.
Why does a function return None?
Every Python function call produces a result.
When a function finishes without an explicit return, Python automatically returns None.
Consider this example:
def show_total(price, quantity):
print(price * quantity)
result = show_total(8500, 3)
print(result)
The output will be:
25500
None
The function displayed 25500, but it did not return that number.
Therefore, the value stored in result is None.
None does not mean zero, an empty string, or an error.
It represents the absence of a useful returned value.
Common beginner mistakes
1. Forgetting the parentheses
Writing the function name by itself refers to the function:
greet
Adding parentheses calls it:
greet()
The first expression identifies the function object. The second expression executes the function.
2. Sending the wrong number of arguments
A function with three required parameters expects three corresponding arguments:
def show_total(product, price, quantity):
return price * quantity
This call is incomplete:
show_total("notebook", 8500)
Python will report an error because the quantity argument is missing.
The correct call is:
show_total("notebook", 8500, 3)
3. Sending arguments in the wrong order
Consider this function:
def show_total(product, price, quantity):
return price * quantity
This call uses the correct number of arguments but places them incorrectly:
show_total(8500, "notebook", 3)
Python will assign:
8500 → product
"notebook" → price
3 → quantity
The names of positional parameters do not automatically identify the arguments. Their position determines how Python assigns them.
4. Trying to calculate with a function that only prints
This function displays a value but returns None:
def show_double(number):
print(number * 2)
Therefore, this operation will fail:
result = show_double(5)
print(result + 4)
The function prints 10, but result contains None.
To reuse the calculated value, return it instead:
def calculate_double(number):
return number * 2
result = calculate_double(5)
print(result + 4)
A practical example
Let us create a function that calculates the price of a purchase after applying a discount:
def calculate_discounted_price(price, discount_percentage):
discount = price * discount_percentage / 100
final_price = price - discount
return final_price
We can now use the same solution with different values:
first_product = calculate_discounted_price(100000, 10)
second_product = calculate_discounted_price(80000, 15)
print(first_product)
print(second_product)
The output is:
90000.0
68000.0
We can also combine the returned values:
purchase_total = first_product + second_product
print(purchase_total)
This demonstrates the main advantage of return: the results can continue moving through the program.
A better way to think about functions
Functions are more than a Python syntax feature.
They help us:
- Divide large problems into smaller tasks.
- Give meaningful names to those tasks.
- Avoid repeating instructions.
- Make changes in one place.
- Test individual pieces of logic.
- Reuse solutions with different data.
- Combine small solutions into larger programs.
When deciding whether to create a function, ask:
- Does this task appear more than once?
- Can I describe the task with a clear name?
- Which information does the task need?
- Should the function display something or return a result?
- Will another part of the program need the result?
These questions transform functions from a syntax exercise into a tool for designing better programs.
Final challenge
Create a function called calculate_average that receives three grades and returns their average.
Start with this structure:
def calculate_average(grade_1, grade_2, grade_3):
# Write your solution here
pass
Then store the result and display it:
student_average = calculate_average(4.5, 3.8, 4.2)
print(student_average)
As an additional challenge, create another function that receives the average and returns either "Passed" or "Failed".
Continue learning
I published a complete illustrated Spanish guide that explains these concepts with additional examples, practical exercises, and common mistakes:
What confused you the most when you first learned functions: parameters, arguments, return, or None?
Top comments (0)