Vous avez vu qu'il s'agit de sortes de boites noires à qui on fournit des ENTREES et que nous répondent en retour.
ENTREE(S)
⇒
Fonction
⇒
SORTIE
Vous savez actuellement faire appel à ces fonctions. Nous allons voir aujourd'hui comment en créer vos propres fonctions, qui ne seront donc pas des fonctions natives, présentes de base dans Python.
Commençons par vous montrer ce qu'on peut faire assez facilement avec les fonctions.
Téléchargez le code à l'aide de l'image et lancez le. Nous obtenons une animation.
Commençons par revoir ce que vous savez déjà sur les fonctions.
Rappels
(Rappel) 1.1 FONCTION : notion
ENTREE(S)
⇒
Fonction
⇒
SORTIE
Description
Les fonctions sont des instructions particulières qui :
recoivent des données d'entrée et
renvoient leur réponse en sortie.
Un exemple avec la fonction VALEUR_ABSOLUE qui n'attend qu'une entrée (un nombre) et qui renvoie la valeur absolue du nombre (le même nombre mais sans son signe).
-12
⇒
Fonction VALEUR ABSOLUE
⇒
12
12
⇒
Fonction VALEUR ABSOLUE
⇒
12
D'autres exemples
5; 10; 50; 0; 20
⇒
Fonction MAXIMUM
⇒
50
5; 10; 50; 0; 20
⇒
Fonction MINIMUM
⇒
0
5; 10; 50; 0; 20
⇒
Fonction SOMME
⇒
85
(Rappel) 1.2 - FONCTION : native
Une fonction native est une fonction présente de base dans Python.
On en fait l'appel en notant son nom et en fournissant entre parenthèses les entrées séparées par des virgules.
nom_fonction(a, b, c, d...)
Dans le cadre de ce site, les fonctions natives sont toujours écrites en vert.
Fonction VALEUR ABSOLUE : cette fonction se nomme abs() en Python.
>>> abs(-12)12>>> abs(12)12
Fonction MAXIMUM : cette fonction se nomme max() en Python.
La déclaration (mise en mémoire d'instructions pour les utiliser plus tard)
L'appel (utilisation de ces instructions)
A - Déclarer une fonction
Déclarer la fonction revient à stocker ses instructions.
Pour déclarer une fonction, on écrit dans l'ordre
le mot-clé def.
le nom de la fonction
entre parenthèses : les variables d'entrée séparées par des virgules
le caractère :
les instructions du bloc tabulé
1
2
defdouble(x):return2*x
Important : lors de la déclaration, on ne lance aucun appel, on ne fait que mettre en mémoire.
Le mot-clé return permet d'indiquer ce que la fonction devra renvoyer si on l'appelle.
Placer des commentaires en français dans le code Python
On peut placer du texte à destination des developpeurs qui vont lire le programme en utilisant le caractère #. Voir la partie suivante pour un exemple.
Attention : sur votre ligne, tout ce qui se trouve derrière ce # sera purement ignoré par l'interpréteur.
B - Lancer un appel de fonction
Lancer un appel revient à fournir les entrées et attendre la réponse de la fonction.
Ligne 1 : déclaration de nouvelle_note() qui va recevoir une donnée qu'on placera dans note.
Ligne 7 (appel à la fonction nouvelle_note() en lui envoyant 12).
Ligne 1 à 5 : on exécute les lignes avec note contenant 12 initialement. Après la ligne 2, note contient donc 17. Le test de la condition etant alors faux (17 n'est pas supérieur à 20), on passe en ligne 5 : la fonction répond 17
L7 (réception) : on stocke 17 dans n.
Ne zappez pas les rappels si vous ne les avez jamais vu. Sinon, le reste de l'activité risque de vous sembler difficile...
Quelques compléments
1.5 - FONCTION : une déclaration pas à pas
1
2
3
defma_fonction(x):resultat=x * 2returnresultat
Voici comment déclarer une fonction :
On commence la déclaration par le mot-clé def suivi du nom de la fonction. Comme pour les variables, le nom de la fonction doit être explicite : son nom doit permettre de comprendre ce qu'elle réalise.
1
deffois2
on rajoute des parenthèses,
1
deffois2()
entre les parenthèses, on fournit les noms des variables qui vont servir à mémoriser les ENTREES que la fonction va recevoir dans le futur (ici, c'est x).
1
deffois2(x)
On finit cette première ligne par un POINT DOUBLE : signifiant qu'on a fini de fournir le nom et les paramètres d'entrée.
1
deffois2(x):
Les instructions à réaliser par la fonction sont toutes indentées (4 espaces ou touche TAB). C'est comme cela que l'interpréteur Python qu'une instruction appartient à la fonction (ou pas).
1
2
deffois2(x):resultat=x * 2
On finit par return suivi de la réponse qu'on veut renvoyer, ici resultat
1
2
3
deffois2(x):resultat=x * 2returnresultat
J'insiste mais... "Déclarer" n'est pas "Faire appel"
Il faut comprendre qu'après avoir exécuter ces lignes, l'interpréteur Python ne lance pas d'appel à votre fonction. D'ailleurs, il aurait du mal... Que mettrait-il dans x de toutes manières ?
Déclarer la fonction permet juste de mettre ce nom en mémoire pour pouvoir y faire appel plus loin dans le programme.
1.6 return : on peut utiliser directement une expression
Lorsque l'interpréteur rencontre le mot-clé return, il réalise deux choses :
Il évalue l'expression située derrière lui.
Il renvoie la valeur trouvée à l'entité qui a lancé l'appel initialement.
Deux choix de conception :
Stocker d'abord le résultat dans une variable, puis placer ce nom de variable derrière return.
1
2
3
deffois2(x):resultat=x * 2returnresultat
Placer directement l'expression derrière return.
1
2
deffois2(x):returnx * 2
Ici, il est donc inutile de stocker la réponse dans une variable puisque la seule instruction derrière serait de renvoyer le résultat stocké.
return n'est pas une fonction !
Ne placez pas de parenthèses (sauf obligation) derrière le return. Sinon, vous laissez croire qu'il s'agit d'une fonction. Il s'agit bien d'un mot-clé qui renvoie la réponse à celui qui a posé la question.
Beaucoup de questions risquent de vous paraître un peu bête si vous avez vraiment compris le mécanisme des fonctions. Le but ici est bien de casser les mauvaises conceptions mentales, quitte à ouvrir des portes ouvertes.
01° Réaliser les 4 actions suivantes
Ouvrir l'onglet VARIABLES de Thonny pour vérifier que la mémoire est vide initialement
Sauvegarder et lancer le programme suivant sous le nom activite_fonctions.
Vérifier via l'onglet VARIABLES que la mémoire contient maintenant deux nouvelles variables nommées fois2 et plus2.
Le at0x... fait référence à une zone mémoire de stockage et cela devrait donc être différent sur votre machine. Par contre, vous devriez avoir quelque chose de proche à l'écran :
Utiliser ensuite la console pour visualiser que fois2 (juste le nom, sans les parenthèses) ne lance aucun appel mais spécifie que ce nom existe et fait référence à une variable de type function puisqu'elle fait référence à des instructions.
>>> fois2
<function fois2 at 0x7f2d96628af0>>>> type(fois2)
<class 'function'>
Rajoutons maintenant une couche de vocabulaire à connaître.
1.7 FONCTION : paramètre et argument
1
2
3
defvaleur(d, u):# d et u sont les paramètres déclarésresultat=d*10 + ureturnresultat
>>> valeur(5, 3) # 5 et 3 sont les Arguments d'Appel
53
Différence entre paramètre et argument
Il faut savoir distinguer
1a 1er ligne de la déclaration qui contient les variables locales de stockage des entrées qu'on fournira un jour.
Plutôt que de dire les variables locales de stockage d'entrées qu'on fournira un jour", on dira les paramètres.
1
2
3
defvaleur(d, u):# d et u sont les paramètres déclarésresultat=d*10 + ureturnresultat
Ces paramètres dispaissent donc une fois que la fonction a répondu.
son appel qui indique les entrées envoyées à la fonction sur cet appel. Plutôt que de dire les "entrées envoyées à la fonction sur cet appel", on utilisera le mot argument.
>>> valeur(5, 3) # 5 et 3 sont les Arguments d'Appel
53
L'argument n°1 (5) va dans le paramètre n°1 (d), ect...
Cas d'une fonction avec 1 paramètre
1
deffois2(x):<-- x est le paramètre de déclaration
>>> fois2(20) <-- 20 est l'argument de l'appel40
Lors de l'appel, on envoie l'argument 20.
L'argument 20 est alors stocké dans le paramètre x
Cas d'une fonction avec 2 paramètres
1
defvaleur(d, u):<-- d et u sont les paramètres
>>> valeur(5, 3) <-- 5 et 3 sont les arguments de l'appel
Lors de l'appel, on envoie l'argument 5 suivi de l'argument 3.
L'argument 5 est donc stocké dans d et l'argument 3 dans le paramètre u
Moyen mnémotechnique pour les interros
appel (commence par a) : argument (commence par a)
déclaration (commence par d) : paramètre (commence par p, un d à l'envers)
Précision
L'appel peut bien entendu se faire directement dans le programme. C'est même beaucoup plus courant.
1
2
3
4
5
defvaleur(d, u):# d et u sont les paramètres déclarésresultat=d*10 + ureturnresultatvaleur(5, 3) <-- 5 et 3 sont les arguments de l'appel
Paramètre formel et effectif
Il existe une deuxième manière de nommer les choses.
Paramètre formel plutôt que paramètre.
Paramètre effectif plutôt qu'argument.
02° Les fonctions sont maintenant en mémoire. Vous allez maintenant pouvoir faire appel à vos fonctions. Réaliser les appels suivants dans la console de Python, observer les réponses et puis répondre aux questions :
>>> plus2(10)
???
Quel est l'argument envoyé à la fonction plus2() lors de cet appel ?
Quel est alors le contenu affecté au paramètre x lors de cet appel ?
Que va contenir resulat lors de cet appel ?
Quelle est la réponse renvoyée par cet appel de fonction (qui s'affiche puisqu'on en fait rien et que nous travaillons dans la console) ?
>>> plus2(15)
???
Quel est l'argument envoyé à la fonction plus2() lors de cet appel ?
Quel est alors le contenu affecté au paramètre x lors de cet appel ?
Que va contenir resulat lors de cet appel ?
Quelle est la réponse renvoyée par cet appel de fonction (qui s'affiche puisqu'on en fait rien et que nous travaillons dans la console) ?
>>> fois2(10)
???
Quel est l'argument envoyé à la fonction fois2() lors de cet appel ?
Quel est alors le contenu affecté au paramètre x lors de cet appel ?
Que va contenir resulat lors de cet appel ?
Quelle est la réponse renvoyée par cet appel de fonction (qui s'affiche puisqu'on en fait rien et que nous travaillons dans la console) ?
...CORRECTION...
>>> plus2(10)
12
Ici, on voit que l'entrée est 10.
Le paramètre x référence l'entier 10.
La variable resultat référencera 12 après exécution de la ligne 6.
Cet appel renvoie 6.
>>> plus2(15)
17
Cette fois, on envoie 15.
x référence 15.
resulat référence donc 17.
Cet appel renvoie 17.
>>> fois2(10)
20
On envoie une entrée valant 10.
x référence 10.
resultat référence alors 20 (voir ligne 2).
Cet appel renvoie donc 20.
03° Un peu plus complexe que la précédente. Réaliser les appels suivants dans la console de Python, observer les réponses et puis répondre aux questions :
>>> a = plus2(100)
Quel est l'argument envoyé à la fonction lors de cet appel ?
Quel est le contenu affecté au paramètre x lors de cet appel ?
Quelle est la réponse renvoyée par cet appel de fonction ?
Pourquoi n'obtient-on pas d'affichage dans la console ?
>>> b = fois2(a)
Quel est l'argument envoyé à la fonction lors de cet appel ?
Quel est le contenu affecté au paramètre x lors de cet appel ?
Quelle est la réponse renvoyée par cet appel de fonction ?
Pourquoi n'obtient-on pas d'affichage dans la console ?
>>> c = fois2(plus2(10))
Que va évaluer d'abord l'interpréteur Python à cause des priorités ?
Quel est l'argument envoyé à la fonction fois2() lors de cet appel ?
Expliquer le contenu de c.
...CORRECTION...
>>> a = plus2(100)
L'argument envoyé est 100.
x contient donc 100.
La fonction répond donc 102 qu'on affecte à la variable a.
Ici, il y a une affectation dans une variable. La console n'affiche un résultat que si la ligne ne contient que l'évaluation.
>>> b = fois2(a)
L'argument envoyé est a.
x référence donc 102.
La fonction répond donc 204 qu'on affecte à la variable b.
Ici, il y a une affectation dans une variable. La console n'affiche un résultat que si la ligne ne contient que l'évaluation.
>>> c = fois2(plus2(10))
En respectant la priorité des parenthèses, on se rend comppte qu'il faut d'abord évaluer plus2(10).
Python va évaluer plus2(10) à la valeur 12. On envoie donc ce 12 comme argument à fois2().
c récupère donc la valeur évaluée par fois2(12), soit 24.
04° Réaliser les appels suivants qui provoquent tous des erreurs. Pour chaque appel, observer la dernière ligne du message d'erreur de Python et répondre aux questions proposées :
C'est une erreur TypeError. En Python, il s'agit d'une erreur d'exécution.
On envoie 0 argument lors de l'appel alors que la déclaration de la fonction possède UN paramètre. Il manque donc un paramètre.
>>> fois2(10, 20)
TypeError: fois2() takes 1 positional argument but 2 were given
C'est une erreur TypeError. En Python, il s'agit d'une erreur d'exécution.
On envoie 2 arguments lors de l'appel alors que la fonction possède UN paramètre.
>>> fois2 10
SyntaxError: invalid syntax
C'est une erreur de SYNTAXE. Python ne comprend pas l'appel.
L'utilisateur a oublié les parenthèses nécessaires en Python lors de l'appel.
>>> fois2([10])
[10, 10]
Par d'erreur en soi : pas d'erreur de syntaxe, ni d'erreur d'exécution.
Par contre, si l'utilisateur voulait vraiment obtenir un entier multiplié par deux, c'est une erreur de sémantique : il envoie un tableau de 1 case. Python fait son travail, il renvoie un tableau de deux cases identiques.
A l'opérateur * qui possède une signature int * list -> list dont la sémantique est la répétition et pas la multiplication au sens mathématique.
05° Aller sur Python Tutor, et visualiser le déroulé du programme suivant en mode pas à pas.
Lorsqu'on exécute la première fois le bloc de déclaration L1-L2-L3, met-on la fonction en mémoire ou lance-t-on la fonction ?
Chaque appel de fonction dispose-t-il de son propre espace des noms local ou place-t-on les arguments dans l'espace des noms global ?
Que devient un espace des noms local après que la fonction ai répondu ?
Les variables d, u et resultat sont-elles des variables locales ou globales ?
Les variables a, b et c sont-elles des variables locales ou globales ?
...CORRECTION...
On place juste la fonction en mémoire. C'est une déclaration, pas un appel.
Chaque appel de fonction génére son propre espace des noms local et temporaire lui permettant de stocker les arguments reçus dans ses propres paramètres.
Dès qu'une fonction a répondu, l'espace des noms local de cet appel est supprimé puisqu'il ne sert plus à rien.
Les variables d, u et resultat sont des variables locales puisqu'elles appartiennent à l'espace qui disparait.
Les variables a, b et c sont globales puisqu'elles sont déclarées directement dans le programme.
06° Placer la fonction valeur() en mémoire dans Thonny. Utiliser ensuite ceci dans la console :
1
2
3
defvaleur(d, u):resultat=d*10 + ureturnresultat
>>> valeur(2, 6)
26
Question
Expliquer la valeur 26 obtenue sur cet appel en montrant comment on compare l'appel et la déclaration.
...CORRECTION...
1
defvaleur(d, u):
>>> valeur(2, 6)
L'argument 2 est stockée dans le paramètre d.
L'argument 6 est stockée dans le paramètre u.
La fonction calcule donc 2*10 + 6 et renvoie donc 26.
✎ 07° Expliquer la réponse qu'on va obtenir lors de l'appel de la fonction facile() puis plus_difficile() ci-dessous. On vous donne leurs déclarations de la fonction et l'appel voulu dans la console interactive.
Première fonction
1
2
deffacile(x):returnx*10+5
>>> facile(3)
???
Deuxième fonction
1
2
defplus_difficile(x, y, z):returnx*100+y*10 + z
>>> plus_difficile(5, 6, 3)
???
08° Pour valider cette première partie :
Appuyer sur le bouton VISUALISER ci-dessous, pour observer l'ordre d'exécution de ce programme
Expliquer les valeurs finales stockées dans les variables a et b après exécution du code ci-dessous.
Résoudre des problèmes en utilisant des programmes basés sur des algorithmes.
Qu'est-ce qu'un beau programme ?
Point 1 : d'abord des fonctions qui fonctionnent en donnant toujours le bon résultat
On en parlera dans la partie ALGORITHMIQUE.
Point 2 : ensuite des fonctions facilement utilisables
On en parlera un peu aujourd'hui avec la notion de DOCUMENTATION.
Point 3 : ensuite des fonctions dont le code interne est facile à comprendre
On en parlera un peu aujourd'hui avec la notion de COMMENTAIRE.
Point 4 : enfin, des fonctions qui répondent rapidement
On en parlera dans la partie ALGORITHMIQUE.
(Rappel) 2.1 COMMENTAIRES : expliquer le fonctionnement
Les commentaires sont destinés à un lecteur humain et ils visent à rendre le code interne facile à comprendre.
Cela doit permettre de modifier un code même plusieurs années après sa création initiale.
Pour rajouter un commentaire en Python, on utilise le caractère dièse (#) de façon adaptée. Trois exemples à parfaitement comprendre :
Commentaire sur toute une ligne (ligne 1 ci-dessous)
1
# Toute cette ligne est un commentaire.
Commentaire en fin de ligne (ligne 2 ci-dessous)
2
print("Bonjour tout le monde")# Ceci est également un commentaire
Notez bien que la ligne 3 ne comporte aucun commentaire puisque le # fait juste partie d'un string.
3
print("Cette ligne ne contient pas de # commentaire")
Voici le résultat de ce programme L1 à L3 dans la console : il n'affiche pas les commentaires.
1
2
3
# Toute cette ligne est un commentaire.print("Bonjour tout le monde")# Ceci est également un commentaireprint("Cette ligne ne contient pas de # commentaire")
>>> %Run progcommentaires.py
Bonjour tout le monde
Cette ligne ne contient pas de # commentaire>>>
L'interpréteur Python ne tentera pas d'exécuter les commentaires.
Il reste à voir le Point 2 : comment parvenir à créer des fonctions facilement UTILISABLES même si nous n'en sommes pas le créateur.
2.2 DOCUMENTATION : expliquer l'utilisation
2.2.1 Documenter pour utiliser
La documentation doit expliquer comment utiliser la fonction sans provoquer d'erreur.
Si on prend l'analogie de la voiture :
Les commentaires expliquent comment fonctionne la voiture (cours de mécanique, d'électronique...)
La documentation explique comment utiliser la voiture (cours de code et de conduite)
2.2.2 Trouver la documentation
En Python, pour trouver la documentation, il suffit d'utiliser une fonction native : la fonction help().
Imaginons qu'on veuille récupérer la documentation de la fonction native len() : il faut donner le nom de la fonction en tant qu'argument à la fonction type(). Attention, juste le nom, sans les parenthèses. On ne veut pas l'activer.
>>> help(len)
Help on built-in function len in module builtins:
len(obj, /)
Return the number of items in a container.
Première ligne : on voit que len() est une fonction native (build-in).
Help on built-in function len in module builtins:
Deuxième ligne : à qui on doit fournir un seul argument (qui sera rangé dans un paramètre obj visiblement).
len(obj, /)
Troisième ligne : on voit que la fonction va renvoyer le nombre d'éléments contenus dans le conteneur envoyé.
Return the number of items in a container.
2.2.3 Contenu d'une documentation
La documentation contient juste des informations sur
Le but de cette fonction
le type et le nombre d'arguments à lui envoyer (les ENTREES) et
le type et le contenu de la réponse (la SORTIE).
09° Taper ceci dans la console pour récupérer la documentation (écrite par le concepteur de Python) de la fonction bin().
>>> help(bin)
Help on built-in function bin in module builtins:
bin(number, /)
Return the binary representation of an integer.
>>> bin(2796202)
'0b1010101010101010101010'
Nous verrons bientôt à quoi correspond le / dans la documentation. Pour l'instant, faisons comme s'il n'était pas là.
Questions
Dans la documentation, où est-il indiqué que bin() est une fonction native ?
combien d'argument(s) doit-on envoyer à bin() ? De quel(s) type(s) ?
En traduisant la pĥrase de description, expliquer ce que renvoie la fonction (le type et le contenu de la réponse).
...CORRECTION...
Il est noté que bin() est une fonction build-in, "construire à l'interne" en traduction mot à omt.
Un seul de type int. C'est décrit de deux façons : une indication dans la phrase de description et une indication dans l'exemple d'utilisation qu'on trouve en bas de documentation.
La fonction renvoie une représentation de l'entier fourni sous forme binaire, fournie via un string.
Nous allons maintenant voir comment écrire les documentations de vos fonctions personnelles.
2.3 DOCUMENTATION rapide : le prototype + une phrase
1
2
3
defaddition(nbr1:int, nbr2:int) -> int:"""Renvoie la somme de nbr1 et nbr2"""returnnbr1+nbr2
Nous avions vu la signature d'un opérateur (comme +) : int+int->int
Nous allons voir le même principe pour les fonctions.
2.3.1 - Signature d'une fonction
Arguments
⇒
Fonction
⇒
Réponse
Pour pouvoir utiliser une fonction, on a besoin :
de savoir comment elle se nomme.
de savoir combien d'arguments lui envoyer et leurs types.
de savoir ce qu'elle va répondre.
Toute ces informations se retrouvent dans la signature. Par exemple, la signature d'une fonction addition() qui permet d'additionner deux entiers :
addition(int, int) ->int
2.3.2 - Prototype d'une fonction
Prototyper une fonction consiste à rajouter les noms des paramètres à la signature.
addition(nombre1:int, nombre2:int) ->int
Attention : le prototype ne donne pas d'indications sur ce que réalise la fonction. On peut s'en douter en regardant les noms de la fonction et des paramètres si ils sont explicites, mais on ne fait que deviner. On peut donc se tromper.
2.3.3 - Spécification : la documentation minimale d'une fonction
Spécifier une fonction consiste à donner :
Le PROTOTYPE qui fixe la SYNTAXE et le TYPAGE
Une description nommée DOCSTRING qui fixe clairement la SEMANTIQUE
Sous la première ligne du prototype, on rajoute donc un string explicatif :
qu'on place juste sous le prototype,
délimité par trois guillemets d'ouverture et de fermeture.
Exemple
Voilà la spécification de notre fonction-exemple :
1
2
3
defaddition(nbr1:int, nbr2:int) -> int:"""Renvoie la somme de nbr1 et nbr2"""returnnbr1+nbr2
2.3.4 - Obtenir la documentation
La fonction help() ramene les informations fournies dans la documentation.
>>> help(addition)
Help on function addition in module __main__:addition(nbr1: int, nbr2: int) -> int Renvoie la somme de nbr1 et nbr2
10-A° Modifier alors calculer_moyenne() pour qu'elle renvoie la réponse attendue : il faudra lire la documentation pour le savoir.
1
2
3
4
5
defcalculer_moyenne(note1:int, note2:int) -> float:"""Renvoie la moyenne des deux notes envoyées"""return0.0m=calculer_moyenne(10, 20)
Remarquez bien que pour le moment, la fonction renvoie bien une réponse du bon type (un float) mais c'est toujours 0.0 pour l'instant. A vous de faire le travail.
Exemple d'utilisation dans la console interactive (après avoir mis vos modifications de la fonction en mémoire !)
defcalculer_moyenne(note1:int, note2:int) -> float:"""Renvoie la moyenne des deux notes envoyées"""return(note1 + note2)/2m=calculer_moyenne(10, 20)
2.4 DOCUMENTATION longue : le docstring multiligne
2.4.1 Limitation de la documentation rapide
Parfois, la documentation rapide ne suffit pas. Par exemple, cette fonction vitesse() :
1
2
3
defvitesse(distance:int, duree:int) -> float:"""Renvoie la vitesse connaissant la distance parcourue et la durée"""returndistance/duree
Problème 1 : on ne signale pas à l'utilsateur qu'il ne doit surtout pas fournir de durée nulle pour éviter une division par zéro.
Problème 2 : on ne signale pas si il y a des unités attendues pour durée et distance.
2.4.2 Solution : Docstring multiligne
On peut fournir une vraie documentation sur plusieurs lignes.
Il n'existe aucune codification imposée pour cette documentation. Voici les éléments qu'elle doit contenir, quelque soit la façon de l'exprimer :
DESCRIPTION : une description de ce que fait la fonction
PROTOTYPAGE : l'équivalent de la signature et du prototype mais sous forme d'un texte plus libre
PRECONDITION : une explication claire des conditions supplémentaires sur les paramètres d'entrée si certaines valeurs posent problème.
...
1
2
3
4
5
6
7
8
9
defvitesse(distance, duree):"""Renvoie la vitesse connaissant la distance parcourue et la durée
:: param distance(int) :: la distance en m
:: param duree(int) :: la durée NON NULLE en s
:: return (float) :: la vitesse en m.s-1
"""returndistance/duree
10-B° Lire la nouvelle documentation de calculer_moyenne(). Répondre aux questions suivantes :
Sur quelles lignes trouve-t-on les types attendus des deux paramètres ?
Quelles sont les préconditions qu'on trouve dans cette documentation plus longue ?
Sur quelle ligne se trouve l'indication sur le type de la réponse dans cette documentation ?
1
2
3
4
5
6
7
8
9
10
11
defcalculer_moyenne(note1, note2):"""Renvoie la moyenne des deux notes :: param note1(int) :: une note dans [0;20] :: param note2(int) :: une note dans [0;20] :: return (float) :: la moyenne de note1 et note2 """return(note1+note2)/2moy=calculer_moyenne(10, 20)
Enfin, lancer le programme dans Thonny pour vérifier que la fonction fonctionne de la même façon que celui de 10-1 mais que la documentation est juste plus fournie lorsqu'on utilise help().
>>> moy
15.0>>> moy2 = calculer_moyenne(10, 15)
>>> moy2
12.5>>> help(calculer_moyenne)
Help on function calculer_moyenne in module __main__:
calculer_moyenne(note1, note2)
Renvoie la moyenne des deux notes
:: param note1(int) :: une note dans [0;20]
:: param note2(int) :: une note dans [0;20]
:: return (float) :: la moyenne de note1 et note2
...CORRECTION...
Sur quelles lignes trouve-t-on les types attendus des deux paramètres ?
4
5
:: param note1(int) :: une note dans [0;20] :: param note2(int) :: une note dans [0;20]
Quelles sont les préconditions sur les paramètres qu'on trouve dans cette documentation plus longue ?
4
5
:: param note1(int) :: une note dans [0;20] :: param note2(int) :: une note dans [0;20]
Sur quelle ligne se trouve l'indication sur le type de la réponse dans cette documentation ?
6
:: return (float) :: la moyenne de note1 et note2
✎ 11° Compléter les fonctions addition(), multiplication() et division_euclidienne() pour qu'elles fonctionnent correctement. Enregistrer et lancer dans Thonny pour placer cette fonction en mémoire. Faire les appels dans la console pour vérifier le fonctionnement.
defaddition(note1, note2):"""Renvoie la somme des deux notes :: param note1(int) :: une note dans [0;20] :: param note2(int) :: une note dans [0;20] :: return (int) :: la somme de note1 et note2 """return0defmultiplication(x, y):"""Renvoie la multiplication de a par b :: param x(int) :: un entier :: param y(int) :: un entier :: return (int) :: x*y """return0defdivision_euclidienne(a, b):"""Renvoie le quotient et le reste de la division euclidienne de a par b :: param a(int) :: un entier :: param b(int) :: un entier NON NUL :: return (tuple) :: le couple (quotient, reste) """return(0,0)
✎ 12° Placer la fonction en mémoire. Réaliser les appels proposés pour comprendre ce que fait cette fonction.
Question A : écrire la documentation complète (plusieurs lignes) de cette fonction une fois que vous avez compris ce qu'elle fait.
Question B : écrire la documentation en utilisation une documentation rapide (prototype et une seule ligne).
1
2
3
4
5
6
7
8
9
10
importrandomdefde(nb_faces):'''La petite phrase qui va bien :: à faire : décrire le paramètre :: :: à faire : décrire la réponse :: '''returnrandom.randint(1,nb_faces)
>>> import random
>>> help(random.randint)
Help on method randint in module random:randint(a, b) method of random.Random instance
Return random integer in range [a, b], including both end points.
✎ 13° Réaliser la fonction telle qu'elle est spécifiée dans sa documentation :
1
2
3
defest_long(chaine:str)->bool:"""Fonction qui renvoie True si la chaine est d'au moins 6 caractères, False sinon"""pass
Remarque : Une fonction sans instruction provoque une erreur. L'instruction pass porte bien son nom : elle permet de fournir une instruction de façon à ne pas provoquer d'erreur de syntaxe mais cette instruction veut dire "Ne fait rien". On place donc souvent pass comme instruction temporaire.
✎ 14° Réaliser la fonction telle qu'elle est spécifiée dans sa documentation :
1
2
3
4
5
6
7
8
9
10
11
defcontient(chaine1:str,chaine2:str)->bool:"""Prédicat qui renvoie True si chaine1 est bien dans chaine2, False sinon :: exemple .. >>> contient('Bonjour', 'Bon, alors bonjour') False >>> contient('bonjour', 'Bon, alors bonjour') True """pass
Que se passe-t-il lorsque la fonction rencontre un return ?
A quel moment sort-on vraiment de la fonction ?
15° Observer la fonction centaine(). On a demandé à quelqu'un de compléter la fonction suivante pour qu'elle renvoie le chiffre des centaines d'un nombre envoyé en argument. Il a tapé ceci en oubliant de supprimer la ligne qu'on lui avait donné, celle avec le return 0.
1
2
3
4
5
6
7
8
9
10
defcentaine(x):"""Renvoie le chiffre de la centaine de x :: param x(int) :: un entier :: return (int) :: la centaine de x (5 si 1545) """return0mon_petit_calcul=x//100%10returnmon_petit_calcul
Tester la fonction dans la console.
Questions
Pourquoi cette fonction renvoie-t-elle TOUJOURS 0 ?
Modifier la fonction pour qu'elle fonctionne correctement en évitant les étapes superflues.
Si vous ne voyez pas, Python Tutor est votre ami.
...CORRECTION...
On aurait pu croire que la fonction suit son cours et finit par répondre à la fin. Mais non !
Dès qu'on rencontre un return, la fonction renvoie ce qu'on a placé derrière et on sort immédiatement.
Dès qu'on arrive sur la ligne 8, on renvoie 0. Et on sort de la fonction.
Il ne sert strictement à rien de placer des choses sur des lignes qui suivent le return : ces lignes ne seront jamais analysées.
Ici, les lignes 09 et 10 ne servent strictement à rien. C'est comme si vous aviez tapé ceci :
1
2
3
4
5
6
7
8
9
10
defcentaine(x):"""Renvoie le chiffre de la centaine de x :: param x(int) :: un entier :: return (int) :: la centaine de x (5 si 1545) """return0
Après correction, vous devriez avoir ceci :
1
2
3
4
5
6
7
8
defcentaine(x):"""Renvoie le chiffre de la centaine de x :: param x(int) :: un entier :: return (int) :: la centaine de x (5 si 1545) """returnx//100%10
3.1 FONCTION : sortie immédiate avec return
Dès que la fonction rencontre un return :
elle évalue l'expression fournie puis
elle renvoie sa réponse, puis
son espace local des noms est détruit définitivement.
Lorsqu'on rencontre le return, on sort immédiatement. Ok.
Mais...
Et si on ne rencontrait jamais de return ? Que se passe-t-il ?
Nous allons voir que la fonction répond quelque chose quand même et cette réponse est ... vide. Mais une réponse "vide" contient une information : l'information que la fonction est bien terminée puisqu'elle a répondu.
16° Observer le code suivant qui possède une fonction sans return :
1
2
3
defdivision(x:int, y:int):"""Calcule la division entière de x par y, mais n'en fait rien..."""mon_petit_calcul=x//y
Tester la fonction dans la console :
>>> division(7, 2)
>>>
Puisque division(7,2) est la seule chose présente sur la ligne, sa réponse aurait du être transmise dans la console. Or, on constate que rien ne s'affiche. En apparence, la fonction n'a rien répondu.
Une fonction Python renvoie au moins la valeur None lorsqu'elle se termine sans avoir rencontré return.
On parle parfois de procédure pour désigner une fonction qui ne répond rien. Les procédures n'existent donc pas vraiment en Python.
La ligne 4 ci-dessous est donc totalement facultative :
1
2
3
4
defdivision(x:int, y:int) -> None:"""Calcule la division entière de x par y, mais n'en fait rien..."""mon_petit_calcul=x//yreturnNone
3.2.2 Attention au stockage de la réponse...
Il arrive souvent qu'on utilise mal de telles fonctions qui renvoient None si on a lu trop vite la documentation.
Le cas typique vient de la méthode append() qui permet de rajouter une case à la fin d'un tableau Python : elle modifie le tableau mais ne renvoie "rien".
Bonne utilisation
>>> t = [10, 20, 30]
>>> t.append(100)
>>> t
[10, 20, 30, 100]
Mauvaise utilisation
Si quelqu'un l'utilise mal en pensant qu'elle répond en donnant la nouvelle version du tableau, il va écraser le tableau et y placer None !
>>> t = [10, 20, 30]
>>>t = t.append(100)
>>> t
Ici, t contient maintenant None.
3.2.3 None et les booléens
Lorsqu'on veut évaluer un contenu sous forme de booléen, None est considéré comme le cas nul ou vide.
>>> bool(None)
False
Mais attention : None n'est identique à False.
>>> a = None
>>> a == False
False>>> bool(a) == False
True
Cette partie ne comporte aucun attendu du programme de NSI.
Par contre, elle vous permettra de mieux comprendre certains codes que vous pourriez trouver sur le Web et vous simplifier la vie lors de vos projets.
4.1 FONCTION : Paramètres par défaut
4.1.1 Intérêt
Imaginons une fonction qui renvoie un résultat aléaoire compris entre un entier debut et un entier fin :
1
2
3
4
5
6
7
8
9
10
11
importrandomdefaleatoire(debut,fin):"""Renvoie un entier aléatoire entre debut et fin :: param debut(int) :: un entier :: param fin(int) :: un entier SUPERIEUR à debut :: return (int) :: un entier dans [debut, fin] """returnrandom.randint(debut,fin)
Si cette fonction doit simuler un dé, l'entier debut sera toujour 1. Et pourtant, il faut toujours lui fournir cette valeur puisqu'il y a deux arguments à envoyer.
Si on ne met qu'un seul paramètre attendu et qu'on impose que la valeur de départ est toujours 1, on obtient une fonction moins flexible.
Comment avoir le meilleur des deux mondes ?
4.1.2 Paramètres par défaut
On peut donner des valeurs d'arguments par défaut aux fonctions. Si l'utilisateur ne fournit pas de valeurs pour ces paramètres, il sera rempli automatiquement avec la valeur située un signe = dans la déclaration.
1
2
3
4
5
6
7
8
9
10
11
importrandomdefaleatoire(fin,debut=1):"""Renvoie un entier aléatoire entre debut et fin :: param fin(int) :: un entier SUPERIEUR à debut :: param debut(int) :: un entier :: return (int) :: un entier dans [debut, fin] """returnrandom.randint(debut,fin)
On peut alors faire des appels en envoyant la valeur de départ, ou pas.
>>> aleatoire(50, 40)
43>>> aleatoire(50)
12
Attention au positionnement : remarquez bien qu'il faut que les paramètres ayant une valeur par défaut soient positionnés derrière les paramètres sans valeur par défaut. C'est pour cela que debut=1 est déclarée derrière fin.
4.1.3 Documentation
On peut bien entendu continuer à indiquer rapidement le type des paramètres, même avec des valeurs par défaut.
1
2
3
4
5
importrandomdefaleatoire(debut:int=1,fin:int=1):"""Renvoie un entier aléatoire entre debut et fin"""returnrandom.randint(debut,fin)
4.2 FONCTION : Paramètres nommés ou positionnels
4.2.1 Paramètres nommés
Cette fonctionnalité est présente de base dans Python : plutôt que de fournir les arguments dans l'ordre imposé par l'ordre des paramètres dans la déclaration, on peut les fournir comme on le veut, pourvu de tous les fournir.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
importrandomdefsomme_aleatoire(nb,debut,fin):"""Renvoie la somme de x lancés aléatoire entre debut et fin :: param nb(int) :: POSITIF, le nombre de lancés voulus :: param debut(int) :: un entier :: param fin(int) :: un entier SUPERIEUR à debut :: return (int) :: un entier dans [nb*debut, nb*fin] """s=0# Compteur-mémoire de la sommefor_inrange(nb):# Fait l'action nb foiss=s+random.randint(debut,fin)# Incrémente s d'un nombre aléatoirereturns
>>> somme_aleatoire(10, 1, 6) # on demande 10 dés à 6 faces>>> somme_aleatoire(nb=10, debut=1, fin=6) # on demande 10 dés à 6 faces>>> somme_aleatoire(debut=1, fin=6, nb=10) # on demande 10 dés à 6 faces
4.2.2 Paramètres positionnels uniquement
Nommer les paramètres, c'est pratique mais dangereux. Un changement de nom et tous les programmes utilisant l'ancienne version ne fonctionneront plus.
On peut empêcher l'utilisation des paramètres nommés et donc imposer que seul l'ordre de transfert des arguments soit important.
Pour cela, il suffit de rajouter un symbole / dans la liste des paramètres.
Les paramètres à gauche du / sont positionnels uniquement (nb).
Les paramètres à droite du / sont nommables lors de l'appel (debut et (fin)).
>>> somme_aleatoire(10, 1, 6) # on demande 10 dés à 6 faces>>> somme_aleatoire(10, debut=1, fin=6) # on demande 10 dés à 6 faces>>> somme_aleatoire(nb=10, debut=1, fin=6) # ECHEC : on tente de nommer le premier paramètre !TypeError: somme_aleatoire() got some positional-only arguments passed as keyword arguments: 'nb'
4.3 FONCTION : documentation des types structurés
Selon les versions de Python, il est possible, ou pas d'écrire ce que contient un type structuré.
Exemple avec une fonction dont le paramètre doit être un tableau d'entiers.
1
2
deff(x:list[int]):
...
Pour un dictionnaire dont les clés sont des strings et les valeurs sont des integers :
1
2
deff(x:dict[(str, int)]):
...
Si la version de Python que vous utilisez provoque une erreur et que vous ne pouvez pas en changer pour une raison ou une autre, il suffit de modifier la documentation pour fournir qu'un string :
Le principe de fonctionnement d'un programme utilisant le module pyxel est basé sur la séquence suivante qui inclut une boucle infinie :
1 - La fonction init() crée la fenêtre graphique.
2 - La fonction run() active l'alterance infinie ci dessous :
3 - TANT QUE le programme est actif :
On mémorise les actions de l'utilisateur
SI la dernière mise à jour date de plus d'un 1/30e de seconde
On active une fonction controle() qui va
faire appel à des fonctions maj_...() pour mettre à jour les données
On modifie l'affichage (la vue) en faisant appel à actualiser_vue() qui va
faire appel à cls() pour effacer l'écran
faire appel à des fonctions afficher_...() pour afficher des formes à l'écran
Fin du SI
Fin TANT QUE
17 (pyxel)° Vérifier si le module pyxel est installé :
>>> import pyxel
Si cela ne fonctionne pas, installer la bibliothèque pyxel dans Thonny :
Allez dans l'onglet "Outils"
Cherchez "Gérer les paquets"
Lancez la recherche sur pyxel puis activer l'installation
Attendez que l'installation soit totalement effectuée
Validez l'installation en utisant le bouton Fermer
Une fois avoir vérifié que le module soit bien installé, placer en mémoire et lancer le programme suivant.
Vérifier que vous parvennez à faire bouger le vaisseau à l'aide des touches flèches gauche et droite.
Questions
Lignes 16 : le dictionnaire data est-il une variable globale ou locale ?
Lignes 29 : le dictionnaire data est-il déclaré comme un paramètre ?
Lignes 32-36 : l'affectation est-elle faite sur le dictionnaire data ou sur la valeur associée à l'une des clés ? En conséquence, data est-elle une variable locale ou globale dans cette fonction ?
Conséquence : nous savons qu'une fonction n'est pas capable de modifier une variable globale, mais une fonction est-elle capable de modifier le CONTENU d'un conteneur global MUABLE ?
"""Module de présentation des interfaces Homme-machine (ihm) basée sur pyxel On découpe les fonctions en 3 catégories : - celles du CONTROLEUR : la logique liée aux actions de l'utilisateur - celles du MODELE : la gestion des données pures - celles de la VUE : la gestion de ce qu'on montre à l'utilisateur"""# 1 - Importations ==============================importpyxel# 2 - CONSTANTES et variables globales ============================================data={'x':100,'y':50}# Dictionnaire stockant les données modifiables# 3 - FONCTIONS ==================================================================defcontroler_touches():# CONTROLEUR """Fonction qui récupère l'action, modifie les données en conséquence"""ifpyxel.btn(pyxel.KEY_LEFT):actualiser_modele_vaisseau(-1,0)# Modifie en mémoire la position du vaisseauifpyxel.btn(pyxel.KEY_RIGHT):actualiser_modele_vaisseau(1,0)# Modifie en mémoire la position du vaisseaudefactualiser_modele_vaisseau(dx,dy):# MODELE"""Modifie les données du vaisseau pour intégrer le déplacement dx et dy voulu"""data['x']=data['x']+dxifdata['x']>128:data['x']=128ifdata['x']<0:data["x"]=0defactualiser_vue():"""création des objets (30 fois par seconde)"""pyxel.cls(0)# vide la fenetreafficher_vaisseau(data['x'],data['y'])# vaisseau (carre 8x8)defafficher_vaisseau(x,y):# VUE"""Dessine et mémorise un nouveau vaisseau en (x,y)"""pyxel.rect(x,y,8,8,1)# carré 8x8 et en couleur 1# 4 - PROGRAMME PRINCIPAL ============================pyxel.init(128,128,title="Mon premier jeu")pyxel.run(controler_touches,actualiser_vue)
...Correction...
Lignes 16 : data est une variable globale puisque déclarer dans le programme lui-même.
Lignes 29 : le dictionnaire data ne fait pas partie des paramètres transmis.
Lignes 32-36 : l'affectation est faite sur le contenu du dictionnaire. On ne fait que modifier le contenu du dictionnaire. En conséquence, data est toujours la variable globale.
Conséquence : on constate donc que
une fonction n'est pas capable de modifier un conteneur global (on ne peut pas modifier le meuble) mais
une fonction peut modifier le contenu d'un conteneur global : si on sait où se trouve une armoire, on peut y aller et modifier son contenu.
18 (pyxel)° Expliquer si la variable data est une variable globale ou locale dans la fonction actualiser_vue() ?
...Correction...
Le nom data n'apparaît pas en tant que paramètre et il n'y a aucune affectation directe sur data. Il s'agit donc d'une variable globale.
Dans cette fonction, on utilise le nom de cette variable pour obtenir son adresse puis lire son contenu.
(Rappel) 5.1 Principe du programme tkinter
Le principe de fonctionnement d'un programme utilisant le module tkinter est basé sur la séquence suivante qui inclut une boucle infinie :
1 - La fonction Tk() crée la fenêtre graphique.
2 - La méthode bind() permet de faire le lien entre un événement et une fonction de contrôle controle_xxx() de l'événement
3 - La méthode mainloop() lance la surveillance en boucle des événements
4 - TANT QUE le programme est actif :
SI l'utilisateur appuie sur une touche, on active la fonction controle_xxx() correspondante qui va
D'abord déterminer comment faire appel aux fonctions maj_xxx() pour modifier les modèles
Ensuite demander à modifier l'affichage (la vue) en faisant appel à actualiser_vue() qui va
faire appel à delete() pour effacer l'écran
faire appel à des fonctions afficher_...() pour afficher des formes à l'écran
Fin du SI
Fin TANT QUE
17 (tkinter)° Vérifier si le module tkinter est installé :
>>> import tkinter
Si cela ne fonctionne pas, installer la bibliothèque tkinter dans Thonny :
Allez dans l'onglet "Outils"
Cherchez "Gérer les paquets"
Lancez la recherche sur tkinter puis activer l'installation
Attendez que l'installation soit totalement effectuée
Validez l'installation en utisant le bouton Fermer
.
Une fois avoir vérifié que le module soit bien installé, placer en mémoire et lancer le programme suivant.
Vérifier que vous parvenez à faire bouger le vaisseau à l'aide des touches flèches gauche et droite.
Questions
Lignes 17 : le dictionnaire data est-il une variable globale ou locale ?
Lignes 34 : le dictionnaire data est-il déclaré comme un paramètre ?
Lignes 37-41 : l'affectation est-elle faite sur le dictionnaire data ou sur la valeur associée à l'une des clés ? En conséquence, data est-il une variable locale ou globale ?
Conséquence : nous savons qu'une fonction n'est pas capable de modifier une variable globale, mais une fonction est-elle capable de modifier le CONTENU d'un conteneur global MUABLE ?
"""Module de présentation des interfaces Homme-machine (ihm) basée sur tkinter On découpe les fonctions en 3 catégories : - celles du CONTROLEUR : la logique liée aux actions de l'utilisateur - celles du MODELE : la gestion des données pures - celles de la VUE : la gestion de ce qu'on montre à l'utilisateur"""# 1 - Importations ==============================fromtkinterimportTk# pour créer la fenetre de jeufromtkinterimportCanvas# pour créer la zone de dessin# 2 - CONSTANTES et variables globales ============================================data={'x':100,'y':50}# Dictionnaire stockant les données modifiables# 3 - FONCTIONS ==================================================================defcontroler_touches(evenement):# CONTROLEUR """Fonction qui récupère l'action, modifie les données en conséquence puis la vue"""touche=evenement.keysym# touche utilisée (Left, Right, Up, Left)iftouche=="Left":# Si l'utilisateur appuie sur FLECHE LEFTactualiser_modele_vaisseau(-3,0)# Modifie en mémoire la position du vaisseauiftouche=="Right":actualiser_modele_vaisseau(3,0)# Modifie en mémoire la position du vaisseauactualiser_vue()defactualiser_modele_vaisseau(dx,dy):# MODELE"""Modifie les données du vaisseau pour intégrer le déplacement dx et dy voulu"""data['x']=data['x']+dxifdata['x']>500:data['x']=500ifdata['x']<0:data["x"]=0defactualiser_vue():# VUE"""Efface puis dessine la nouvelle vue"""plateau.delete("all")# Efface les dessins dans le canvasafficher_vaisseau(data['x'],data['y'])defafficher_vaisseau(x,y):# VUE"""Dessine et mémorise un nouveau vaisseau en (x,y)"""plateau.create_rectangle(x,y,x+20,y+20,fill="blue",width=0)# 4 - PROGRAMME PRINCIPAL ============================fenetre=Tk()# Référence de la fenètre graphiquefenetre.title("Mon premier jeu")fenetre.geometry("600x600")plateau=Canvas(fenetre)# Référence de la zone du plateau de jeuplateau.configure(width=500)plateau.configure(height=500)plateau.configure(bg="ivory")plateau.place(x=50,y=50)actualiser_vue()# Dessine le vaisseau à la position initialefenetre.bind("<Any-KeyPress>",controler_touches)# Lie le clavier à la fonction fourniefenetre.mainloop()# Lance la surveillance des événements
...Correction...
Lignes 17 : data est une variable globale puisque déclarer dans le programme lui-même.
Lignes 34 : le dictionnaire data ne fait pas partie des paramètres transmis.
Lignes 37-41 : l'affectation est faite sur le contenu du dictionnaire. On ne fait que modifier le contenu du dictionnaire. En conséquence, data est toujours la variable globale.
Conséquence : on constate donc que
une fonction n'est pas capable de modifier un conteneur global (on ne peut pas modifier le meuble) mais
une fonction peut modifier le contenu d'un conteneur global : si on sait où se trouve une armoire, on peut y aller et modifier son contenu.
18 (tkinter)° Expliquer si la variable data est une variable globale ou locale dans la fonction actualiser_vue() ?
...Correction...
Le nom data n'apparaît pas en tant que paramètre et il n'y a aucune affectation directe sur data. Il s'agit donc d'une variable globale.
Dans cette fonction, on utilise le nom de cette variable pour obtenir son adresse puis lire son contenu.
19 ✎° Compléter maintenant la fonction controler_touches() pour qu'on puisse faire les bons appels en cas d'appui sur les touches UP et DOWN.
Attention, le système ne marchera qu'après la question 20.
20 ✌° Compléter enfin la fonction actualiser_modele_vaisseau() pour qu'on puisse gérer les données liées à la coordonnée y.
5.2 FONCTION : interaction avec une variable globale référençant un type structuré
Une fonction peut ACCEDER à une variable globale.
Une fonction ne peut PAS MODIFIER UNE VARIABLE GLOBALE.
Une fonction peut MODIFIER LE CONTENU d'un CONTENEUR MUABLE GLOBAL
Si la variable globale fait référence à un type structuré, la fonction peut donc accéder à la localisation de la structure. Une fois sur place, elle pourra donc MODIFIER LE CONTENU de la structure, alors qu'elle ne pas peut modifier la structure.
J'ai entendu parler de routine, de procédure. C'est quoi ?
Le mot fonction est utilisé de façon assez générique dans Python. Par contre en informatique, il existe des entités qui peuvent être gérées de façon différente selon les langages.
Le vrai mot générique pour parler d'une suite d'instructions mémorisées et à laquelle on peut faire appel de nombreuses fois est le mot routine.
On distinguera deux types de routine :
Si la routine ne renvoie rien (pas de return), on parle de procédure.
Si la routine renvoie bien quelque chose vers le programme d'appel, on parle de fonction.
Du coup, les vraies procédures n'existent pas en Python : même si votre fonction ne renvoie rien, elle renvoie None. Cela permet de savoir que la fonction n'a rien renvoyé mais ce n'est pas vraiment ...rien... En effet, si la variable reponse existe et contient None, nous avons appris quelque chose : notre fonction est terminée.
On peut détruire une variable ?
Oui, on peut libérer la place mémoire attribuée à une variable. Pour cela, il faut utiliser le mot-clé del.
Exemple :
>>> a = 5
>>> a
5>>> del a
>>> a
NameError: name 'a' is not defined
Activité publiée le 28 08 2019
Dernière modification : 15 07 2023
Auteur : ows. h.