Aller au contenu

Fonctions

Lors de l’écriture d’un programme, particulièrement lorsqu’on travaille à plusieurs sur un projet, il est naturel et recommandé de décomposer le problème global en différents sous-problèmes, chaque sous- problèmes étant plus facile à résoudre. La finalisation du travail consistera à agencer tous ces sous- problèmes les uns avec les autres.

De plus, il est fréquent qu’une séquence d’instructions particulières soit utilisée plusieurs fois. Il serait très préjudiciable en terme de clarté et de structure du programme de recopier l’intégralité de ces instructions.

Une fonction permet de regrouper une série d'instructions, ce qui facilite la compréhension du code. Le mot clé def est utilisé pour définir des fonctions en Python.

   def ma_fonction():
      print("La NSI c'est fantastique, non ?")

Attention

On vient de définir la fonction mais on ne l'a pas encore appelée. Pour l'exécuter il faut la nommer et passer les arguments requis.

Valeurs retournées

Par défaut une fonction en Python retournera None. Donc, même si cette fonction affiche une chaîne de caractère, elle ne renvoie pas une chaîne de caractère, elle retourne None.

Question

Quelle sera la valeur retournée par la fonction ma_fonction ?

Une fonction peut retourner une ou plusieurs valeurs. Lorsqu'une fonction retourne une valeur elle n'affiche rien. Si on souhaite afficher les valeurs retournées il faut utiliser la fonction print.

Questions

  • Qu'affiche le code ci-dessous ?
      def carre(n):
          return n**2
    
      print(carre(8))
    

On peut déclarer des variables en dehors des fonctions, ces variables seront accessibles à l'intérieur des fonctions (définies dans le même fichier).

Questions

  • Que se passe t'il si on exécute le code ci-dessous ?
  • Quel peut être l'inconvénient d'utiliser une variable globale de cette manière ?
    pays = 'France'
    def carre(n):
          print(pays)
          return n**2
    
    carre(8)
    

Il peut y avoir plus return, mais un seul sera exécuté.

def bonjour_binaire(genre):
    if genre == "M":
        return "Bonjour monsieur"
    elif genre == "F":
        return "Bonjour madame"

# appel
bonjour_binaire("F")

Paramètres et arguments

On peut ajouter un ou des paramètres lors de la définition d'une fonction :

  def ma_fonction_coucou(nom):
     print("Coucou ", nom)
Ici, on vient d'ajouter un paramètre nom. Lorsque l'on appelle la fonction ma_function_coucou on passe la valeur en argument :

  ma_fonction_coucou('John')

Ici 'John' est un argument de la fonction ma_function_coucou.

Portée des variables

Il est très important de distinguer les variables globales et les variables locales.

Les variables déclarées dans une fonction sont effacées à la fin de la fonction. On dit que ce sont des variables locales. Il est donc impossible d'utiliser ces variables déclarées en dehors de la fonction elle- même.

Question

Que se passe t'il d'après vous si on exécute le code ci-dessous ?

def ma_function_carre(x):
   x = x**2
   return x

print(x)

Prototype et documentation

Le prototype doit décrire le rôle de la fonction, le type des paramètres et le type de la valeur de retour. Ces informations sont communément appelées le prototype de la fonction.

def somme(a, b):
    """La somme de deux nombres.

    Renvoie la somme des deux nombres donnés en arguments

    Paramètres
    ----------
    a : int
        première valeur à ajouter
    b : int
        deuxième valeur à ajouter

    Renvoie
    -------
    int
        La somme des deux arguments de la fonction
    """
    return a + b

Maintenant, en tapant help(somme), vous aurez toutes les informations utilise pour utiliser la fonction.

help(somme)

Help on function somme in module __main__:

somme(a, b)
    La somme de deux nombres.

Renvoie la somme des deux nombres donnés en arguments

Paramètres
----------
a : int
    première valeur à ajouter
b : int
    deuxième valeur à ajouter

Renvoie
-------
int
    La somme des deux arguments de la fonction

Notez tout de même qu’en Python, il n’est pas nécessaire de préciser le type des paramètres ni le type de la variable retournée (typage dynamique).

Il est d’usage de documenter ses fonctions juste après la définition de celles-ci. On peut être un peu plus rigoureux sur le format de cette documentation. Pour de plus amples détails, vous pouvez consulter cette page https://peps.python.org/pep-0008/.

Préconditions et postconditions

On peut vouloir vérifier que des conditions qui sont sensées être satisfaites le sont effectivement, à l’aide du mécanisme d’assertion proposé par le langage Python. Prenons un exemple :

Dans cet exemple, trois instructions assert ont été utilisées pour vérifier les préconditions. Une telle instruction se compose d’une condition (une expression booléenne) éventuellement suivie d’une virgule et d’une phrase en langage naturel sous forme de chaîne de caractères.

L’instruction assert teste si la condition est satisfaite :

  • Si c’est le cas, elle ne fait rien
  • Sinon, elle arrête immédiatement l’exécution du programme en affichant une erreur AssertionError et éventuellement le texte associé.

De la même manière, on peut utiliser les assertions pour vérifier des conditions sur la valeur à retourner par la fonction ; on parle de postconditions. La syntaxe est la même, et on testera ces postconditions juste avant le return.

Tests d'assertion

Pour être sûr que notre fonction donne les bons résultats, on utilise des tests d’assertion (affirmation en anglais) qui renvoient une AssertionError en cas d’erreur.

assert somme(1, 2) == 3
assert somme(0, 0) == 0
assert somme(10, -2) == 8

Il est extrêmement important de bien tester son code, cela permet entre autres au développeur de s'assurer (un minimum) de bien avoir le résultat attendu.

Nous verrons par la suite comment on peut tester son code en Python de manière plus approfondie.

Programmation fonctionnelle

Même si on peut voir certaines similitudes entre les fonctions Python et les fonctions mathématiques, les fonctions Python permettent une souplesse plus importante, par exemple on peut modifier des variables en dehors de la portée locale de la fonction (on parle d'effet de bord). Certains langages de programmation dits fonctionnels comme OCaml ou Haskell (surtout Haskell) utilisent des fonctions qui se rapprochent davantage des fonctions mathématiques.

Nous reviendrons sur ce point en Terminale.