Fonctions et structure du code
Introduction :
Les fonctions sont des entités très utiles et très répandues en informatique. Elles sont utilisables dans la plupart des langages informatiques et correspondent même à un style de programmation. Nous allons apprendre à définir et à utiliser des fonctions, puis à les paramétrer de différentes manières. Nous découvrirons ensuite les spécifications fonctionnelles ainsi que les bibliothèques de fonctions.
Définition et appel de fonctions
Définition et appel de fonctions
Nous allons dans un premier temps préciser le concept de fonction en sciences numériques et les différents types de fonctions. Nous verrons ensuite comment définir et utiliser une fonction.
Concept de fonction en informatique
Concept de fonction en informatique
En sciences numériques, une fonction est assez proche d'une fonction au sens mathématique du terme.
Fonction :
Une fonction est une portion de code informatique nommée, qui accomplit une tâche spécifique.
Les fonctions reçoivent généralement des données en entrée et retournent généralement en sortie le résultat du traitement opéré par la fonction.
Il est possible de créer et d'utiliser des fonctions dépourvues de paramètres d'entrée. Le langage Python permet également de créer des fonctions qui ne retournent rien mais exécutent ainsi des procédures de manière isolée et potentiellement répétée.
Types de fonctions
Types de fonctions
On distingue deux types de fonctions : les fonctions natives et les fonctions créées par l'utilisateur.
Fonction native :
Les fonctions natives sont des fonctions préprogrammées mises à la disposition du programmeur par les auteurs du langage.
Il est possible d'étendre les possibilités initiales du langage en créant des fonctions spécifiques pour répondre à des besoins particuliers.
Fonction définie par l'utilisateur :
Les fonctions définies par l'utilisateur sont des fonctions ajoutées par le programmeur aux fonctionnalités préprogrammées du langage.
Une fonction native est prête à l'emploi, tandis qu'une fonction définie par l'utilisateur doit d'abord faire l'objet d'une déclaration pour la définir.
Intérêt des fonctions
Intérêt des fonctions
Les fonctions définies par l'utilisateur permettent d'enrichir le langage. L’emploi de fonctions permet de décomposer des tâches complexes en tâches élémentaires plus simples. Les fonctions présentent également l'intérêt de pouvoir être appelées plusieurs fois, ce qui évite de répéter des portions de code et facilite leur évolution ultérieure.
Modalités de définition d'une fonction
Modalités de définition d'une fonction
Dans son expression la plus simple, une fonction consiste en une ligne de définition suivie par le bloc de code correspondant à cette fonction.
Le mot-clé « def » indique à Python qu'une fonction va être définie. Ce mot-clé est suivi du nom de la fonction, de parenthèses pouvant éventuellement contenir des paramètres, et du signe « : ».
Le corps de la fonction suit immédiatement sous la forme d'un bloc de code indenté, c’est-à-dire dont la marge à gauche des lignes d’instruction se trouve supérieure à celle de la ligne qui introduit la définition de la fonction elle-même.
On veillera à choisir des noms de fonctions évocateurs de ce qu'elles réalisent, afin de faciliter la lecture du programme.
Dans cette exemple, la fonction porte un nom évocateur. On observe qu'elle retourne un résultat, ici, la chaîne de caractères « Bonjour ».
Voyons maintenant comment utiliser cette fonction.
Modalités d'appel d'une fonction
Modalités d'appel d'une fonction
L'appel d'une fonction s'effectue en indiquant son nom suivi des parenthèses ouvrantes et fermantes, ces dernières pouvant optionnellement contenir des valeurs comme nous le verrons par la suite.
On peut aussi stocker le résultat d'une fonction dans une variable :
Si on omet les parenthèses après le nom d'une fonction, Python ne retourne pas le résultat de la fonction mais son adresse mémoire, c’est-à-dire l’endroit, dans la mémoire de l’ordinateur, où se trouve le début du code machine de la fonction :
Les deux fonctions étudiées jusqu'à présent (« bonjour » et « fonction_elementaire ») ne comportaient aucun paramètre. Le paramétrage des fonctions étend grandement leur intérêt, comme nous allons le découvrir maintenant.
Paramétrage des fonctions
Paramétrage des fonctions
La définition de fonction peut inclure des paramètres qui seront utilisables au sein de la fonction.
Principe du paramétrage des fonctions
Principe du paramétrage des fonctions
Les paramètres de la fonction sont indiqués entre parenthèses à la suite de son nom dans la ligne de définition de la fonction.
Le paramètre nom est une variable qui existe uniquement au sein de la fonction et le temps de l'exécution de celle-ci. La variable message est locale à la fonction, elle n'existe pas hors de celle-ci. Cette variable contient le résultat de la concaténation, c'est-à-dire de l'assemblage des deux chaînes de caractères.
On aurait pu directement retourner la chaîne concaténée sans l'étape intermédiaire d'affectation à une variable locale, mais la séparation des deux actions facilite la compréhension du code de la fonction.
L'appel de la fonction bonjour() modifiée s'effectue de la manière suivante :
Si une fonction comporte un paramètre dans sa définition, un argument doit être renseigné dans l’instruction d’appel de la fonction. Dans le cas contraire une erreur est générée.
Une fonction peut être définie avec plusieurs paramètres et donc recevoir plusieurs arguments.
Arguments multiples
Arguments multiples
Faisons évoluer notre fonction pour qu'elle soit capable de dire « bonjour » dans plusieurs langues. Nous ajoutons un paramètre langue dans la définition de la fonction et nous ajoutons dans le corps de celle-ci une série de tests conditionnels.
Si la langue demandée n'est pas spécifiquement reconnue comme étant le français, l’anglais ou l’italien, c'est l'espéranto qui est choisi par notre fonction bonjour(), grâce à la condition « else » qui traite tous les cas autres que ceux prévus par les « if » et « elif ».
En Python :
- le symbole d'égalité simple (=) est une affectation ;
- le symbole double (==) effectue la comparaison d'une possible égalité qui vaut True si l'égalité est vraie et False sinon.
Les exemples ci-dessous illustrent le résultat produit par notre fonction pour différentes valeurs d'arguments.
On remarque que la « zorglangue » n’étant pas reconnue par la fonction, la réponse est affichée en espéranto.
Comme nous n'avons pas prévu l'emploi de majuscules, notre fonction répondrait aussi en espéranto si on lui indiquait « English » ou « ENGLISH » car ces chaines de caractères ne sont pas strictement identiques à « english » écrit tout en minuscules.
Valeurs par défaut
Valeurs par défaut
Nous avons imaginé notre fonction multilingue mais nous nous rendons compte à l'usage que nos messages sont la plupart du temps en français. Toutefois notre fonction ne nous permet pas actuellement d'omettre la langue.
Nous allons donc faire évoluer notre fonction pour préciser la langue uniquement si elle est autre que le français.
Le corps de la fonction n’a pas changé : nous avons seulement précisé une valeur par défaut pour le paramètre langue dans la ligne de définition de la fonction, c’est-à-dire une valeur prise par le programme lorsqu’elle n’est pas explicitement fournie.
Vérifions que notre fonction ainsi modifiée produit bien le résultat attendu :
Nous allons à nouveau faire évoluer notre fonction, en précisant également une valeur par défaut pour le nom : s'il n'est pas spécifié, on le nommera de manière générique « visiteur ».
On notera à nouveau que le corps de la fonction n'a pas été modifié. Vérifions à présent le comportement de notre fonction après modification de son paramétrage.
Quand une fonction est définie avec des valeurs de paramètres par défaut, il devient possible de les omettre lors de l’appel. Il est également possible de les inclure nommément dans l'appel de la fonction.
Le nommage des paramètres en arguments permet de s'affranchir de l'ordre dans lequel ils sont définis par la fonction.
On préférera toutefois respecter l'ordre de définition afin de faciliter l'analyse du code (par soi-même ou par un tiers) plus tard. La documentation des fonctions présente le paramétrage dans l'ordre de définition.
Il est également possible de définir des fonctions contenant à la fois des paramètres sans valeur par défaut et des paramètres avec des valeurs par défaut.
Paramètres avec et sans valeurs par défaut
Paramètres avec et sans valeurs par défaut
Si une fonction comporte à la fois des paramètres sans et avec valeur par défaut, les paramètres sans valeur par défaut doivent impérativement précéder ceux disposant de valeurs par défaut dans la définition de la fonction.
De même, pour l'appel de la fonction, les arguments positionnels nécessitant obligatoirement des valeurs, doivent précéder les arguments optionnels correspondant aux paramètres dotés de valeurs par défaut.
Nous avons constaté que des erreurs d'exécution de nos fonctions pouvaient survenir dans certaines conditions. C'est notamment le cas si nous ne fournissons pas le nombre de paramètre requis, ou si nous fournissons des données inattendues par leur contenu ou par leur nature.
On comprend aisément qu'il n'est pas possible de calculer la racine carrée d'une chaine de caractère. De même, un booléen n'a pas de longueur. Si elles ne sont pas employées dans le contexte prévu, nos fonctions peuvent générer toutes sortes de problèmes et d'erreurs.
Spécifications fonctionnelles
Spécifications fonctionnelles
Il est possible et souhaitable de définir précisément les conditions d'emploi de nos fonctions. Ces conditions peuvent concerner les entrées et les sorties de nos fonctions.
Préconditions et postconditions
Préconditions et postconditions
Les préconditions correspondent aux prérequis d'emploi d'une fonction. Corollairement, les postconditions concernent ce qui est attendu des résultats retournés par une fonction.
Pour notre fonction
nous pouvons définir des préconditions selon lesquelles les paramètres doivent être de type chaine de caractères et non vides.Nous pouvons intégrer des vérifications de nos spécifications dans le corps de notre fonction de différentes manières. L'emploi d'assertions peut nous aider dans ce contexte.
Assertions
Assertions
Le mot clé « assert » du langage Python nous permet de tester si une condition est vraie et de générer une erreur dans le cas contraire.
Vous pourrez constater le déclenchement d'une erreur d'assertion « AssertionError » si vous appelez la fonction des arguments autres que des chaînes de caractères, ou si une chaîne de caractères vide est passée en argument pour l’un ou l’autre des deux paramètres.
Nous pourrions de la même manière évaluer des postconditions s’assurant que le message est de longueur non nulle et qu’il contient bien le nom du visiteur quand il est spécifié.
Documentation des fonctions
Documentation des fonctions
Il est possible et souhaitable de documenter ses fonctions. Cela consiste à inclure dans la définition de la fonction une chaîne de caractères qui présente synthétiquement la fonction, ses paramètres et les résultats qu'elle produit en retour.
Cette chaîne de caractères, appelée « docstring » en anglais, se présente sous la forme d'une chaîne de caractères multilignes entourée de guillemets triplés. Cette docstring est placée immédiatement après la ligne de définition de la fonction.
Ainsi placée, notre docstring permet à Python d'afficher avec help le message d'aide de notre fonction exactement comme pour les fonctions natives du langage. Ainsi, à la console, en tapant : help(bonjour), on obtient :
Les spécifications et la documentation des fonctions contribuent à produire un code informatique de qualité. On s'appuiera également sur l'emploi de jeux de tests qui font l'objet d'un cours séparé.
Pour faciliter leur réemploi, les fonctions peuvent être regroupées sous forme de bibliothèques spécialisées.
Bibliothèques
Bibliothèques
Les bibliothèques sont des conteneurs permettant d'étendre les fonctionnalités initiales du langage, en apportant des outils supplémentaires en fonction des besoins.
Importation d'une bibliothèque
Importation d'une bibliothèque
Le langage Python inclut en standard, un grand nombre de modules spécialisés qui composent sa bibliothèque standard.
- En langage informatique, une bibliothèque est un ensemble de modules, c’est-à-dire un fichier de code, étant regroupées et mises à disposition, afin de ne pas les réécrire à chaque fois.
L'importation d'un tel module s'effectue avec l'instruction « import ». Cette opération ouvre l'accès aux éléments contenus dans ce module.
Le module nommé csv est une bibliothèque dédiée aux traitements des fichiers au format ouvert csv, dont les données tabulaires sont séparées par des virgules ou des points-virgules.
Son importation s'effectue avec l'instruction "import".
Si la bibliothèque souhaitée ne fait pas partie de la bibliothèque standard de Python, elle devra être installée séparément. Il sera ensuite possible de l'importer comme n'importe quelle autre bibliothèque.
Accès à la documentation d'une bibliothèque
Accès à la documentation d'une bibliothèque
Il est essentiel de savoir utiliser la documentation des bibliothèques pour pouvoir mettre en œuvre correctement les fonctions et d’autres éléments qu'elles peuvent contenir.
La documentation officielle disponible en ligne présente le contenu des différents modules et le fonctionnement des éléments de ces modules.
L'aide du module csv est disponible en ligne en français à l'adresse suivante : https://docs.python.org/fr/3/library/csv.html
Une aide hors ligne est également disponible directement sur votre machine avec la fonction native help(). Cette fonction affiche une aide complète sur le module importé :
Cette documentation est générée à partir des « docstrings » que nous avons appris à définir pour nos propres fonctions. On comprend tout l'intérêt de bien documenter les fonctions, en particulier quand elles ont vocation à être utilisées par des tiers.
Il est possible d'obtenir de l'aide sur un élément en particulier.
Pour une vue synthétique sur un module il est possible de faire appel à la fonction native dir() qui retourne la liste de toutes les fonctions du module.
Consulter la documentation des bibliothèques doit devenir un réflexe. Les informations ainsi accessibles facilitent et fiabilisent grandement leur emploi.
Conclusion :
Les fonctions sont de puissants outils à la disposition des programmeurs. Les langages informatiques proposent un nombre important de fonctions natives. Il est possible d’y adjoindre celles issues de bibliothèques spécialisées que nous pouvons importer et sur lesquelles nous savons nous documenter. Nous avons également appris à développer et à paramétrer nos propres fonctions selon nos spécifications, et à documenter nos fonctions.