Retourner à : Python pour débutants
Maintenant que nous avons appris les opérateurs et les structures de données de base en Pyhton, il est temps de regarder comment mieux structurer notre code. Pour cela nous allons apprendre à créer des fonctions et à séparer notre code en plusieurs modules. Pour cela nous allons :
- expliquer ce que sont les fonctions et comment les créer
- expliquer ce qu’est un module en python et comment séparer notre code en modules
- on verra à quoi sers la ligne if __name__ == ‘__main__’: que vous avez peut-être déjà rencontré dans du code
- pour finir on verra comment structurer nos modules en packages
Les fonctions
Commençons par regarder ce que sont les fonctions. Tout au long de notre cours, nous avons déjà utilisé des fonctions, sans pour autant les expliquer en détail et sans regarder comment créer nos propres fonctions. Et bien une fonction est un block de code réutilisable qui execute une tâche bien précise. L’idée principale est d’éviter de dupliquer du code inutilement et de faciliter la lecture de notre code.
En python une fonction est construite de la manière suivante:
def nom_de_la_fonction(param_1, param_2):
<block_de_code>On a tout d’abord le mot clé def, qui indique que ce qui va suivre est la définition d’une fonction, ensuite nous avons le nom que nous voulons donner à notre fonction, puis entre parenthèses nous pouvons avoir 0, 1 ou plusieurs paramètres. Pour finir les parenthèses sont suivies d’un double point « :« . En dessous, nous retrouvons le block de code indenté qui appartient à cette fonction et sera exécuté quand on l’appellera.
Notez que les paramètres sont des valeurs qui seront passées à notre fonction lorsque nous y feront appel et que nous pouvons utiliser ces paramètres à d’intérieur du block de code de la fonction, comme on l’aurait fait pour n’importe quelle variable.
Ensuite pour faire appel à notre fonction, il suffit d’utiliser son nom suivi de parenthèses, et si la fonction prend des paramètres en entrée, nous devons passer ces paramètres également entre parenthèses comme ceci:
# ceci va exécuter la fonction et lui passer les chiffres 1 et 2 en paramètre
nom_de_la_fonction(1, 2) Donc si nous souhaitons créer et utiliser une fonction qui va imprimer le message hello world, on peut faire la chose suivante :
def hello():
print("Hello World")
hello()Maintenant si on souhaite écrire une fonction qui va prendre des paramètres en entrée et retourner un résultat, comme par exemple une fonction qui va calculer la somme de deux nombres, on peut faire la chose suivante :
def sum_two_numbers(number_1, number_2):
return number_1 + number_2
sum_1 = sum_two_numbers(12, 32)
sum_2 = sum_two_numbers(44, 1)
print(sum_1, sum_2)Comme vous le voyer pour retourner un résultat dans notre fonction on utilise le mot clé return, ce mot clé indique que la fonction à terminé son execution et retourne le résultat qui le précède. Donc ici on retourne en tant que résultat la somme de number_1 et number_2.
Ensuite pour utiliser cette fonction il suffit de lui passer les nombres que nous souhaitons additionner en paramètre et nous pouvons assigner le résultat à une variable de notre choix. L’exécution du code ci-dessus nous donne le résultat suivant :

