Outils pour utilisateurs

Outils du site


nsi:premiere:definition_fonctions

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
nsi:premiere:definition_fonctions [2021/06/21 11:48] goupillwikinsi:premiere:definition_fonctions [2024/08/21 16:21] (Version actuelle) goupillwiki
Ligne 1: Ligne 1:
-====== Fonctions : Définition et syntaxe Python ======+====== Fonctions : organiser le code ====== 
 + 
 +{{ :nsi:premiere:python:fonctions.eleves.pdf |Fiche élève à imprimer}} -- [[https://diapo.goupill.fr/fonctions_organiser.html|Diaporama]]
  
 <WRAP tip>On a dit qu'un programme était la traduction d'un algorithme dans un langage de programmation. Ce n'est pas tout à fait exact. Il est plus juste de dire que le programme traduit un **ensemble d'algorithmes**, chaque algorithme réalisant une fonction. Un programme ordinaire est donc constitué de fonction chacune réalisant une petite partie du travail.</WRAP> <WRAP tip>On a dit qu'un programme était la traduction d'un algorithme dans un langage de programmation. Ce n'est pas tout à fait exact. Il est plus juste de dire que le programme traduit un **ensemble d'algorithmes**, chaque algorithme réalisant une fonction. Un programme ordinaire est donc constitué de fonction chacune réalisant une petite partie du travail.</WRAP>
Ligne 5: Ligne 7:
 <WRAP important>Quand les programmes sont très simples, il peut paraître inutile de s'embarrasser avec trop d'organisation. Mais notre but est d'apprendre de bonnes méthodes de façon à pouvoir plus tard envisager des programmes plus ambitieux. Le découpage du programme en fonction est alors **INDISPENSABLE**. D'ailleurs, l'essentiel de votre travail de programmation va vite être d'écrire des fonctions ou de les compléter.</WRAP> <WRAP important>Quand les programmes sont très simples, il peut paraître inutile de s'embarrasser avec trop d'organisation. Mais notre but est d'apprendre de bonnes méthodes de façon à pouvoir plus tard envisager des programmes plus ambitieux. Le découpage du programme en fonction est alors **INDISPENSABLE**. D'ailleurs, l'essentiel de votre travail de programmation va vite être d'écrire des fonctions ou de les compléter.</WRAP>
  
-====== Définition ======+===== Besoin d'organisation =====
  
-{{ :nsi:premiere:fonction.png?nolink&400 |}}+==== Un programme mal écrit ====
  
-Il s'agit d'un bloc de programme qui s'**exécute sur demande**. Lors de sa définition, on précise s'il faut lui fournir des entrées et s'il fournit en réponse des résultats en sortie.+Prenons un programme mal écrit :
  
-Quand une fonction n'pas de sortie, on peut la qualifier de **procédure**, même si ce terme technique n'pas grande importance.+<code python linenums> 
 +x = int(input()) 
 +y = int(input()) 
 += x 
 +b = y 
 +while  % b != 0: 
 +    r = a % b 
 +    a = b 
 +    b = r 
 +z = b 
 +print(x//z) 
 +print(y//z) 
 +</code>
  
-==== Une fonction traduit un algorithme ====+  * Celui qui écrit le programme est encore dans son idée, il se comprend peut-être... mais dès qu'il oublie un peu, il ne se comprend plus lui-même ! 
 +  * Pour un autre, la compréhension de ce programme demandera beaucoup d'efforts alors qu'il est très simple.
  
-Reprenons l'exemple de l’[[nsi:premiere:alkwarizmi|algorithme de Al-Kwarizmi]].+**Le programmeur doit faire un effort de lisibilité !**
  
-<code lang-none linenums> +==== Mieux nommer les variables ====
-ENTRÉES : a et b, réels positifs +
-SORTIE : solution réelle positive de x^2 + a * x +
-DÉBUT +
-    RENVOYER (racine(a^2 + 4*b) - a) / 2 +
-FIN +
-</code> +
- +
-Les termes **entrées** / **sortie** montrent bien la proximité entre les idées d'algorithme et de fonction.+
  
-==== Syntaxe Python ====+Les variables doivent être mieux nommées pour qu'on sache ce qu'elles signifient. On peut aussi rendre les ''print'' et ''input'' plus explicites.
  
 <code python linenums> <code python linenums>
-def extraire_solution(ab)+num = int(input("Numérateur : ")) 
-    return (sqrt(a**2 + 4*b) - a2+den = int(input("Dénominateur : ")) 
 += num 
 += den 
 +while  a % b != 0
 +    r = b 
 +    = b 
 +    b = r 
 +d = b 
 +print(f"Fraction réduite : {num//d}/{y//d}");
 </code> </code>
  
-  * Le mot clé ''%%def%%'' introduit la définition, +C'est un peu mieux.
-  * La ligne de ''%%def%%'' se termine par ''%%:%%'', donc indentation après, +
-  * ''%%return%%'' est le mot-clé pour ''%%RENVOYER%%''.+
  
-> Notez au passage que le carré est noté ''%%**2%%'' en Python. Pour disposer de la fonction ''%%sqrt%%'' (square-root racine carrée) il faudra au préalable aller la chercher dans la bibliothèque de fonction mathématique : ''%%from math import sqrt%%''.+==== Extraire la fonction ====
  
-<WRAP info> +Le programme contient un calcul basé sur le ''while''. On peut l'extraire pour le mettre en évidence.
-En définissant la fonction, on lui donne un nom -- ici ''%%extraire_solution%%'' -- et on précise les entrées -- ou arguments -- ici ''%%a%%'' et ''%%b%%''. La ligne de définition est appelée la **signature** de la fonction. +
-</WRAP>+
  
-==== Bien nommer la fonction ====+<code python linenums> 
 +def ma_fonction(a,b): 
 +    while  a % b !0: 
 +        r  % b 
 +        a b
 +        b 
 + return b
  
-Il faut choisir un nom expressifpas ''%%f%%'' ou ''%%fonction%%'' qui ne disent rien. Le nom est choisi de façon à dire ce que fait la fonction. Icielle extrait la solution d'une équationil est donc naturelle de l'appeler "extraire solution". Mais on n'a pas le droit aux espaces dans les noms de variables ou de fonctions. Dans ces cas là, il existe des conventions pour harmoniser les pratiques.+num = int(input("Numérateur : ")) 
 +den = int(input("Dénominateur : ")) 
 +d = ma_fonction(numden) 
 +print(f"Fraction réduite : {num//d}/{y//d}"); 
 +</code> 
 + 
 +On peut améliorer les choses en nommant convenablement la fonction. 
 + 
 +<code python linenums> 
 +def pgcd(a,b): 
 +    while  a % b != 0: 
 +        r  % b 
 +        a = b= a 
 +        b = r 
 + return b 
 + 
 +num = int(input("Numérateur : ")) 
 +den = int(input("Dénominateur : ")) 
 += pgcd(numden) 
 +print(f"Fraction réduite : {num//d}/{y//d}"); 
 +</code>
  
 <WRAP tip> <WRAP tip>
 Conventions pour les noms en plusieurs mots : Conventions pour les noms en plusieurs mots :
-  * ''%%snake_case%%'', la [[https://fr.wikipedia.org/wiki/Snake_case|casse du serpent]] : tout en minuscule, mots séparés par ''%%_%%''. Pour l'exemple ''%%extraire_solution%%''. C'est la convention recommandée en Python. +  * ''%%snake_case%%'', la [[https://fr.wikipedia.org/wiki/Snake_case|casse du serpent]] : tout en minuscule, mots séparés par ''%%_%%''. Pour l'exemple ''%%calcule_pgcd%%''. C'est la convention recommandée en Python. 
-  * ''%%camelCase%%'', la [[https://fr.wikipedia.org/wiki/Camel_case|casse du chameau]] : changement de mot avec une majuscule. Pour l'exemple ''%%extraireSolution%%''.+  * ''%%camelCase%%'', la [[https://fr.wikipedia.org/wiki/Camel_case|casse du chameau]] : changement de mot avec une majuscule. Pour l'exemple ''%%calculePgcd%%''.
 </WRAP> </WRAP>
  
-==== Commenter la fonction ====+=== Signature ===
  
-Il est recommandé d'ajouter des commentaires juste après la signature de façon à expliciter l'usage de la fonction.+<code python linenums:1> 
 +def pgcd(a,b): 
 +</code>
  
-<code python linenums> +Cette ligne est la définition de la fonction. Elle indique le **nom** de la fonction et elle indique les entrées nécessaires. 
-def extraire_solution(a, b): + 
-    ""+{{ :nsi:premiere:python:pgcd.png?nolink&400 |}} 
-    a, b: réels positifs + 
-    renvoie la solution réelle positive de l'équation x**2 + a x +=== principal === 
-    """ + 
-    return (sqrt(a**2 + 4*b) - a) / 2+<code python linenums:8
 +num = int(input("Numérateur : ")) 
 +den int(input("Dénominateur : ")) 
 +d = pgcd(num, den) 
 +print(f"Fraction réduite : {num//d}/{y//d}");
 </code> </code>
  
-==== Typer entrées et sorties ====+Ces lignes constituent la partie principale du programme. À la ligne 10 notamment, on appelle la fonction ''pgcd''. C'est là qu'elle s'exécute.
  
-On peut ajouter des informations de types sur les entrées et sorties. Icinous n'avons que des réelsce que l'on notera ''%%float%%''.+<WRAP important>Lors de la définitionavec ''def'', la fonction ne s'exécute pas. Si dans un programme on ne fait que définir des fonctionsalors à l'exécution il ne fera rien.</WRAP> 
 + 
 +=== Documenter la fonction === 
 + 
 +On appelle **documentation** le bloc de texte que l'on écrit sous la signature :
  
 <code python linenums> <code python linenums>
-def extraire_solution(a:float, b:float-> float:+def pgcd(a, b):
     """     """
-    ab: réels positifs + a: entier 
-    renvoie la solution réelle positive de l'équation x**2 + x = b+        b: entier non nul 
 + renvoie le pgcd de ab
     """     """
-    return (sqrt(a**2 + 4*b) - a) / 2+    while  != 0: 
 +        r  % b 
 +        = b= a 
 +        b = r 
 + return b
 </code> </code>
  
-==== Préconditions ====+Vous **devez** documenter vos fonctions.
  
-S'il est important de vérifier que les préconditions sont bien remplies, on peut forcer une vérification grâce au mot-clé ''%%assert%%''.+=== Typer ===
  
-> En mathématique, une assertion est une déclaration que l'on tient pour vraie.+On peut indiquer dans la signature les types des entrées et sorties de la fonction. Ce n'est pas obligatoire et n'est pas exigé en NSI. C'est bien de le faire du moment que cela reste simple.
  
 +<code python linenums>
 +def pgcd(a:int,b:int) -> int:
 +    ...
 +</code>
  
 +==== Modulariser ====
 +
 +On peut pousser l'organisation une étape plus loin en plaçant la fonction dans un **module** séparé.
 +
 +<WRAP group>
 +<WRAP half column>
 <code python linenums> <code python linenums>
-def extraire_solution(a:float, b:float) -> float:+# monmodumle.py 
 + 
 +def pgcd(a:int, b:int) -> int:
     """     """
-    ab: réels positifs + a: entier 
-    renvoie la solution réelle positive de l'équation x**2 + x = b+        b: entier non nul 
 + renvoie le pgcd de ab
     """     """
-    assert >= 0 +    while  % b != 0: 
-    assert >= 0 +        
-    return (sqrt(a**2 + 4*b) - a) / 2+        ba 
 +        b = r 
 + return b
 </code> </code>
 +</WRAP>
  
 +<WRAP half column>
 +<code python linenums>
 +# main.py
 +from monmodule import pgcd
  
-===== Exécution =====+num int(input("Numérateur : ")) 
 +den int(input("Dénominateur : ")) 
 +pgcd(num, den) 
 +print(f"Fraction réduite : {num//d}/{y//d}"); 
 +</code> 
 +</WRAP> 
 +</WRAP>
  
-==== Définir n'est pas exécuter ====+Ainsi, le principal est très lisible. On comprend en un coup d'œil ce qu'il fait.
  
-Si le programme entier est : +===== Avantages ===== 
-<code python linenums+ 
-# ceci est la totalité du programme +Les fonctions ont bien des avantages. 
-def extraire_solution(ab): + 
-    """ +  * évitent les répétitions 
-    ab: réels positifs +  * facilitent les tests automatiques 
-    renvoie la solution réelle positive de l'équation x**2 + x = b+  * les variables utilisées n'existent que le temps nécessaire. 
 +  * facilitent le travail à plusieurs 
 +  * simplifient la structure 
 +  * modularisation 
 + 
 +==== return !!! ==== 
 + 
 +  * Une fonction ne contient **jamais** de ''print''... 
 +  * **SAUF** si la fonction est fait exprès pour l'affichage. 
 +  * La sortie d'une fonction est faite par ''return'' 
 + 
 +<WRAP tip
 +  * Certaines fonctions peuvent ne rien renvoyer et ne contenir aucun ''return'' (toutefois en Pythonune fonction renvoie ''none'' à défaut d'autre chose
 +  * Après l'exécution d'un ''return'', la fonction se termine immédiatement. 
 +  * Il peut y avoir plusieurs ''return'' dans une fonction. C'est d'ailleurs très pratique. 
 +</WRAP> 
 + 
 +==== assert comme précondition ==== 
 + 
 +''assert'' permet d'indiquer une condition qui **doit** être vérifiée. 
 + 
 +<code python> 
 +# monmodule.py 
 +def pgcd(a:int,b:int) -> int:
     """     """
-    return (sqrt(a**2 + 4*b) - a) / 2+ renvoie le pgcd de et b 
 + """ 
 + assert b != 0 
 + ...
 </code> </code>
  
-Alors à l'exécution, ce programme **ne fait rien**. En lisant ce programme, l'interpréteur Python se contente de noter qu'une fonction nommée ''%%extraire_solution%%'', demandant deux arguments, est définie des lignes 2 à 7.+Indique clairement la condition à laquelle la fonction fait son travail correctement.
  
-==== Demande d'exécution ====+==== assert comme test élémentaire ====
  
-<code python linenums> +On sait **d'avance** que ''pgcd(15,35== 7''. On peut s'en servir comme test simple vérifiant que la fonction fait bien son travail.
-# ceci est la totalité du programme +
-def extraire_solution(a, b): +
-    """ +
-    a, b: réels positifs +
-    renvoie la solution réelle positive de l'équation x**2 + a x = b +
-    """ +
-    return (sqrt(a**2 + 4*b- a) / 2+
  
-x = extraire_solution(1039+<code python> 
-print(x)+# monmodule.py 
 +def pgcd(a:int,b:int-> int: 
 +    """ 
 + renvoie le pgcd de a et b 
 + """ 
 + ... 
 +  
 +assert pgcd(15,35== 5
 </code> </code>
  
-  * Ligne 2, l'interpréteur note qu'il y a une définition pour ''%%extraire_solution%%'' et passe à la suite, ligne 8+C'est même une bonne idée de multiplier ces tests en essayant les cas bizarres
-  * Ligne 9, l'interpréteur exécute ce qui est à droite de ''%%=%%'' : + 
-    * fonction ''%%extraire_solution%%'' reconnue avec les arguments ''%%10%%'' et ''%%39%%'' +<code python> 
-    * exécution de la fonction, retour à la ligne en prenant ''%%a = 10%%'' et ''%%b = 39%%'', +assert pgcd(2*3*3*7*11*233*7*23*17*17*13== 3*7 
-    ligne 7, le calcul ''%%(sqrt(a**2 + 4*b- a) / 2%%'' donne ''%%3%%''. La fonction renvoie ''%%3%%'' +assert pgcd(0,5) == 5 
-    * Retour à la ligne 9. L'exécution de la fonction a produit le nombre ''%%3%%''. Donc ''%%x 3%%'', +</code>
-  * ligne 10, l'affichage de ''%%x%%'' conduit à l'affichage de ''%%3%%''.+
  
 ==== Les parenthèses sont signe de fonction ==== ==== Les parenthèses sont signe de fonction ====
Ligne 147: Ligne 250:
 </code> </code>
  
-''%%z%%'' est un nombre entier -- ''%%int%%'' -- mais le fait d'écrire ensuite ''%%z()%%'' fait que python essaie de comprendre ''%%z%%'' comme une fonction. Un entier ne peut pas être appelé comme une fonction, c'est le sens du message d'erreur.+''%%z%%'' est un nombre entier -- ''%%int%%'' -- mais le fait d'écrire ensuite ''%%z()%%'' fait que Python essaie de comprendre ''%%z%%'' comme une fonction. Un entier ne peut pas être appelé (//called//comme une fonction, c'est le sens du message d'erreur.
  
  
nsi/premiere/definition_fonctions.1624268887.txt.gz · Dernière modification : de goupillwiki