Nous avons depuis le début de notre long périple (de 5 pages) vu plusieurs fonctions, tels que print, input ou encore range. Nous allons maintenant nous intéresser à eux, car ils ont tout un rôle en programmation. Elles permettront notamment de coder plus joliment et d'introduire la notion de module, avec la librairie standard.
Tout d'abord, parlons de la notion de fonction. Une fonction est en fait un morceau de code qui prend éventuellement des valeurs de départ, les entrées, exécute des actions et éventuellement renvoie une valeur de retour, la sortie.
Cette définition ressemble un peu à la notion de fonction en mathématiques, avec les antécédents et les images, mais a quand même une différence, tout comme les variables mathématiques ont une différence avec les variables en programmation. En effet, une fonction peut avoir des variables en son sein et pourrait modifier des variables extérieures à elle quand elle est appelée, même si cela est déconseillé si on a pas de raisons valables. C'est pour cela que certains langages les nomment plutôt des "procédures", pour vous faire une idée de la différence.
En Python, les fonctions s'écrivent comme ceci:
def nom_fonction():
#Suite d'instructions
Reprenons un exemple que nous avons vu précédemment: celui du mot de passe. Nous allons maintenant créer une fonction qui permet de demander à l'utilisateur un mot de passe.
def mot_de_passe():
essai = input("Entrez le mot de passe: ")
while essai != "1234":
essai = input("Mot de passe incorrect. Veuillez réessayer: ")
Nous en arrivons au premier avantage d'utiliser des fonctions: elles peuvent être utilisées plusieurs fois dans un programme. Par exemple, si l'on veut demander plusieurs fois le mot de passe à l'utilisateur, il nous suffit d'écrire plusieurs fois la fonction mot_de_passe.
mot_de_passe()
print("Premier mot de passe bon !")
mot_de_passe()
print("Deuxième mot de passe bon !")
print("Par contre, ton mot de passe est encore pourri...")
Si jamais on veut changer le mot de passe, comme le remarque inopinément notre programme, il suffit de modifier la définition de notre programme. C'est un deuxième avantage des fonctions: si on veut modifier une fonction, on n'a qu'à seulement modifier sa définition et non plus toucher à tous les endroits où l'on utilise la fonction.
Par contre, nous voudrions pouvoir modifier facilement le mot de passe, pour que les mots de passe soient différents les deux fois. Pour cela, nous pouvons redéfinir la fonction pour qu'elle prenne une entrée, le mot de passe à écrire. Pour cela, on écrit le nom de l'argument entre les parenthèses de la première ligne. Cet argument peut ainsi être utilisé dans le code de la fonction. Voici ce que cela donnerait avec notre fonction:
def mot_de_passe(réponse):
essai = input("Entrez le mot de passe: ")
while essai != réponse:
essai = input("Mot de passe incorrect. Veuillez réessayer: ")
Les noms des fonctions comme des arguments respectent les mêmes règles que les noms des variables. En écrivant comme nous l'avons vu les noms d'arguments, il faut qu'à chaque appel de la fonction, on donne les valeurs de tous les arguments dans le bon ordre, sinon l'interpréteur va hurler qu'il ne peut pas utiliser la fonction.
Nous pouvons définir des valeurs "par défaut" à des arguments d'une fonction. Ainsi, si lors d'un appel de la fonction on ne donne pas de valeur à ces arguments, alors ils auront leur valeur par défaut. Pour définir une valeur par défaut, on l'indique simplement avec un signe = dans les parenthèses de la définition de la fonction. Par exemple, nous pourrions ajouter un argument, message, à la fonction mot_de_passe pour afficher un message après que l'utilisateur ait donné le bon mot de passe et qui vaudrait par défaut "Mot de passe correct.":
def mot_de_passe(réponse, message="Mot de passe correct."):
essai = input("Entrez le mot de passe: ")
while essai != réponse:
essai = input("Mot de passe incorrect. Veuillez réessayer: ")
print(message)
Lorsque l'on a une fonction à utiliser ou à créer, une chose importante à connaitre est son prototype. Le prototype d'une fonction est ce qui est défini dans l'en-tête de la fonction. Il y a le nom de la fonction ainsi que ses paramètres. La plupart des langages y inclut aussi le type des paramètres et celui de la valeur retournée, mais en Python, cela n'a pas besoin d'être défini. Néanmoins, il est aussi important en pratique de connaitre les types d'entrée et de sortie d'une fonction pour l'utiliser correctement.
Maintenant, intéressons-nous aux sorties des fonctions: comment pouvons-nous faire retourner quelque chose à une fonction ? En Python, pour qu'une fonction retourne une valeur, on utilise le mot-clé return suivi de la valeur à retourner. Ainsi, voilà une fonction qui calcule le carré d'un nombre:
def carré(x):
return x ** 2
Petite précision même si cela peut paraître évident: lorsque l'interprète exécute return, la fonction s'arrête ! Faites donc attention de ne pas mettre d'instructions après ça. Voici un simple exemple en mode interactif:
>>> def test():
... print("Avant return")
... return 0
... print("Après return")
...
>>> test()
Avant return
0
Une dernière chose enfin sur les fonctions: j'ai dit qu'elles pouvaient modifier les variables à l'extérieur d'elles. Cependant, cela est très déconseillé. En effet, pourquoi modifier une variable à l'extérieur ? Vous n'êtes pas sûr de lui donner une valeur qui ne posera pas de problème... A moins que vous soyez sûrs de ce que vous faites. C'est pour cela qu'en Python, on ne peut pas par défaut avoir accès aux variables externes. Pour avoir accès à une variable en dehors de la fonction, vous devez écrire au début du code de la fonction global suivi du nom des variables dont vous avez besoin. Eh oui, Python protège vos codes, mais si vous lui demandez de ne pas le faire, il vous considère comme un adulte responsable et vous laisse faire !
Voici par exemple une fonction qui permet d'échanger les valeurs de deux variables nombre_1 et nombre_2:
def doubler_nombre():
global nombre1, nombre2
nombre1, nombre2 = nombre2, nombre1
Les fonctions, comme nous avons vu, nous permettent de découper un programme en plusieurs morceaux indépendants afin de réduire la taille d'un programme lorsqu'une tâche est effectuée plusieurs fois, mais aussi afin d'améliorer la compréhension d'un code. En effet, il est plus simple de voir "l'essentiel" d'un programme, puis les définitions des fonctions dont nous avons besoin.
Python a beaucoup, mais alors beaucoup de fonctions, bien plus que ce que nous avons vu depuis maintenant. Le langage permet aussi d'utiliser beaucoup de fonctionnalités, comme des classes (des implémentations pour créer des types). Toutes ces fonction et autres codes sont réunis dans une grand ensemble, la librairie standard, et organisés en modules.
Un module est un fichier avec du code et que l’on va pouvoir réutiliser dans un autre fichier. Cela va nous permettre de raccourcir notre programme en y mettant l’essentiel de notre code, d’écrire une bonne pour toute notre code sans copier-coller et d’utiliser des codes faits, eux, par des personnes qui se sont spécialisées et donc de faire par exemple une interface graphique sans avoir à connaître comment sont faits les widgets, par exemple.
Pour importer un module dans un programme en Python, il suffit de rajouter cette ligne:
import nom_du_module
Nous pourrons ainsi utiliser ce qui est défini dans le module en écrivant le nom du module, puis le nom de la fonction séparé par un point. Nous pouvons remplacer le nom du module par un pseudo-nom en écrivant comme ceci:
import nom_du_module as pseudo_nom
Nous pouvons aussi n'importer que certaines fonctions du module, mais que nous n'aurons pas besoin d'appeler avec le nom du module en écrivant ceci:
from nom_du_module import nom_fonction_1, nom_fonction_2, ...
Ou même tout importer et pouvoir utiliser le nom des fonctions seul avec ça:
from nom_du_module import *
Si je vous montre tout ceci, c'est que chaque manière d'importer a ses avantages. La première et la deuxième sont les plus sûres, car il permet de ne pas avoir d'erreurs si deux fonctions s'appellent pareil dans deux modules différents. En effet, elles s'appelleraient de la même manière et l'interpréteur ne saura pas laquelle utiliser. Par contre, écrire toujours le même nom est un peu rébarbatif. Pour ma part, je vais utiliser la première manière, car elle permet de savoir d'où vient quelle fonction et de son coté, la Python Software Foundation demande de faire de même dans la PEP 8 sur la lisibilité du code, mais vous faites comme vous voulez tant que cela est logique ! Vous êtes des adultes responsables, n'oubliez pas !
Pour mieux comprendre l'idée de module, faisons une petite manipulation. Pour cela, créez un nouveau fichier que nous allons nommer mon_module.py et qui sera notre module. Nous allons y écrire quelques fonctions:
def carré(x):
return x ** 2
def moyenne(x, y):
return (x + y) / 2
def exp(x):
return 2 ** x
Nous allons pouvoir utiliser ce module dans un autre programme. Enregistrez, puis créez un autre fichier dans le même dossier, test.py, dans lequel nous allons écrire un petit programme utilisant les fonctions que nous avons défini dans notre module:
import mon_module
print(mon_module.carré(5), mon_module.exp(3), mon_module.moyenne(8, 3))
Exécutez maintenant test.py et vous devriez voir s'afficher 25 8 5.5.
Le module que nous avons créé ici est écrit en Python, mais il existe des modules écrits dans d'autres langages. Il faut alors utiliser un code permettant de faire le parallèle entre les deux langages. L'interpréteur CPython, que vous utilisez très probablement car il est "officiel", permet de programmer des modules en C facilement (enfin, il faut connaitre le langage ! ^^), un langage connu pour sa rapidité et qui est plus "terre-à-terre" avec le fonctionnement de la machine.
Nous allons maintenant nous intéresser à la librairie standard. C'est un ensemble de modules présents par défaut à l'installation de Python, très polyvalent et optimisé. Elle est une très bonne base pour faire des programmes intéressants, même si pour des programmes avancés il faudra télécharger des modules, comme PyQT, Sympy, Django...
Parmi ces modules, nous allons en voir deux: le module "math" et le module "random". Ce sont deux modules très utiles, mais ne sont bien sûr pas les seuls: j'en montrerais surement d'autres, plus tard...
Tout d'abord, le module "math" est un module qui contient comme son nom l'indique plusieurs fonctions et variables utiles pour les mathématiques. En voici une liste non exhaustive:
import math
math.ceil(x) #Fonction retournant un entier arrondi au supérieur
math.floor(x) #Fonction retournant un entier arrondi à l'inférieur
math.pi #Constante pi = 3.141592653589793...
#Fonctions trigonométriques. Attention, les angles à donner sont en radians
math.radians(x) #Convertit les degrés en radians
math.cos(x) #Renvoie le cosinus de x radians
math.sin(x)
math.tan(x)
math.acos(x)
math.asin(x)
math.atan(x)
math.sqrt(x) #Calcule la racine carrée d'un nombre
math.dist(p, q) #La distance entre deux points (deux listes avec les coordonnées)
math.gcd(a, b) #Retourne le PGCD de deux nombres
Le module "math" contient beaucoup plus de fonctions et de variables, notamment pour la combinatoire, les nombres complexes et plein d'autres choses.
Maintenant, parlons du module "random". Ce module permet de générer des nombres aléatoires, ce qui est pratique pour faire des simulations ou pour créer des situations au hasard. Sachez que l'aléatoire est compliqué à réellement mettre en place, car les ordinateurs ne permettent peuvent pas en générer. Ils peuvent exécuter des directives à la lettre, mais pas créer de nombres aléatoires. Il existe cependant des techniques pour créer des nombres dits pseudos-aléatoires.
Voici une liste de fonctions que permettent de générer du pseudo-aléatoire dans ce module:
import random
random.randint(a, b) #Retourne un nombre aléatoire entre a et b inclus
random.choice(seq) #Retourne un élément de la liste seq. Lance une erreur si c'est vide.
random.shuffle(a) #Mélange la liste a sans rien renvoyer.
random.random() #Retourne un float entre 0.0 et 1.0.
Comme "math", "random" contient bien plus de fonctions, mais celles-ci largement suffisantes pour des programmes ne faisant pas de simulations très poussées.
La librairie standard contient des dizaines et des dizaines de modules comme ceci. Si vous voulez vous renseigner sur cette librairie qui mérite d'être utilisée, il existe une très bonne documentation officiel de Python, qui contient même une traduction française.
Parlons aussi de quelques fonctions que nous n'avons pas besoin d'importer, car elles le sont par défaut. En voici quelques unes assez simples, en plus de print et input:
min(a, b, ...) #Renvoie le minimum de tous les paramètres
max(a, b, ...) #Pareil que min, avec le maximum
sorted(seq, key=None, reverse=False) #Renvoie seq trié.
#Ecrire "reverse=True" renverse la liste et "key=" change la fonction-critère.
Eh bien ! Vous avez vu pas mal de fonctions, je crois que vous avez de quoi faire des programmes assez intéressants...
Une fonction est un morceau de code s'exécutant lorsqu'on l'appelle, pouvant avoir des entrées et pouvant renvoyer une sortie.
En Python, pour définir une fonction, on utilise cette écriture:
def nom_fonction(argument_1, argument_2, ...):
...
La première ligne, l'en-tête de la fonction, définit son prototype: le nom de la fonction et de ses arguments. Il peut aussi être utile de connaitre les types que nous pouvons utiliser en argument et le type de sortie.
Pour qu'une fonction retourne une valeur de sortie, il faut utiliser l'instruction return, suivi de la valeur à renvoyer. Voici par exemple une fonction qui calcule la moyenne de deux nombres:
def moyenne(a, b):
return (a + b) / 2
Une fonction peut aussi avoir accès à une variable externe à elle. Cependant, pour être sûr de ce qui se passe, Python demande pour accéder à des variables d'écrire au début de la fonction global suivi des noms des variables, comme ceci:
def fonction():
global a, b, ...
#Suite d'instructions
Les fonctions permettent de réutiliser un morceau de code plusieurs fois et d'englober plusieurs instruction en une seule plus compréhensible par son nom.
Un module est un morceau de code contenant plusieurs fonctions et variables que nous pouvons réutiliser dans d'autres programmes. Il peut être écrit en Python ou dans d'autres langages à l'aide de système permettant de les rendre compatibles avec l'interpréteur. Par exemple, il est possible de faire un module pour CPython en C.
Pour importer le module en Python, il faut écrire une ligne en en-tête du programme, qui peut être:
import nom_du_module : les fonctions et variables du module devront être appelés comme ceci: nom_du_module.nom_fonction
import nom_du_module as pseudo: permet de changer le nom du module dans le programme.
from nom_du_module import nom_1, nom_2, ...: importe quelques fonctions et variables, mais il n'y a pas besoin d'écrire le nom du module à chaque utilisation.
from nom_module import *: importe tout et il ne suffit que d'écrire le nom de ce que nous avons besoin dans le module.
Il existe déjà énormément de fonctions en Python, contenues dans un grand ensemble de modules réunis dans la librairie standard. Parmi ces modules, deux peuvent être utiles: le module "math" et le module "random".
La module "math" permet d'effectuer des calculs mathématiques. En voici une liste non-exhaustive:
import math
math.ceil(x) #Fonction retournant un entier arrondi au supérieur
math.floor(x) #Fonction retournant un entier arrondi à l'inférieur
math.pi #Constante pi = 3.141592653589793...
#Fonctions trigonométriques. Attention, les angles à donner sont en radians
math.radians(x) #Convertit les degrés en radians
math.cos(x) #Renvoie le cosinus de x radians
math.sin(x)
math.tan(x)
math.acos(x)
math.asin(x)
math.atan(x)
math.sqrt(x) #Calcule la racine carrée d'un nombre
math.dist(p, q) #La distance entre deux points (deux listes avec les coordonnées)
math.gcd(a, b) #Retourne le PGCD de deux nombres
Le module "random", lui, permet de générer de l'aléatoire dans des programmes.
import random
random.randint(a, b) #Retourne un nombre aléatoire entre a et b inclus
random.choice(seq) #Retourne un élément de la liste seq. Lance une erreur si c'est vide.
random.shuffle(a) #Mélange la liste a sans rien renvoyer.
random.random() #Retourne un float entre 0.0 et 1.0.
Bien sûr, les modules "random", "math", et la librairie standard en général ne se résume pas à ça, loin de là. Pour se renseigner, la documentation officielle est une bonne piste.
Il existe aussi un certain nombre de fonctions déjà utilisables sans import, car elles le sont par défaut. print et input en font parti. En voici quelques autres qui pourront vous être utiles:
min(a, b, ...) #Renvoie le minimum de tous les paramètres
max(a, b, ...) #Pareil que min, avec le maximum
sorted(seq, key=None, reverse=False) #Renvoie seq trié.
#Ecrire "reverse=True" renverse la liste et "key=" change la fonction-critère.