Les modules
Imaginons maintenant que nous souhaitions créer un programme qui fasse les choses suivantes:
- Définisse 3 variables, donc deux nombres a et b, ainsi qu’un prénom name
- Définisse les fonctions:
- hello, qui prend un prénom en paramètre et dit Hello suivi de ce prénom
- goodbye, qui prend un prénom en paramètre et dit Goodbye suivi de ce prénom
- sum_two_numbers, qui calcule la somme de deux nombres
- sub_two_numbers, qui soustrait deux nombres
- multiply_two_numbers, qui multiplie deux nombres
- divide_two_numbers, qui divise deux nombres
- surface_square, qui calcule la surface d’un carré de longueur a
- surface_rectangle, qui calcule la surface d’un rectangle avec les côtés de longueur a, b
- surface_circle, qui calcule la surface d’un cercle de rayon a
- Ensuite le programme :
- Fait appel à hello
- Imprime le résultat de toutes les méthodes de calcules ci-dessus appliquées aux variables a et b quand nécessaire.
- Fait appel à la méthode goodbye
Si on met toutes ces fonctions et ce code dans un seul et même fichier, on obtient le code suivant :
def hello(name):
print(f"Hello {name}")
def goodbye(name):
print(f"Goodbye {name}")
def sum_two_numbers(number_1, number_2):
return number_1 + number_2
def sub_two_numbers(number_1, number_2):
return number_1 - number_2
def multiply_two_numbers(number_1, number_2):
return number_1 * number_2
def divide_two_numbers(number_1, number_2):
return number_1 / number_2
def surface_square(length):
return length * length
def surface_rectangle(length, width):
return length * width
def surface_circle(radius):
return 3.14 * radius * radius
a = 12
b = 3
name = "John"
sum = sum_two_numbers(a, b)
sub = sub_two_numbers(a, b)
mult = multiply_two_numbers(a, b)
div = divide_two_numbers(a, b)
surface_square_a = surface_square(a)
surface_rectangle_a_b = surface_rectangle(a, b)
surface_circle_a = surface_circle(a)
hello(name)
print(f"{a} + {b} = {sum}")
print(f"{a} - {b} = {sub}")
print(f"{a} * {b} = {mult}")
print(f"{a} / {b} = {div}")
print(f"surface square {a} = {surface_square_a}")
print(f"surface rectangle {a} x {b} = {surface_rectangle_a_b}")
print(f"surface circle {a} = {surface_circle_a}")
goodbye(name)Si on execute ce code on obtient :

