C’est le cours python numéro 17 de la série des cours d’initiation à python.
En informatique, un synonyme courant du terme “fonction” est “sous-programme” (en anglais : sous-programme, sous-programme). En effet, un autre avantage de l’utilisation des fonctions est de pouvoir découper un programme long et compliqué en “morceaux” distincts, qui peuvent être développés et testés séparément (voire en parallèle, confiés à des programmeurs différents). Par exemple, le programme principal d’un jeu vidéo pourrait ressembler à ceci :
initialize_graph () load_options () caractère = choisir_caractère () résultat = correspondance (personnage) si résultat == Vrai : la victoire() autre: défaite() sortir()
Dans une maison de logiciels, un programmeur expert en graphisme pourrait s’occuper de la première fonction, tandis que des experts en intelligence artificielle pourraient développer la fonction match(), etc.
Un précepte général de l’informatique dit que les fonctions doivent être totalement indépendantes du programme principal, c’est-à-dire ne faire référence à aucune de ses ressources : la seule communication entre le programme et les fonctions doit s’effectuer via les paramètres (en entrée), et les retour (en sortie). De cette manière, il est possible de développer les fonctions séparément du programme principal : un programmeur aurait seulement besoin de savoir quelles données sa fonction entre et ce qu’elle doit retourner. Mais il y a plus : une fois que vous avez programmé une fonction qui “fait quelque chose”, vous pouvez facilement la réutiliser dans un autre programme.
Le principal problème pratique de cette approche réside dans l’utilisation des variables : si la fonction est un morceau de code séparé du programme principal, ses variables seront-elles également séparées ou seront-elles toujours les mêmes ? Si nous y réfléchissons, de nombreuses questions se posent :
Les premiers langages de programmation suivaient une approche très simple : chaque nom correspondait à une et une seule variable, toujours la même, qui pouvait être librement lue et modifiée à tout moment du programme (dans le programme principal ou au sein d’une fonction). Dans de très grands programmes avec de nombreuses variables, cela a conduit à plusieurs inconvénients. Par exemple, supposons que deux programmeurs différents doivent écrire deux fonctions différentes d’un même programme : avec cette approche ils devraient “s’accorder” sur le nom des variables à utiliser, afin de ne pas courir le risque qu’une des fonctions modifie les variables de l’autre . De plus, chaque fois que vous avez besoin d’ajouter de nouvelles variables dans le programme, vous devez toujours vérifier que vous n’avez pas déjà utilisé leur nom ailleurs.
Par conséquent, les paramètres et les variables créés à l’intérieur d’une fonction sont distincts de ceux à l’extérieur, même s’ils portent le même nom : en particulier les paramètres, comme je l’ai déjà dit, sont de nouvelles variables qui contiennent une copie de la valeur utilisée dans l’appel. Voyons quelques exemples pour clarifier nos idées :
def test (x) : # x est le paramètre (variable locale) x = x + 1 # on change la valeur du paramètre print ("A l'intérieur de la fonction x =", x) # écrira "Fonction interne x = 11" # à la sortie de la fonction x est détruit # démarrage du programme principal a = 10 # on crée la variable a print ("Avant l'appel à =", a) # écrira "Avant appel à = 10" test (a) # on passe a en paramètre à la fonction print ("Après l'appel de =", a) # écrira "Après avoir appelé a = 10": a n'a pas changé en dehors de la fonction
Dans le premier exemple on appelle une fonction qui modifie la valeur de son paramètre : on voit qu’à la sortie de la fonction la variable utilisée dans l’appel est restée inchangée (la fonction a modifié la variable locale x mais pas la variable globale a) .
Faisons maintenant quelque chose de plus audacieux : utilisons le même nom à la fois dans le programme principal et dans la fonction. Modifier comme suit :
def test (x) : # x est le paramètre (variable locale) x = x + 1 # on change la valeur du paramètre print ("A l'intérieur de la fonction x =", x) # écrira "Fonction interne x = 11" # à la sortie de la fonction x est détruit # démarrage du programme principal x = 10 # la variable globale a le même nom que le paramètre print ("Avant d'appeler x=", x) # écrira "Avant l'appel x = 10" test (x) # on passe x en paramètre à la fonction print ("Après avoir appelé x =", x) # écrira "Après appel à = 10": x n'a pas changé en dehors de la fonction
On voit que le résultat est exactement le même : la variable x définie dans le programme principal est globale et non le même paramètre x (local) de la fonction.
Enfin, nous créons des variables à l’intérieur de la fonction et voyons ce qui se passe :
def test (x) : # x est le paramètre (variable locale) x = x + 1 # on change la valeur du paramètre y = 20 # créons une nouvelle variable print ("A l'intérieur de la fonction x =", x, "et y =", y) # écrira "A l'intérieur de la fonction x = 11 et y = 20" # à la sortie de la fonction x et y sont détruits # démarrage du programme principal x = 10 # on crée la variable x print ("Avant d'appeler x=", x) # écrira "Avant l'appel x = 10" test (x) # on passe x en paramètre à la fonction print ("Après la fonction x=", x, "et y =", y) # donnera une NameError : y est local et n'existe pas en dehors de la fonction
Voyons maintenant la réponse à la dernière question : une fonction peut-elle lire ou écrire une variable globale définie en dehors d’elle ? Le changement d’une variable globale au sein d’une fonction est considéré par les programmeurs comme une pratique à éviter, car dans le programme principal on appellera la fonction et après l’appel la variable sera mystérieusement “modifiée”, sans aucune affectation (et donc sans que le programmeur notices) Pour cela, Python a mis en place une stratégie assez compliquée, mais que vous devez connaître :
Ce mécanisme permet de créer autant de variables que l’on veut dans le corps d’une fonction, sans se soucier de leurs noms : ceux-ci n’affecteront jamais les variables définies en dehors de la fonction. Voyons un exemple :
def new_a (): a = 10 # ici a est local print ("Dans la fonction a tient", a, "et b tient", b) a = 5 # ici a est global (différent de la fonction a) b = 20 print ("Avant que la fonction a tienne", a, "et b tienne", b) nouveau_a () print ("Après la fonction a tient", a, "et b tient", b)
La sortie du programme est celle-ci :
Avant la fonction a vaut 5 et b vaut 20 Dans la fonction a vaut 10 et b vaut 20 Après la fonction a vaut 5 et b vaut 20
La variable b est toujours restée la même (définie globalement dans le programme principal, et uniquement lue par la fonction), tandis que la variable a, définie dans la fonction, est locale et donc différente (même si elle porte le même nom) de la globale définie dans le principal du programme.
La règle 2 stricte empêche complètement qu’une variable qui lui est extérieure soit modifiée depuis l’intérieur d’une fonction. Ce comportement, comme nous l’avons dit, est considéré comme dangereux, mais il est parfois impossible de l’éviter. Pensons par exemple à un jeu qui dispose de diverses options globales (résolution vidéo, volume audio, niveau de difficulté…) : celles-ci seront probablement stockées dans certaines variables globales. Si maintenant je voulais implémenter une série de fonctions edit_audio(), edit_video(), edit_difficult() pour changer ces options, il faudrait nécessairement qu’elles agissent sur ces variables globales, ce qui est impossible avec les instructions vues jusqu’ici. C’est pourquoi (généralement les langages de programmation ne suivent pas à la lettre les diktats de l’informatique théorique !) un assouplissement de la règle 2 est envisagé.
Il est possible de déclarer qu’une variable dans une fonction est globale avec l’instruction globale, suivie du nom de la variable (ou de plusieurs noms séparés par des virgules).
Editez le dernier programme comme ceci :
def new_a (): mondial un a = 10 # maintenant a est global print ("Dans la fonction a tient", a, "et b tient", b) a = 5 # ici a est global b = 20 print ("Avant que la fonction a tienne", a, "et b tienne", b) nouveau_a () print ("Après la fonction a tient", a, "et b tient", b) Copie
Et voici la sortie :
Avant la fonction a vaut 5 et b vaut 20 Dans la fonction a vaut 10 et b vaut 20 Après la fonction a vaut 10 et b vaut 20
Qu’est ce qui a changé? Dans la dernière ligne, nous avons maintenant que a est égal à 10. C’est parce que cette fois la variable a à l’intérieur de la fonction a été déclarée globale, donc la fonction agit sur la même variable que le programme principal.
Dans les leçons précédentes, nous avons souvent rencontré des situations où l’utilisateur devait entrer un nombre, par exemple, de 1 à 6, ou une réponse “s” ou “n”. Ces situations généraient une bonne quantité de code, car il fallait aussi vérifier que la saisie était correcte et éventuellement répéter la question. L’un des préceptes de base de l’informatique est la réutilisation du code : les programmeurs détestent devoir réécrire plusieurs fois le même code (plus d’efforts mais surtout plus de possibilité d’erreurs), donc une fois que vous avez écrit et vérifié un ensemble de lignes qui sûrement ” fait ce qu’il doit faire “, nous essayons généralement de le transformer en fonction afin de pouvoir le réutiliser autant de fois que nous le souhaitons.
Cette fois, nous n’écrirons pas un programme, mais un module fonction, qui contiendra diverses fonctions d’entrée (sans qu’aucun programme principal ne les appelle). Nous pouvons ensuite importer le module depuis nos programmes de la même manière que les modules Python par défaut (tant que le programme et le module sont dans le même répertoire) : from myinput import *.
Voici la première fonction :
def input_sn (invite) : tandis que Vrai : réponse = entrée (invite) si resp dans ["s", "n"] : réponse de retour print ("Entrée incorrecte")
Comprendre ce que fait la fonction devrait être assez simple : elle prend l’invite en paramètre (c’est-à-dire la question que nous devons poser à l’utilisateur) et renvoie la chaîne saisie par l’utilisateur, en vérifiant qu’il s’agit bien de “s” ou de “n”. Un exemple d’utilisation pourrait être le suivant (ATTENTION ! N’écrivez pas ces lignes dans le fichier, elles ne servent qu’à titre d’exemple) :
depuis mon importation d'entrée * . . . resp = input_sn ("Voulez-vous continuer ? (y / n)")
Une fonction un peu plus sophistiquée peut demander en second paramètre une liste de réponses possibles, en vérifiant toujours que la réponse de l’utilisateur correspond à l’une d’entre elles ; ajoutez cette autre fonction après input_sn() (comme toujours, sautez une ligne entre une fonction et une autre pour améliorer la lisibilité) :
def input_list (invite, exacte): tandis que Vrai : réponse = entrée (invite) si resp exactement : réponse de retour print ("Entrée incorrecte")
Comprendre ce que fait la fonction devrait être assez simple : elle prend l’invite en paramètre (c’est-à-dire la question que nous devons poser à l’utilisateur) et renvoie la chaîne saisie par l’utilisateur, en vérifiant qu’il s’agit bien de “s” ou de “n”. Un exemple d’utilisation pourrait être le suivant (ATTENTION ! N’écrivez pas ces lignes dans le fichier, elles ne servent qu’à titre d’exemple) :
from myinput import * . . . risp = input_sn("Voulez-vous continuer? (s/n) ")
Une fonction un peu plus sophistiquée peut demander en second paramètre une liste de réponses possibles, en vérifiant toujours que la réponse de l’utilisateur correspond à l’une d’entre elles ; ajoutez cette autre fonction après input_sn() (comme toujours, sautez une ligne entre une fonction et une autre pour améliorer la lisibilité) :
def input_lista(invite, exacte): while True: risp = input(prompt) if risp in esatte: return risp print("Entrée incorrecte")
Et voici un exemple de son utilisation :
from myinput import * . . . risp = input_lista("Voulez-vous des pâtes ou de la pizza ? ", ["pasta", "pizza"])
(notez que le deuxième paramètre doit être une liste, donc il doit être écrit entre crochets (un tuple entre crochets était également bien).
Voici une fonction qui accepte deux nombres en paramètre, en plus de l’invite, et renvoie un nombre saisi par l’utilisateur, uniquement s’il est compris entre le minimum et le maximum.
def input_int (invite, min, max): tandis que Vrai : resp = int (entrée (invite)) si resp> = min et resp <= max : réponse de retour print ("Entrée incorrecte")
Infine una funzione più sofisticata, che richiede all’utente una scelta tra un menu di opzioni: essa prende come parametro una lista con le varie opzioni, le stampa su più righe precedute da un numero, e restituisce il numero immesso dall’utente:
def input_menu (options): pour i dans la plage (len (options)): print (i + 1, "", options [i]) # pour écrire des nombres entre 1 et len (options) tandis que Vrai : resp = int (entrée ("?")) si resp> = 1 et resp <= len (options) : réponse de retour print ("Entrée incorrecte")
Par exemple, nous pourrions appeler la fonction comme ceci :
from myinput import * . . . opz = input_menu(["Nuovo", "Apri", "Salva", "Salva con nome", "Esci"]) if opz == 1: nuovo() elif opz == 2: apri() elif opz == 3: salva() elif opz == 4: salva_nome() else: esci()
Voici des exercices corrigés en gestion de stock sur le thème du stock de sécurité,…
L’observation et l’analyse des situations de travail dangereuses sont des étapes clés dans la prévention…
Une fiche méthodologique est un outil structuré et synthétique qui facilite l’organisation et la communication…
Voici une série d’exercices conçus pour perfectionner vos compétences Excel. Les corrigés sont inclus pour…
Excel offre plusieurs méthodes pour calculer une moyenne tout en tenant compte des filtres ou…
Excel propose plusieurs fonctions pour insérer ou manipuler la date actuelle. Voici les principales méthodes…
This website uses cookies.