Leçons du module (2/4)
Paramètres par défaut et nommés
Les paramètres des fonctions peuvent avoir des valeurs par défaut : si l'appelant ne les passe pas, les valeurs par défaut sont utilisées. Vous pouvez également appeler une fonction en passant des paramètres par nom (arguments nommés ou keyword arguments).
Paramètres par défaut
def saluta(nome, saluto="Ciao"):
return f"{saluto}, {nome}!"
saluta("Ada") # 'Ciao, Ada!'
saluta("Ada", "Hello") # 'Hello, Ada!'Les paramètres avec valeurs par défaut doivent venir après ceux sans :
def f(a, b=1): # OK
def f(a=1, b): # SyntaxErrorArguments nommés
Vous pouvez passer des arguments par nom, dans n'importe quel ordre, ce qui rend l'appel plus lisible :
def crea_utente(nome, eta, attivo=True):
return {"nome": nome, "eta": eta, "attivo": attivo}
crea_utente("Ada", 36)
crea_utente(nome="Ada", eta=36, attivo=False)
crea_utente(eta=36, nome="Ada") # any order when all are keywordRègle d'or : dans un appel, les arguments positionnels viennent AVANT les arguments nommés.
crea_utente("Ada", eta=36) # OK
crea_utente(nome="Ada", 36) # SyntaxError⚠️ Le piège du paramètre par défaut mutable
NE JAMAIS utiliser d'objet mutable (liste, dictionnaire, ensemble) comme valeur par défaut : la valeur par défaut est évaluée UNE SEULE FOIS, lors de la définition de la fonction, et partagée entre tous les appels.
def aggiungi(elemento, lista=[]): # BUG!
lista.append(elemento)
return lista
aggiungi(1) # [1]
aggiungi(2) # [1, 2] !!! not [2] as you'd expect
aggiungi(3) # [1, 2, 3]Le modèle correct : utiliser None comme sentinelle et le créer à l'intérieur :
def aggiungi(elemento, lista=None):
if lista is None:
lista = []
lista.append(elemento)
return listaLe danger des arguments par défaut mutables
N'utilisez jamais d'objets mutables (comme des listes ou des dictionnaires) comme valeurs par défaut pour les paramètres : par exemple def add(x, my_list=[]). La valeur par défaut n'est évaluée qu'une seule fois lors de la définition de la fonction, ce qui signifie que les appels ultérieurs partageront exactement le même objet mutable ! La meilleure pratique consiste à utiliser None :
def add(x, my_list=None):
if my_list is None:
my_list = []
my_list.append(x)
return my_listÀ vous de jouer
Définissez `power(base, exponent=2)` qui renvoie base ** exponent. Calculez `square = power(5)` et `cube = power(5, exponent=3)`. Évaluez `(square, cube)`.
Afficher l'indice
return base ** exponent
Solution disponible après 3 tentatives
Exercice de révision
Définissez `create_record(name, values=None)` qui, lorsque values vaut None, utilise un nouvelle liste vide. Ajoutez 1 à values et renvoyez le dictionnaire de l'enregistrement {'name': name, 'values': values}. Appelez-la deux fois sans passer values et attribuez à `a` et `b`. Évaluez `(a['values'], b['values'])`.
Afficher l'indice
Utilisez None comme valeur par défaut et créez la liste à l'intérieur de la fonction.
Solution disponible après 3 tentatives
Défi supplémentaire
Définissez une fonction `greet(name, message="Hello")` qui renvoie la chaîne formatée `"{message}, {name}!"`. Testez la fonction en appelant `greet("Bob")` comme dernière expression.
Afficher l'indice
Utilisez un paramètre par défaut message="Hello" et une f-string pour le salut renvoyé.
Solution disponible après 3 tentatives