print(), len(), etc.)This type of programming is called procedural or modular programming.
To write your own function, use the def operator:
Syntax:
def function_name (list of arguments):
body of the function (instructions)# A function called 'calculate_total_price' takes two arguments
def calculate_total_price(base_price, tax_rate):
total = base_price * (1 + tax_rate)
return totalA function is made of two parts:
Before using a function you will need to write it.
Once written, a function can be called (executed) by using its name followed by parenthesis:
# Function call
final_price = calculate_total_price(100, 20)# The function takes two arguments (input) in order to do its work
def calculate_total_price(base_price, tax_rate):
total = base_price * (1 + tax_rate)
return total
# 100 is copied into 'base_price' parameter, 20 is copied into 'rax_rate'
final_price = calculate_total_price(100, 20) # Returns 120.0A function always return something, usually the
result of the procedure, with a return statement. The
return statement :
print("Let's compute the final price...") # 1
final_price = calculate_total_price(150, 20) # 2 Function returns and passes control back
print(f"Final price is ${final_price:.2f}" # 3If you omit the return statement in a function (or use a
bare return with no value), the function return None
def some_procedure():
print("do stuff")
print("do stuff")
print("finished")
result = some_procedure()
print(result) # None!def some_procedure():
print("do stuff")
print("do stuff")
print("finished")
#Stops and return
return "done";
# This will never be executed!
print("do another thing")
some_procedure()Functions allow breaking down a program into multiple parts
Each function acts like a black box that exposes a service through an interface while hiding its internal details. They hide the implementation details of performing from other parts of the program.
By writing a program with functions, one can reason about the system to understand and evolve (change) it.
Using functions makes your programs easier to write, read, test, and fix.
Write a function called
display_message() that prints one sentence telling everyone
what you are learning about in this chapter. Call the function, and make
sure the message displays correctly.
Write a function called
favorite_book() that accepts one parameter,
title. The function should print a message, such as âOne of
my favorite books is Alice in Wonderlandâ. Call the
function, making sure to include a book title as an
argument in the function call.
From Prof. Karim ZKIK, PhD, Associate Professor
When calling a function, you pass values into its parameters. Python allows you to pass these values either :
def add(x, y, z):
return x + y + z
# Positional argument (implicit), order matters!
add(1, 2, 3)
# Named arguments (also called 'keywords')
add(y=2, z=1, x=3)
# Mixing
# You can combine both styles in a single function call,
# but positional arguments must always come BEFORE named arguments.
add(2, z=3, y=2)# Arbitrary number of positional arguments
def varargs(*args):
return args
varargs(1, 2, 3)
# Arbitrary number of named arguments
def keyword_args(**kwargs):
return kwargs
keyword_args(1, 2) #TypeError: keyword_args() takes 0 positional arguments but 2 were given
keyword_args(foo=1, bar=2) #{'foo': 1, 'bar': 2}In Python, functions can have default arguments, which are parameters with predefined values. This means you donât always need to pass every argument while calling a function.
Syntax:
def function_name(param1=value1, param2=value2, ...):
# function body# tax_rate as the value 20 by default
def calculate_total_price(base_price, tax_rate = 20):
total = base_price * (1 + tax_rate)
return total
# 20 is used as default value (no value provided)
final_price = calculate_total_price(100) # Returns 120.0
# 30 is provided and used instead of default value
final_price = calculate_total_price(100, 30) # Returns 130.0Rule: Non-default parameters must come before default parameters in the function definition
def swap(x, y):
# Return several values as a tuple. Could be written with parentheses: return (y, x)
return y, x
x, y = swap(1, 2)
print(x, y)Functions, like if/else block or for/while loop, has a scope.
The body of the function is a a code block, variables declared in it are local to the function: their lifecycle ends (they are destroyed) when the function returns.
x = 5
def setX(num):
# Local variable x is not the same as the global variable x (global scope)
x = num # => 43
print (x) # => 43
return # local x is destroyed and no longer exists
setX(43)
print(x) # 5Write a function called
make_shirt() that accepts a size and the text of a message
that should be printed on the shirt. The function should print a
sentence summarizing the size of the shirt and the message printed on
it. Call the function once using positional
arguments to make a shirt. Call the function a
second time using keyword arguments.
Modify the make_shirt() function so
that shirts are large by default with a message that reads âI love Monty
Pythonâ. Make a large shirt and a medium shirt with the default message,
and a shirt of any size with a different message.
Write a function called
describe_city() that accepts the name of a city and its
country. The function should return a simple sentence,
such as âReykjavik is in Icelandâ. Give the parameter
for the country a default value. Call your function for
three different cities, at least one of which is not in the default
country, and store each sentance in a list.
Print all sentances.
From Prof. Karim ZKIK, PhD, Associate Professor
def display_message():
print("I'am learning how and why to write functions in Python")
display_message()
def favorite_book(title):
print(f"One of my favorite books is {title.title()}")
favorite_book("Comment parler des livres que l'on a pas lu ?")def make_shirt(size="L", text="I love Monty Python!"):
print(f"Size: {size} Text: '{text}'")
make_shirt('M', "Best boss")
make_shirt(size='M',text="Best boss")
make_shirt('M')
make_shirt()
make_shirt(text="Stupid", size="S")
def describe_city(name, country="France"):
return f"{name.title()} is in {country.title()}"
descriptions = [describe_city("Paris"), describe_city("London", "England"), describe_city("Pnom Penh", "Cambodia")]
for desc in descriptions:
print(desc)It is recommended to use the infinitive form in English. A
function acts, it manipulates and transforms data. A
verb is therefore a good choice for a function name. For
example, search, create_new_game, or
remove_vowels are very good choices.
It is also important to name arguments well so that the user of
your function easily understands what they correspond to. Never
use single-character names like a or
i, unless the functionâs purpose is completely obvious.
Today we have auto-completion tools, so we have no
excuse for not using long yet meaningful names for our variables
and functions!
The more arguments a function accepts, the higher its arity increases, making it harder to remember the order in which to provide their values and what each argument is used for. This adds complexity and requires extra mental effort from the person using it. You must therefore define and name a functionâs arguments carefully to provide the simplest possible signature for the problem it is meant to solve.
A bug is the difference between expected/assumed behavior (in your head) and actual/real behavior of the program.
It is a mismatch or an expectation-reality gap.
It results in a defect or fault in the program.
Moth found trapped between points at Relay #70, Panel F, of the Mark II Aiken Relay Calculator while it was being tested at Harvard University, 9 September 1947.
But, is this legend true? In 1878, Edison wrote about âBugs as being little faults and difficultiesâ
âEveryone knows that debugging is twice as hard as writing a program in the first place. So if youâre as clever as you can be when you write it, how will you ever debug it?â Brian W. Kernighan
Debugging is the process of finding, analyzing, and removing errors (or âbugsâ) in a computer program so that it runs correctly (as expected).
Simple bugs:
How to debug: Read the error messages thrown by the interpreter and fix accordingly.
def sum(*numbers):
sum = 0
for x in numbers
sum += x
return sum
sum(1,2,3)Error:
File "...program.py", line 5
for x in numbers
^
SyntaxError: expected ':'SyntaxError, expected â:â. I forgot a
semicolon!Harder bugs:
âThe most effective debugging tool is still careful thought, coupled with judiciously placed print statements.â Brian W. Kernighan
Here is a small program with bugs, supposed to calculate the average of grades that are greater than or equal to 10/20 from a list.
Debug this code.
grades = [12, 8, 15, 17, 9, 14]
def compute_average(grades)
total = 0
count = 0
for grade in grades:
if grade <= 10:
total = total + grade
count = count + 1
average = total / grade
return average
result = compute_average(grades)
print("Average of notes greater or equal than 10 : " + result)Key takeaway: Donât use GenAI to write code for you! Use it as a learning assistant to explore concepts and enhance your skills.
Solve the following problems of the problem sheet:
While inserting print() statements works for simple
programs, it can become inefficient for complex or larger
applications.
Step-debugging lets you pause code execution, inspect memory states in real time, step through instructions line-by-line, and alter variables on the fly.
Python comes with a built-in interactive
debugger called pdb. It requires no external
installations and works directly in any terminal.
You can create breakpoints to jump from to one point and pause the execution
# Import debugger
# pdb.set_trace() hardcodes a breakpoint directly into the code
import pdb; pdb.set_trace()
def calculate_total(prices, tax_rate):
subtotal = sum(prices)
breakpoint() # Execution pauses here; drops you into the pdb shell
total = subtotal * (1 + tax_rate)
return total
calculate_total([10, 20, 30], 0.05)Copy/paste the code and type the following commands in the interactive debug session:
l: to see where you are, c: to continue to
next breakpoint, p subtotal: to print the content of the
variable, n: next instruction and then
exit