def greet(name):
print(f"Hello, {name}!")User-Defined Functions
User-Defined Functions
In the previous lesson, we used built-in Python functions such as print(), type(), int(), float(), str(), len(), round(), and abs().
Now we will create our own functions.
A user-defined function is a reusable block of code that performs a specific task.
We use functions to:
- avoid repeating code
- give names to useful actions
- organize programs into smaller parts
- reuse the same logic with different inputs
Creating a Function
In Python, functions are created using the def keyword.
def <function_name>(<argument>):
<code_of_the_function>The def keyword marks the beginning of a function definition.
The function name comes after def.
The code inside the function must be indented.
Defining and Calling a Function
This code defines a function:
This cell does not print anything.
Python has learned that the function greet() exists, but we have not used it yet.
To use a function, we call it.
greet("Jorge")Hello, Jorge!
We can call the same function many times.
greet("Ana")
greet("Luis")
greet("Marta")Hello, Ana!
Hello, Luis!
Hello, Marta!
The value inside the parentheses is called an argument.
Write a function called say_goodbye(name).
It should print a goodbye message using the name.
Example:
say_goodbye("Ana")Expected output:
Goodbye, Ana!def say_goodbye(name):
print(f"Goodbye, {name}!")
say_goodbye("Ana")Goodbye, Ana!
Functions Help Us Avoid Repetition
Imagine we want to print multiplication tables.
Without a function, we would repeat the same structure many times.
With a function, we write the logic once.
def multiplication_table(x):
for n in range(1, 11):
print(f"{x} x {n} = {x * n}")Now we can reuse it with different numbers.
multiplication_table(3)3 x 1 = 3
3 x 2 = 6
3 x 3 = 9
3 x 4 = 12
3 x 5 = 15
3 x 6 = 18
3 x 7 = 21
3 x 8 = 24
3 x 9 = 27
3 x 10 = 30
multiplication_table(8)8 x 1 = 8
8 x 2 = 16
8 x 3 = 24
8 x 4 = 32
8 x 5 = 40
8 x 6 = 48
8 x 7 = 56
8 x 8 = 64
8 x 9 = 72
8 x 10 = 80
Write a function called countdown(number).
It should print the numbers from number down to 1.
Example:
countdown(5)Expected output:
5
4
3
2
1def countdown(number):
for n in range(number, 0, -1):
print(n)
countdown(5)5
4
3
2
1
Positional Arguments
A function can receive more than one argument.
def <function_name>(<argument_1>, <argument_2>):
<code_of_the_function>For example, this function takes a student’s name and grade, then says if the student passed.
def check_pass(name, grade):
if grade >= 5:
print(f"{name} has passed!")
else:
print(f"{name} has failed")check_pass("Luke", 8)Luke has passed!
check_pass("Yoda", 2)Yoda has failed
The arguments above are positional arguments.
That means Python uses their position to decide what each value means.
check_pass("Leia", 6)Leia has passed!
Here:
"Leia"goes intoname6goes intograde
The order matters.
check_pass(6, "Leia")TypeError: '>=' not supported between instances of 'str' and 'int'
This fails because Python tries to compare "Leia" with 5.
Without running the code, guess the output.
def describe_pet(name, animal):
print(f"{name} is a {animal}")
describe_pet("Nina", "cat")
describe_pet("dog", "Rex")Nina is a cat
dog is a RexThe second call works, but the order is wrong. Python does not know that "dog" is probably the animal and "Rex" is probably the name.
Checking Input Types
Sometimes a function receives arguments with the wrong type.
We can check the type before continuing.
def check_pass(name, grade):
if type(name) != str:
print("Name must be a string")
return
if type(grade) != int and type(grade) != float:
print("Grade must be a number")
return
if grade >= 5:
print(f"{name} has passed!")
else:
print(f"{name} has failed")check_pass("Luke", 8)
check_pass("Yoda", 2)
check_pass(6, "Leia")Luke has passed!
Yoda has failed
Name must be a string
The return statements stop the function early.
Improve the function below so that it checks whether x and y are numbers.
def addition(x, y):
print(x + y)def addition(x, y):
if type(x) != int and type(x) != float:
print("x must be a number")
return
if type(y) != int and type(y) != float:
print("y must be a number")
return
print(x + y)print() and return
A function can show information with print().
A function can also send information back with return.
This difference is important.
A Function That Uses print()
def add_print(a, b):
print(a + b)result = add_print(3, 2)5
The function prints 5.
But what is stored in result?
print(result)None
The answer is None.
The function displayed a value, but it did not return a value.
A Function That Uses return
def add_return(a, b):
return a + bresult = add_return(3, 2)This cell does not display anything because there is no print().
But the result has been stored.
print(result)5
A returned value can be reused.
double_result = result * 2
print(double_result)10
What is the difference between these two functions?
def square_print(x):
print(x ** 2)
def square_return(x):
return x ** 2square_print(x) displays the square on the screen.
square_return(x) gives the square back to the program.
This means we can store it.
result = square_return(5)
print(result + 10)When Should We Use print()?
Use print() when you want to show something to the user.
def greet(name):
print(f"Hello, {name}!")This function is about displaying a message.
When Should We Use return?
Use return when the function calculates something that you want to reuse.
def difference(a, b):
y = a - b
return yz = difference(3, 2)
print(z)1
Another example:
def square_root(x):
return x ** (1 / 2)n = square_root(9)
print(n)3.0
We can use returned values inside other calculations.
x = 16
y = square_root(x)
print(f"The square root of {x} is {y}")The square root of 16 is 4.0
We can also apply the function multiple times.
n = square_root(square_root(81))
print(n)3.0
Functions Can Return Text
A function can return a string.
def greet_with_return(name):
return f"Hello, {name}!"
message = greet_with_return("Bob")
print(message)Hello, Bob!
Write a function called make_email(username, domain).
It should return an email address.
Example:
make_email("ana", "university.edu")Expected result:
ana@university.edudef make_email(username, domain):
return f"{username}@{domain}"
email = make_email("ana", "university.edu")
print(email)ana@university.edu
Functions Can Return Boolean Values
A function can return True or False.
def is_even(number):
return number % 2 == 0print(is_even(10))
print(is_even(7))True
False
This is useful with if statements.
number = 12
if is_even(number):
print("Even")
else:
print("Odd")Even
Write a function called is_adult(age).
It should return True if the age is at least 18.
Otherwise, it should return False.
Test it with three ages.
def is_adult(age):
return age >= 18
print(is_adult(15))
print(is_adult(18))
print(is_adult(30))False
True
True
Example: Distance Between Two Points
We can use functions to give names to mathematical formulas.
This function takes the coordinates of two points in a 2D space and prints the distance between them.
(d = )
def distance_2d(x1, y1, x2, y2):
width = x2 - x1
height = y2 - y1
d = (width ** 2 + height ** 2) ** (1 / 2)
return ddistance = distance_2d(1, 3, 5, 4)
print(f"The distance is {distance:.2f}")The distance is 4.12
print(distance_2d(1, 1, 2, 2))
print(distance_2d(2, 2, 1, 1))
print(distance_2d(1, 2, 1, 2))1.4142135623730951
1.4142135623730951
0.0
::: {.callout-note}
Exercise
Write a function called rectangle_area(width, height).
It should return the area of a rectangle.
Then use it to calculate the area of:
- a rectangle with width
3and height4 - a rectangle with width
10and height2 - a rectangle with width
5.5and height3:::
def rectangle_area(width, height):
return width * height
print(rectangle_area(3, 4))
print(rectangle_area(10, 2))
print(rectangle_area(5.5, 3))12
20
16.5
Example: Odd Index Characters
We can write a function that returns the characters in odd index positions.
def odd_index_chars(text):
return text[1::2]
print(odd_index_chars("abcdefg"))bdf
Remember that Python starts counting at 0.
For the string "abcdefg":
ahas index0bhas index1chas index2dhas index3
So the odd index characters are b, d, and f.
Write a function called first_half(text).
It should return the first half of a string.
Example:
first_half("python")Expected result:
pytdef first_half(text):
middle = len(text) // 2
return text[:middle]
print(first_half("python"))pyt
Example: Sum of Squares
Write a function that calculates the sum of the squares of all integers from 1 to n.
For example, if n = 4, the result is:
(1^2 + 2^2 + 3^2 + 4^2 = 30)
def sum_of_squares(number):
result = 0
for x in range(1, number + 1):
result = result + x ** 2
return resulty = sum_of_squares(2)
print(y)
y = sum_of_squares(4)
print(y)5
30
Write a function called sum_from_1_to_n(number).
It should return the sum of all integers from 1 to number.
Example:
sum_from_1_to_n(5)Expected result:
15def sum_from_1_to_n(number):
result = 0
for x in range(1, number + 1):
result = result + x
return result
print(sum_from_1_to_n(5))15
Example: Quadratic Function
We can also use functions to represent mathematical functions.
Consider:
(f(x) = a x^2 + b x + c)
def quadratic(a, b, c, x):
y = a * x ** 2 + b * x + c
return yprint(quadratic(1, 1, -6, 2))0
The function above calculates:
(1 ^2 + 1 - 6)
::: {.callout-note}
Exercise
Use the function quadratic(a, b, c, x) to calculate:
(f(x) = 2x^2 - 3x + 1)
for:
x = 0x = 1x = 2x = 3:::
def quadratic(a, b, c, x):
y = a * x ** 2 + b * x + c
return y
print(quadratic(2, -3, 1, 0))
print(quadratic(2, -3, 1, 1))
print(quadratic(2, -3, 1, 2))
print(quadratic(2, -3, 1, 3))1
0
3
10
Keyword Arguments
Keyword arguments are passed using the parameter name.
function(argument_name=value)With positional arguments, order matters.
With keyword arguments, the name tells Python where the value goes.
def greet(name, greeting="Hello"):
print(f"{greeting}, {name}!")greet("Alice")
greet("Bob", greeting="Hi")
greet("Don Pepito", greeting="Hola")Hello, Alice!
Hi, Bob!
Hola, Don Pepito!
Here, name is required.
greeting has a default value. If we do not provide it, Python uses "Hello".
Default Values
A default value makes an argument optional.
def root(x, n=2):
return x ** (1 / n)By default, the function computes the square root.
print(root(4))2.0
But we can choose another root.
print(root(16, n=4))2.0
Keyword arguments must come after positional arguments.
This works:
root(16, n=4)This does not work:
root(n=4, 16)Write a function called apply_discount(price, discount=10).
It should return the price after applying the discount percentage.
Example:
apply_discount(100)Expected result:
90Example:
apply_discount(100, discount=25)Expected result:
75def apply_discount(price, discount=10):
return price - price * discount / 100
print(apply_discount(100))
print(apply_discount(100, discount=25))90.0
75.0
Example: Calculator With Keyword Arguments
Build a calculator function that accepts three arguments:
num1num2operation
If no operation is given, it should use addition.
def calculator(num1, num2, operation="addition"):
if operation == "addition":
return num1 + num2
elif operation == "subtraction":
return num1 - num2
elif operation == "multiplication":
return num1 * num2
elif operation == "division":
return num1 / num2result = calculator(4, 2)
print(result)
result = calculator(4, 2, operation="addition")
print(result)
result = calculator(4, 2, operation="subtraction")
print(result)
result = calculator(4, 2, operation="multiplication")
print(result)
result = calculator(4, 2, operation="division")
print(result)6
6
2
8
2.0
This function works, but it has two possible problems:
- it does not handle unknown operations
- it does not handle division by zero
We can improve it.
def calculator(num1, num2, operation="addition"):
if operation == "addition":
return num1 + num2
elif operation == "subtraction":
return num1 - num2
elif operation == "multiplication":
return num1 * num2
elif operation == "division":
if num2 == 0:
return "Cannot divide by zero"
return num1 / num2
else:
return "Unknown operation"print(calculator(4, 2))
print(calculator(4, 2, operation="division"))
print(calculator(4, 0, operation="division"))
print(calculator(4, 2, operation="power"))6
2.0
Cannot divide by zero
Unknown operation
Add one more operation to the calculator: "power".
It should return num1 ** num2.
def calculator(num1, num2, operation="addition"):
if operation == "addition":
return num1 + num2
elif operation == "subtraction":
return num1 - num2
elif operation == "multiplication":
return num1 * num2
elif operation == "division":
if num2 == 0:
return "Cannot divide by zero"
return num1 / num2
elif operation == "power":
return num1 ** num2
else:
return "Unknown operation"
print(calculator(2, 3, operation="power"))8
Example: Quadratic Function With Defaults
Let us return to the quadratic function.
(f(x) = a x^2 + b x + c)
This time, a = 1, b = 1, and c = -6 are default values.
def quadratic(x, a=1, b=1, c=-6):
y = a * x ** 2 + b * x + c
return yIf we only provide x, Python uses the default values.
result = quadratic(2)
print(result)0
We can also replace the defaults.
result = quadratic(2, a=2, b=0, c=0)
print(result)8
Use the function above to calculate:
(f(x) = x^2 + x - 6)
for x = -3, x = 0, and x = 2.
Then use the same function to calculate:
(g(x) = 3x^2 - 2x + 1)
for x = 2.
def quadratic(x, a=1, b=1, c=-6):
y = a * x ** 2 + b * x + c
return y
print(quadratic(-3))
print(quadratic(0))
print(quadratic(2))
print(quadratic(2, a=3, b=-2, c=1))0
-6
0
9
Example: Radioactive Decay
In this exercise, we will create a function to model radioactive decay.
Radioactive decay describes how the amount of a radioactive element decreases over time.
The formula is:
(N(t) = N_0 (1/2)^{t / T_h})
Where:
- \(T_h\) is the half-life of the radioactive element
- \(N(t)\) is the number of radioactive atoms at time \(t\)
- \(N_0\) is the initial number of radioactive atoms
Create a function called radioactive_decay(n0, half_life, t).
It should return the number of atoms remaining at time t.
We will use default values for half_life and t.
def radioactive_decay(n0, half_life=5730, t=500):
return n0 * (1 / 2) ** (t / half_life)Carbon-14 has a half-life of approximately 5730 years.
remaining_carbon_14 = radioactive_decay(1000, half_life=5730, t=2000)
print(f"After 2000 years, there are approximately {remaining_carbon_14:.0f} Carbon-14 atoms remaining.")After 2000 years, there are approximately 785 Carbon-14 atoms remaining.
Uranium-238 has a much longer half-life, approximately 4.468 billion years.
remaining_uranium_238 = radioactive_decay(100, half_life=4.468 * 10 ** 9, t=10 ** 9)
print(f"After 1 billion years, there are approximately {remaining_uranium_238:.0f} Uranium-238 atoms remaining.")After 1 billion years, there are approximately 86 Uranium-238 atoms remaining.
::: {.callout-note}
Exercise
Use radioactive_decay() to answer this question:
A sample starts with 5000 atoms. The half-life is 100 years.
How many atoms remain after:
0years50years100years200years :::
def radioactive_decay(n0, half_life=5730, t=500):
return n0 * (1 / 2) ** (t / half_life)
print(radioactive_decay(5000, half_life=100, t=0))
print(radioactive_decay(5000, half_life=100, t=50))
print(radioactive_decay(5000, half_life=100, t=100))
print(radioactive_decay(5000, half_life=100, t=200))5000.0
3535.533905932738
2500.0
1250.0
Common Mistakes
Forgetting the Parentheses
This refers to the function:
printThis calls the function:
print()The same happens with our own functions.
greet
greet("Ana")Forgetting the Colon
Incorrect:
def greet(name)
print(f"Hello, {name}")Correct:
def greet(name):
print(f"Hello, {name}")Wrong Indentation
Incorrect:
def greet(name):
print(f"Hello, {name}")Correct:
def greet(name):
print(f"Hello, {name}")Using a Variable Outside the Function
def double(x):
result = x * 2
print(result)This fails because result was created inside the function.
A better version:
def double(x):
result = x * 2
return result
answer = double(5)
print(answer)Printing Instead of Returning
def double(x):
print(x * 2)
answer = double(5)
print(answer + 10)This fails because answer is None.
Correct version:
def double(x):
return x * 2
answer = double(5)
print(answer + 10)Summary of Argument Types
Positional Arguments
Positional arguments are matched by order.
def subtract(a, b):
return a - b
subtract(10, 3)Here, a = 10 and b = 3.
Order matters.
Keyword Arguments
Keyword arguments are matched by name.
subtract(a=10, b=3)This is clearer when a function has many arguments.
Default Values
Some arguments can have default values.
def greet(name, greeting="Hello"):
print(f"{greeting}, {name}!")If no greeting is given, Python uses "Hello".
Some More Exercises
::: {.callout-note}
Celsius to Fahrenheit
Write a function called celsius_to_fahrenheit(celsius).
Use this formula:
(F = C + 32)
The function should return the temperature in Fahrenheit.
Test it with:
02037100:::
def celsius_to_fahrenheit(celsius):
return celsius * 9 / 5 + 32
print(celsius_to_fahrenheit(0))
print(celsius_to_fahrenheit(20))
print(celsius_to_fahrenheit(37))
print(celsius_to_fahrenheit(100))32.0
68.0
98.6
212.0
Write a function called check_password(password).
It should return True if the password is "python".
Otherwise, it should return False.
Then ask the user for a password and use the function inside an if statement.
def check_password(password):
return password == "python"
password = input("Password: ")
if check_password(password):
print("Access granted")
else:
print("Incorrect password")StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.
Write a function called classify_grade(grade).
It should return:
"Fail"if the grade is below5"Pass"if the grade is from5to below7"Good"if the grade is from7to below9"Excellent"if the grade is9or higher
Then test the function with several grades.
def classify_grade(grade):
if grade < 5:
return "Fail"
elif grade < 7:
return "Pass"
elif grade < 9:
return "Good"
else:
return "Excellent"
print(classify_grade(3))
print(classify_grade(5))
print(classify_grade(8))
print(classify_grade(10))Fail
Pass
Good
Excellent
Write a function called analyze_text(text).
It should print:
- the original text
- the number of characters
- the text in uppercase
- the first character
- the last character
Example:
analyze_text("python")def analyze_text(text):
print(f"Original text: {text}")
print(f"Number of characters: {len(text)}")
print(f"Uppercase: {text.upper()}")
print(f"First character: {text[0]}")
print(f"Last character: {text[-1]}")
analyze_text("python")Original text: python
Number of characters: 6
Uppercase: PYTHON
First character: p
Last character: n
Homework and Review
When you feel ready, you can test your knowledge by working through the review exercises.
Work through the “Functions” homework exercises available here. To earn participation credit, you must complete the exercises highlighted in red.