Prérequis : bases de Python vues en première (variables, boucles, conditions)
À l’issue de ce chapitre, vous saurez :
global ;*args et **kwargs pour un nombre variable de paramètres ;assert et documenter les fonctions avec des docstrings.Les fonctions sont un moyen efficace de structurer un programme et de l’organiser en modules. Le
choix du nom d’une fonction est important pour la lisibilité du programme. En Python, une fonction
est définie à l’aide du mot-clé def.
def ma_fonction():
print("Les fonctions en Python sont faciles à apprendre")
ma_fonction()
Les fonctions en Python sont faciles à apprendre
À noter que l’appel s’effectue par ma_fonction() au lieu de print(ma_fonction()) car ma_fonction affiche son message avec la fonction print au lieu de renvoyer une valeur avec l’instruction return.
Lorsqu’une nouvelle variable est affectée à l’intérieur du corps de la fonction, elle n’est définie qu’à l’intérieur de la fonction. La variable n’est pas visible en dehors de la fonction. Nous pouvons donc choisir n’importe quel nom lors de la définition des variables sans nous soucier des variables extérieures à la fonction.
Par exemple :
x = 10 # x est une variable globale
y = 10 # y aussi
def une_fonction():
x = 5 # x est une variable locale
global y # Ceci permet de modifier la valeur de la variable globale y
y = 5
print(x)
print(y)
une_fonction()
print(x)
print(y)
10
10
10
5
La variable x ne change pas en dehors de la fonction puisque la portée de x définie à l’intérieur de
la fonction est limitée à la fonction elle-même. Seul le mot-clé global permet de réaffecter une variable globale (y = 5). En revanche, une liste ou un dictionnaire global peut être modifié en place sans global, par exemple avec L.append(3) ou d[cle] = valeur.
À ce sujet, voir cette vidéo :
Les paramètres, sont utilisés pour transmettre des informations dans une fonction.
Soit la fonction fraction suivante :
def fraction(numerateur, denominateur):
print(f"{numerateur}/{denominateur}")
Il existe plusieurs façons de passer les paramètres :
Dans la fonction fraction, les paramètres numerateur et denominateur sont appelés paramètres
positionnels (en anglais positional arguments). Il est strictement obligatoire de les préciser lors
de l’appel de la fonction. De plus, il est nécessaire de respecter le même ordre lors de l’appel que
dans la définition de la fonction. Dans l’exemple ci-dessous, 10 correspond à numerateur et 4
correspond à denominateur.
fraction(10, 4)
10/4
On peut aussi nommer explicitement les paramètres lors de l’appel, en écrivant nom_du_parametre=valeur : on parle
d’arguments nommés (en anglais keyword arguments). Les paramètres peuvent alors être passés dans n’importe quel
ordre. Cette possibilité ne dépend pas de la définition de la fonction : elle vaut pour tous les paramètres, comme
ici pour numerateur et denominateur, qui n’ont pas de valeur par défaut.
fraction(numerateur=10, denominateur=4)
fraction(denominateur=4, numerateur=10)
10/4
10/4
Il est possible de préciser des valeurs par défaut pour certains paramètres. Comme leur nom l’indique, ces valeurs seront utilisées par défaut lors d’un appel à la fonction si aucune valeur effective (si aucun paramètre) n’est passée à la place.
Utiliser des valeurs par défaut pour les paramètres de fonctions permet donc aux utilisateurs d’appeler cette fonction en omettant de passer les paramètres possédant des valeurs par défaut.
def presentation(prenom, age=15, ville="Lyon"):
print(
f"Je m'appelle {prenom}, j'ai au moins {age} ans et j'habite à {ville}."
)
presentation("Gaudric")
presentation("Faustin", 19)
presentation("Justine", 21, "Paris")
presentation("Audrey", ville="Toulouse")
presentation(age=20, ville="Strasbourg", prenom="Augustin")
Je m'appelle Gaudric, j'ai au moins 15 ans et j'habite à Lyon.
Je m'appelle Faustin, j'ai au moins 19 ans et j'habite à Lyon.
Je m'appelle Justine, j'ai au moins 21 ans et j'habite à Paris.
Je m'appelle Audrey, j'ai au moins 15 ans et j'habite à Toulouse.
Je m'appelle Augustin, j'ai au moins 20 ans et j'habite à Strasbourg.
Complément hors programme. Les syntaxes *args et **kwargs ne sont pas exigibles au baccalauréat, mais on les rencontre dans la documentation des bibliothèques.
La syntaxe *args (remplacez args par ce que vous voulez) permet d’indiquer lors de la définition
d’une fonction qu’elle peut accepter un nombre variable de paramètres. Ces paramètres sont
intégrés dans un tuple. On va pouvoir préciser zéro, un ou plusieurs paramètres classiques dans la
définition de la fonction avant la partie variable.
def aire_rectangle(*args):
if len(args) == 2:
return args[0] * args[1]
else:
print("Merci de stipuler deux paramètres")
print(aire_rectangle(3, 8))
24
De façon alternative, la syntaxe **kwargs (on peut remplacer kwargs par ce que l’on veut) permet
également d’indiquer que la fonction peut recevoir un nombre variable de paramètres mais cette
fois-ci les paramètres sont passés nommés (par exemple cote1=4) et la fonction les reçoit regroupés dans un dictionnaire Python.
def aire_rectangle2(**kwargs):
if len(kwargs) == 2:
result = 1
for key, value in kwargs.items():
result *= value
return result
else:
print("Merci de stipuler deux paramètres")
print(aire_rectangle2(cote1=4, cote2=8))
32
Les syntaxes *args et **kwargs peuvent être utilisées pour réaliser les opérations inverse de celles
présentés ci-dessus, à savoir séparer des données composites pour passer les valeurs ou éléments de
ces données un à un en paramètres des fonctions. On, utilisera la syntaxe *args pour séparer les
paramètres présents dans une liste ou un tuple et la syntaxe **kwargs pour séparer les paramètres
présents dans un dictionnaire et fournir des paramètres nommés à une fonction.
def somme(a, b, c):
s = a + b + c
print(s)
ma_liste = [1, 2, 3]
# somme(ma_liste) # Erreur car la somme attend trois paramètres
somme(*ma_liste)
mon_dico = {'a': 1, 'b': 2, 'c': 3}
somme(**mon_dico)
6
6
La même décomposition s’applique à la fonction fraction : le tuple, la liste ou le dictionnaire fournit les
valeurs des paramètres.
fraction(*(10, 4))
fraction(*[10, 4])
fraction(**{'numerateur': 10, 'denominateur': 4})
10/4
10/4
10/4
On peut également passer une fonction comme paramètre. Par exemple, on peut passer la fonction
intégrée len() ou une fonction définie par l’utilisateur voyelle_presente() comme paramètre à une
autre fonction :
phrase = ['Les', 'fonctions', 'Python', 'sont', 'formidables']
def appliquer_fonction(prop):
return [prop(mot) for mot in phrase]
print(appliquer_fonction(len))
def voyelle_presente(mot):
for x in mot:
if x in 'aeiouy':
return True
return False
print(appliquer_fonction(voyelle_presente))
[True, True, True, True, True]
None et le test is NoneUne fonction qui se termine sans return renvoie la valeur spéciale None, qui signifie « aucune valeur ». On utilise aussi None pour indiquer qu’une variable ne désigne encore rien : par exemple, une variable meilleur qui ne désigne encore aucun élève avant le parcours d’une liste d’élèves.
Pour tester si une valeur vaut None, on écrit x is None, ou x is not None, plutôt que x == None : is vérifie qu’il s’agit exactement de l’objet None.
None et le test is None (suite)def chercher(liste, valeur):
"""Renvoie l'indice de valeur dans liste, ou None si elle n'y est pas."""
for i in range(len(liste)):
if liste[i] == valeur:
return i
return None
resultat = chercher([4, 8, 15], 8)
if resultat is not None:
print(f"Trouvé à l'indice {resultat}") # Trouvé à l'indice 1
print(chercher([4, 8, 15], 3) is None) # True
On réserve is à ce test. Pour comparer deux valeurs, on utilise toujours ==.
Python n’oblige pas à spécifier le type des paramètres d’une fonction. Il est donc nécessaire de vérifier le type de variable d’entrée avant d’exécuter la fonction.
def est_une_voyelle(lettre):
if lettre in 'aeiouy':
return True
return False
print(est_une_voyelle("poire"))
False
Pour éviter l’exécution et générer une erreur, on peut utiliser l’instruction assert. Le code ci-dessous
utilise aussi la fonction isinstance(v, T), qui renvoie True si la valeur v est de type T, False sinon : par
exemple, isinstance("a", str) vaut True et isinstance(3, str) vaut False.
def est_une_voyelle(lettre):
assert (isinstance(lettre, str)), "La lettre doit être un caractère"
assert (len(lettre) == 1), "La longueur de la lettre doit être de un !"
if lettre in 'aeiouy':
return True
return False
print(est_une_voyelle("f"))
print(est_une_voyelle("poire"))
False
AssertionError: La longueur de la lettre doit être de un !
Si l’instruction assert échoue, elle produit une erreur, affiche le mesage correspondant et la
fonction arrête l’exécution.
Il est recommandé de documenter les fonctions : pour cela on utilise une docstring.
def est_une_voyelle(lettre):
'''Prend en paramètre une chaîne de caractères de longueur un et retourne True si c'est une voyelle et False si ce n'est pas la cas'''
assert (isinstance(lettre, str)), "La lettre doit être un caractère"
assert (len(lettre) == 1), "La longueur de la lettre doit être de un!"
if lettre in 'aeiouy':
return True
return False
La docstring de n’importe quelle fonction peut être affichée en exécutant la fonction help.
help(est_une_voyelle)
Help on function est_une_voyelle in module __main__:
est_une_voyelle(lettre)
Prend en paramètre une chaîne de caractères de longueur un et retourne True si c'est une voyelle et False si ce n'est pas la cas
return et print dans une fonction ?
return renvoie une valeur que le programme peut utiliser (stocker dans une variable, passer à une autre fonction, etc.) et met fin à l'exécution de la fonction. print affiche simplement un texte à l'écran sans renvoyer de valeur exploitable (la fonction renvoie alors None).x (par exemple x = 5) à l’intérieur d’une fonction sans utiliser global ?
x n'est pas modifiée. C'est la portée locale : les variables définies dans une fonction ne sont pas visibles à l'extérieur. En revanche, x = x + 1 provoque l'erreur UnboundLocalError : la variable locale x est utilisée avant d'avoir reçu une valeur.assert pour vérifier les paramètres d’une fonction ?
def et renvoie une valeur avec return.global permet de réaffecter une variable extérieure (à éviter dans la mesure du possible), alors qu’une liste ou un dictionnaire global peut être modifié en place sans global.*args et **kwargs permettent un nombre variable de paramètres.help()).Elle peut également être affichée à l’aide de l’attribut __doc__.
print(est_une_voyelle.__doc__)
Prend en paramètre une chaîne de caractères de longueur un et retourne True si c'est une voyelle et False si ce n'est pas la cas