Ce code fonctionne, mais il est très difficile à lire, malgré le fait que nos fonctions n’ont qu’une seule ligne de code. Imaginez à quoi ce code ressemblerait avec des fonctions plus complexes, ce serait très vite ingérable. Idéalement on aurait besoin d’une manière de diviser notre code en plusieurs fichiers, et ça tombe bien on peut le faire sans problème.
Commençons par créer 3 nouveaux fichiers et par y déplacer nos fonctions. On va créer un fichier greetings.py qui va contenir les fonctions hello et goodbye, un fichier arithmetic.py qui va contenir les méthodes sum_two_numbers, sub_two_numbers, multiply_two_numbers et divide_two_numbers, et pour finir on aura également un fichier geometry.py qui va contenir le reste des fonctions.
def hello(name):
print(f"Hello {name}")
def goodbye(name):
print(f"Goodbye {name}")def sum_two_numbers(number_1, number_2):
return number_1 + number_2
def sub_two_numbers(number_1, number_2):
return number_1 - number_2
def multiply_two_numbers(number_1, number_2):
return number_1 * number_2
def divide_two_numbers(number_1, number_2):
return number_1 / number_2def surface_square(length):
return length * length
def surface_rectangle(length, width):
return length * width
def surface_circle(radius):
return 3.14 * radius * radiusMaintenant que nos fonctions sont dans leurs fichiers respectifs, nous devons voir comment faire pour les utiliser dans notre fichier main.py. Pour cela on peut utiliser le mot clé import suivi du nom du fichier que nous souhaitons importer sans le .py. Ensuite pour utiliser les fonctions ou tout autre objet défini dans ce fichier, il suffit de faire précéder la fonction ou l’objet en question du nom du fichier suivi d’un point, puis le nom de la fonction ou de l’objet en question.
Donc, si on souhaite faire appel à la méthode hello du fichier greetings.py, on doit tout d’abord importer greetings, et puis on peut appeler la fonction en faisant un greetings.hello(« Mon prénom »). Appliquons tout cela aux différentes fonctions utilisées dans notre fichier main.py :
import arithmetic
import geometry
import greetings
a = 12
b = 3
name = "John"
sum = arithmetic.sum_two_numbers(a, b)
sub = arithmetic.sub_two_numbers(a, b)
mult = arithmetic.multiply_two_numbers(a, b)
div = arithmetic.divide_two_numbers(a, b)
surface_square_a = geometry.surface_square(a)
surface_rectangle_a_b = geometry.surface_rectangle(a, b)
surface_circle_a = geometry.surface_circle(a)
greetings.hello(name)
print(f"{a} + {b} = {sum}")
print(f"{a} - {b} = {sub}")
print(f"{a} * {b} = {mult}")
print(f"{a} / {b} = {div}")
print(f"surface square {a} = {surface_square_a}")
print(f"surface rectangle {a} x {b} = {surface_rectangle_a_b}")
print(f"surface circle {a} = {surface_circle_a}")
greetings.goodbye(name)Il existe une autre manière d’importer les fonctions dont on a besoin et d’y accéder directement sans devoir passer par le nom du module suivi d’un point. Pour cela on peut faire utiliser le mot clé from suivi du nom du module, suivi du mot clé import et puis on n’a plus qu’à énumérer les différents objets qu’on souhaite importer séparés par des virgules.
L’avantage quand on fait cela, est qu’on peut utiliser les méthodes directement sans utiliser le nom du module suivi d’un point. Notez tout de même que bien que le code en devienne plus lisible, et bien que vous n’ayez accès qu’aux méthodes importer, python chargera tout de même le contenu entier du module.
from geometry import surface_circle, surface_rectangle, surface_square
import arithmetic
import greetings
a = 12
b = 3
name = "John"
sum = arithmetic.sum_two_numbers(a, b)
sub = arithmetic.sub_two_numbers(a, b)
mult = arithmetic.multiply_two_numbers(a, b)
div = arithmetic.divide_two_numbers(a, b)
surface_square_a = surface_square(a)
surface_rectangle_a_b = surface_rectangle(a, b)
surface_circle_a = surface_circle(a)
greetings.hello(name)
print(f"{a} + {b} = {sum}")
print(f"{a} - {b} = {sub}")
print(f"{a} * {b} = {mult}")
print(f"{a} / {b} = {div}")
print(f"surface square {a} = {surface_square_a}")
print(f"surface rectangle {a} x {b} = {surface_rectangle_a_b}")
print(f"surface circle {a} = {surface_circle_a}")
greetings.goodbye(name)
if __name__ == ‘__main__’
Comme dit il y à un instant, si on importe un module ou des objets d’un module, Python va charger tout le code de ce module, et si l’auteur de ce module à ajouter du code en dehors qui s’execute au chargement du fichier, ce code va s’executer lors de l’import du module.
Considérons que le fichier greetings.py contienne les lignes de code suivantes en fin de fichier :
def hello(name):
print(f"Hello {name}")
def goodbye(name):
print(f"Goodbye {name}")
name = "Mika"
hello(name)
goodbye(name)Et bien si on execute ce fichier on a bien le résultat attendu :

Ici, on voit bien les deux prints. En revanche ce qui peut surprendre, est que si nous lançons notre fichier main.py. On peut également apercevoir ces deux prints au tout début de l’execution de notre code :

