Salut à toi, élève de NSI, comment puis-je t'aider ?
Voila quelques essais d'un élève pour écrire une fonction qui modifie le score d'un joueur dans un jeu :
l'instruction print
à la ligne 6 affiche la valeur de score telle qu'elle était avant l'appel de la fonction :
score n'a donc pas du tout été modifiée lors de cet appel....
Tout se passe comme si il y avait en fait deux variables score différentes dans ce code, l'une dans la fonction, et l'autre en dehors...
Bon...je n'ai qu'à essayer d'affecter directement à la variable score la valeur de celle dans la fonction, en lui donnant un autre nom :
Ah, maintenant j'ai une erreur...on dirait que je ne peux pas "accéder" à la variable sc depuis "l'extérieur" de la fonction....
Je sais ! Je vais directement modifier la variable score dans la fonction, sans la passer en argument :
Non, ça ne fonctionne toujours pas...comment interpréter tout cela ??
Selon l'endroit du code où elles ont été définies ( = initialisées ), les variables n'ont pas la même portée, c'est à dire la (ou les) partie(s) du code où elles sont effectivement accessibles( = utilisables ) :
Les variables définies dans une fonction sont appelées variables locales. Elles ne peuvent être utilisées que localement c’est-à-dire qu’à l’intérieur
de la fonction qui les a définies.
En fin de fonction, ces variables sont "effacées" par Python et n'existent plus en dehors de la fonction : tenter d’appeler une variable locale depuis l’extérieur de la fonction qui l’a définie provoquera donc une erreur.
Les paramètres d'une fonction sont par définition des variables locales ( comme le paramètre score dans le premier exemple ci-dessus ).
Les variables définies ( = initialisées ) dans le programme principal du script, c’est-à-dire en dehors de toute fonction, sont appelées des variables globales.
On peut légitiment penser que la portée d'une variable globale est le script tout entier, fonctions y comprises; c'est le cas, mais à moitié seulement :
multiplier_score
( ligne 11 ) ne pose pas de problème, ce qui signifie que la fonction a pu "lire" sans problème le contenu
de la variable b, variable globale.ajouter_score
( ligne 12 ) provoque par contre une erreur, à la ligne 5, c'est à dire où on a essayé de modifier la variable globale b.Les variables globales sont donc accessibles (= utilisables) à travers l’ensemble du script, mais en lecture seulement à l’intérieur des fonctions utilisées dans ce script.
Une fonction va pouvoir utiliser la valeur d’une variable définie globalement mais ne va pas pouvoir modifier sa valeur, c’est-à-dire la redéfinir; si on essaie de redéfinir une variable globale à l’intérieur d’une fonction, on ne fera que créer une autre variable de même nom que la variable globale qu’on souhaite redéfinir mais qui sera locale et bien distincte de cette dernière ( comme la variable score dans le premier exemple ci-dessus ).
Mais il est (de loin !) préférable de donner des noms différents aux variables locales et aux variables globales, même si celles-ci contiendront la même information; c'est une bonne pratique, qui facilite ( grandement ! ) le débogage et la maintenance d'un code...
NameError: name 'XXX' is not defined
).UnboundLocalError: cannot access local variable 'XXX'
where it is not associated with a value
).Et alors, comment résoudre notre problème : pouvoir modifier dans une fonction la valeur du score du joueur ??
Une solution serait d'utiliser le mot-clé global
dans la fonction, qui lui indique que ce que l'on veut modifier est bien la variable globale score, et pas une hypothétique
variable locale qui n'existe en fait pas :
Et là, ça marche ! Cependant, notez bien que l'on conseille d'éviter au maximum ce genre d'usage des variables globales, c'est un véritable nid à problèmes très difficiles à résoudre...
Méthode préférable : on peut très bien s'en passer, en passant la variable globale en argument, et en récupérant la valeur modifiée de la variable comme résultat, que l'on réaffecte alors dans le programme principal à la variable globale :
Vous allez essayer de réutiliser cette notion de portée de variable sur un exemple plus complexe.
Le programme ci-dessous implémente le jeu de Nim, qui se joue à deux joueurs : partant d'un tas de N allumettes ( par exemple ), chaque joueur, à tour de rôle, ne peut prendre que 1, 2 ou 3 allumettes du tas; le gagnant est celui qui prend la dernière allumettes du tas.
Vous devez corriger le code ci-dessous afin qu'il s'exécute correctement, en pensant bien aux conseils donnés ci-dessus ( pas de variable globale, nom des variables différents dans les fonctions et dans le programme principal,...)
Attention, ce code ne fonctionnera pas dans l'éditeur ci-dessous ( utilisation de la fonction input
).
Exécutez ce script sous Pyzo.
Votre but : résoudre toutes les erreurs rencontrées à l'exécution du script, et pouvoir faire une partie avec votre voisin. Trouverez-vous la stratégie gagnante ??