def ma_fonction(p1, p2):
resultat = p1 * p2 + p1 + 5
return resultatFunctions
Before starting
- Download this Jupyter notebook
- Connect to the SSP Cloud
- or another platform (ENSAI Jupyter, Jupyter Lab, Google Colab, Kaggle…)
- Import the .ipynb file
1 Functions
The idea of a function is to group together pieces of code that could be used in several places in your program. Using functions is a good practice:
- it reduces code duplication
- it allows you to better structure your code and make it clearer
A function is composed of:
- a set of parameters
- instructions that use the parameters
- returns or displays a result
The def keyword is used to define a function. Here is an example of a function:
- Function name: ma_fonction
- Parameters: 2 parameters p1 and p2
- Output: result of the operation p1 x p2 + p1 + 5
Now that our function is defined, we can call it as many times as we want
ma_fonction(2, 6)ma_fonction(5, 1) + ma_fonction(8, 2)1.1 Arguments
Arguments are the parameters of the function. When we call a function by specifying arguments, we say that we “pass” arguments to it. These arguments then become variables that can only be used inside the function.
def maximum(a, b):
if a > b:
resultat = a
else:
resultat = b
return resultatmaximum(1, 5)Outside functions, arguments no longer exist and are no longer known.
aPositional arguments and keyword arguments
In Python, functions support two ways of passing arguments:
- positional arguments: arguments are passed in the order in which they were defined
- keyword arguments: the parameter name is specified when passing the argument
Let’s illustrate this difference using a function that simply performs a division.
def division(x, y):
if y == 0:
print("ERROR: Division by 0 is impossible")
else:
return x / y# Positional arguments
division(8, 2)# Keyword arguments
division(x=8, y=2)In the case of positional arguments, respecting the order is mandatory.
print(division(0, 5))
print(division(5, 0))We notice that None is displayed above. The explanation is that when we enter the if y == 0 part of the code, there is no return. Therefore, by default, the method returns None, which represents the absence of a value.
In the case of keyword arguments, the order no longer matters.
print(division(x=0, y=5))
print(division(y=5, x=0))Required arguments and optional arguments
When defining a function, it is common to want to combine:
- arguments that the user must absolutely specify
- optional arguments that specify a default behavior of the function, but can also be modified if necessary
Let’s look at how we can modify the behavior of the print function using an optional argument.
print("salut")
print("salut")print("salut", end=' ')
print("salut")We modified the behavior of the first print call using the optional parameter end. By default, this value is set to '\n', meaning a line break. We changed it in the second cell to a space, hence the difference in output.
We will now create a function with an optional argument. To explain the behavior of this method, documentation has been added between the characters """.
def note_finale(note1, note2, bonus=0) -> float:
"""Fonction d'ajout de 2 notes
Parameters
----------
note1 : float
la première note
note2 : float
la deuxième note
bonus : float
un bonus (optionnel, par défaut égal à 0)
Returns
-------
float : sommes des 2 notes et du bonus
"""
return note1 + note2 + bonus# Default behavior (bonus=0)
note_finale(8.5, 7)# Modified behavior
note_finale(8.5, 7, bonus = 2)You will also notice that the function signature ends with -> float.
This is also a non-binding documentation element. It indicates the expected data type of the output.
Bonus: variable number of arguments
- The
*argsnotation allows a function to receive a variable number of positional arguments - The
**kwargsnotation allows a function to receive a variable number of key-value arguments
# Example using args
def moyenne(*args):
somme = 0
nb = 0
for a in args:
somme += a
nb += 1
print(f"Moyenne de {args} : {somme / nb}")
moyenne(10, 15)
moyenne(8, 20, 16, 12)# Example using kwargs
def recette(**kwargs):
for a in kwargs:
# get argument name
arg_name = a
# get argument value
arg_value = kwargs[arg_name]
print(arg_name, " = ", arg_value)
recette(tomate=2, farine="100g", sel=True)1.2 Results
Principle
We have seen:
- that every function returns an output result
- that the
returnstatement is used to specify this result
When the function is called, it is evaluated to the value specified by return, and this value can then be stored in a variable and used in subsequent calculations, and so on.
def division(x, y):
return x / ya = division(4, 2)
b = division(9, 3)
division(a, b) # 2 / 3Important note: when a return statement is reached in a function, the rest of the function is not executed.
def test(x):
return x
print("will I be displayed?")
test(3)Returning multiple results
A function returns by definition one result, which can be any Python object. What should we do if we want to return several results? We can simply store the different results in a container (list, tuple, dictionary, etc.), which can itself contain a large number of objects.
def calculs_mathematiques(a, b):
somme = a + b
difference = a - b
produit = a * b
return somme, difference, produit
resultats = calculs_mathematiques(10, 5)
print(resultats)
type(resultats)By default, multiple returns are tuples. But it is also possible to return a list or a dictionary.
def puissance_liste(a):
return [a**2, a**3]
puissance_liste(4)def puissance_dico(nombre):
carre = nombre ** 2
cube = nombre ** 3
return {"carre": a**2, "cube": a**3}
puissance_dico(4)1.3 Lambda functions
There is another concise way to define a simple function: the lambda function.
carre = lambda x: x**2
carre(6)2 Exercises
2.1 Exercise 1
Create a puissance function that takes two numbers x and y as input and returns the power function \(x^y\).
# Test your answer in this cell2.2 Exercise 2
Write a statistiques_descriptives function that:
- takes a list of numbers as input
- returns the mean and variance
# Test your answer in this cell2.3 Exercise 3
Write an est_pair function that:
- takes one parameter as input
- returns a boolean indicating whether this parameter is even
Add a test to check that the parameter is an integer.
# Test your answer in this cell2.4 Exercise 4
Write a function that:
- takes a list of any elements as input
- returns a new list containing the unique elements from the initial list
- allows, through an optional parameter, to sort or not sort the final list in alphanumeric order (the default behavior is not to sort).
# Test your answer in this cell2.5 Exercise 5
Recursive functions are functions that call themselves within the body of the function, which leads to infinite calls until reaching a stopping criterion (see the Pascal triangle example below).
Implement the factorial function recursively.
def triangle_pascal(n):
if n == 0:
return [[1]] # Stopping condition
else:
triangle = triangle_pascal(n - 1) # Recursive call to obtain previous rows
prev_row = triangle[-1] # Retrieve the last generated row
new_row = [1] # First element of the new row
# Calculate the elements of the new row
for i in range(len(prev_row) - 1):
new_row.append(prev_row[i] + prev_row[i + 1])
new_row.append(1) # Last element of the new row
triangle.append(new_row) # Add the new row to the triangle
return triangle
print('\n'.join(['\t'.join(map(str, row)) for row in triangle_pascal(10)]))# Test your answer in this cell2.6 Exercise 6
Write an appliquer_fonction_liste function that:
takes as parameters:
- a list of integers
- a function
returns the list to which the function has been applied
Example:
appliquer_fonction_liste([1, 2, 3, 4], lambda x: x**2) -> [1, 4, 9, 16]
# Test your answer in this cell