Et oui, lors de l’import de greetings, Python charge le module, voit les 3 lignes de codes incluant les deux prints, et les execute. Comment faire pour que le code d’un fichier ne soit exécuté uniquement que si c’est le fichier lui même qui a été exécuté directement et non pas importé par un autre fichier ?
Et bien pour cela on peut vérifier le contenu de la variable __name__, qui est une variable mise à disposition par python et qui contiens la valeur __main__ lorsque le fichier actuel est le fichier qui a été exécuté directement par python. Si en revanche le fichier a été importé, cette variable contient le nom du module importé. Et on peut donc faire la chose suivante :
def hello(name):
print(f"Hello {name}")
def goodbye(name):
print(f"Goodbye {name}")
if __name__ == "__main__":
name = "Mika"
hello(name)
goodbye(name)from geometry import surface_circle, surface_rectangle, surface_square
import arithmetic
import greetings
if __name__ == "__main__":
a = 12
b = 3
name = "John"
sum = arithmetic.sum_two_numbers(a, b)
sub = arithmetic.sub_two_numbers(a, b)
mult = arithmetic.multiply_two_numbers(a, b)
div = arithmetic.divide_two_numbers(a, b)
surface_square_a = surface_square(a)
surface_rectangle_a_b = surface_rectangle(a, b)
surface_circle_a = surface_circle(a)
greetings.hello(name)
print(f"{a} + {b} = {sum}")
print(f"{a} - {b} = {sub}")
print(f"{a} * {b} = {mult}")
print(f"{a} / {b} = {div}")
print(f"surface square {a} = {surface_square_a}")
print(f"surface rectangle {a} x {b} = {surface_rectangle_a_b}")
print(f"surface circle {a} = {surface_circle_a}")
greetings.goodbye(name)
Et maintenant si on execute le fichier greetings.py on a toujours le résultat suivant :

En revanche si on relance le fichier main.py, nous n’avons plus que le code de main.py qui est exécuté :

Les packages
Séparer notre en code en plusieurs fichiers, aide déjà grandement à la clarté du code, mais dès qu’on a des projets plus sérieux le nombre de fichiers augmente rapidement et on a donc besoin d’une manière de structurer tout ces fichiers. Pour cela on peut créer des packages.
Un package n’est rien d’autre qu’un dossier dans lequel on définir un fichier appelé __init__.py. Ce fichier indique à python que le dossier est en faite un package python et que son contenu peut être importé. On peut donc y stocker des modules ou des sous-packages.
Dans notre exemple, nous pouvons regrouper les modules arithmetic et geometry dans un package nommé mathematics. Pour cela on doit créer l’arborescence suivante :
mathematics
|- __init__.py
|- arithmetic.py
|- geometry.py
greetings.py
main.py
Une fois que c’est fait, nous pouvons adapter notre fichier main.py de la manière suivante :
from mathematics.geometry import surface_circle, surface_rectangle, surface_square
from mathematics import arithmetic
import greetings
if __name__ == "__main__":
a = 12
b = 3
name = "John"
sum = arithmetic.sum_two_numbers(a, b)
sub = arithmetic.sub_two_numbers(a, b)
mult = arithmetic.multiply_two_numbers(a, b)
div = arithmetic.divide_two_numbers(a, b)
surface_square_a = surface_square(a)
surface_rectangle_a_b = surface_rectangle(a, b)
surface_circle_a = surface_circle(a)
greetings.hello(name)
print(f"{a} + {b} = {sum}")
print(f"{a} - {b} = {sub}")
print(f"{a} * {b} = {mult}")
print(f"{a} / {b} = {div}")
print(f"surface square {a} = {surface_square_a}")
print(f"surface rectangle {a} x {b} = {surface_rectangle_a_b}")
print(f"surface circle {a} = {surface_circle_a}")
greetings.goodbye(name)
Comme indiqué dans le code, nous pouvons, ici aussi, importer un module complet de notre package, ou des méthodes spécifiques d’un module contenu dans un package.
Notez que pour naviguer dans un package, et accéder à un sous-package ou module, on utilise un point. Donc si on a un module c qui est contenu package b, lui-même contenu dans un package a, on peut importer ce module de la manière suivante :
from a.b import cEt si on souhaite importer une méthode spécifique de ce module c on peut faire :
from a.b.c import my_functionEt voilà, grace aux packages, aux modules et aux fonctions, on peut créer du code organisé facile naviguer et à lire. Cette façon de structurer le code est indispensable pour tout projet autre que de simples exercices académiques, et il est donc conseillé de bien se familiariser avec ces concepts.