Semaine Prochaine et TP TP de rattrapage Programmation Impérative Fonctions, etc lundi 8h, H104 pour ceux qui n'ont pas atteint 10 (obligatoire) un TP « classique » Séance de TP suivante mercredi continuer le TP5 (chomp) rendu final avant le TP6 NB: les TP suivants seront de moins en moins guidés 6 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Retours sur les examens Programmation Impérative 7 : Plan Notes par email Infos Statistiques Fonctions en Python moyenne : 10.85 écart type : 2.93 médiane : 10.37 Fonctions et Programmes Fonctions Comme Outils d'Abstraction But de calibration avoir une idée de ce qui est attendu rien n'est perdu/gagné le suivant ne sera pas plus simple Technique de la Fonction Principale Technique de la Simulation Fonctions Récursives et Pile d'Appels 7 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc 8 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Fonctions en Python Les bibliothèques fournissent des fonctions Il est possible d'écrire ses propres fonctions éviter de se répéter, éviter le copier/coller Qu'est ce qu'une fonction un nom et une liste de noms de paramètres un corps (suite d'instructions) possiblement une valeur retournée (avec return ) Définie suivant le modèle 1 2 3 4 5 def «nom» ( «liste-param» ): "documentation de la fonction, «instr» # dans le corps de la «instr» # dans le corps de la … # dans le corps de la optionnelle" fonction fonction fonction Définir une fonction ne l'exécute pas 1 2 3 4 5 6 def meteo(temperature): if temperature > 0: print("Il fait bon") else: print("Il fait froid") Qu'affiche le programme suivant ? ⇒ RIEN Le corps de la fonction n'est exécuté que lorsqu'on l'appelle 1 2 3 4 5 6 7 8 def meteo(temperature): if temperature > 0: print("Il fait bon") else: print("Il fait froid") meteo(4) meteo(-10) def , ( , ) , : et l'indentation sont obligatoires Dans «liste-param», les noms de variables séparés par des , 9 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc 10 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Définition et appel de fonction 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def norme(x, y): d = x**2 + y**2 return d ** 0.5 # Appel 1 print(norme(3, 4)) # Appel 2 print(norme(40, 30)) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Programmation Impérative 7 : Plan # Juste se rappeler # ... que norme existe a1_x a1_y a1_d a1 = Infos Fonctions en Python = 3 = 4 = a1_x**2 + a1_y**2 a1_d ** 0.5 Fonctions et Programmes Fonctions Comme Outils d'Abstraction print(a1) a2_x a2_y a2_d a2 = Technique de la Fonction Principale Technique de la Simulation = 40 = 30 = a2_x**2 + a2_y**2 a2_d ** 0.5 Fonctions Récursives et Pile d'Appels print(a2) NB chaque appel de fonction a ses propres variables x et y chaque appel de fonction a sa propre variable d return donne la valeur par laquelle sera remplacée l’appel 11 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc 12 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Différence Entre Programme et Fonction Programmation Impérative 7 : Plan Programme Infos un fichier .py entier exécuté depuis bash, avec python lefichier.py p1 p2 p3 … des paramètres dont la valeur est tapée dans le terminal des paramètres accessibles avec la liste sys.argv des paramètres forcément chaînes de caractères interrompu par exit() Fonctions en Python Fonctions et Programmes Fonctions Comme Outils d'Abstraction Technique de la Fonction Principale Fonction Technique de la Simulation définie dans une partie d'un fichier .py appelée n'importe où en python, avec la_fonction(p1,p2,p3) des paramètres dont la valeur est calculée à l'appel de la fonction des paramètres qui sont des valeurs/objets python des paramètres accessibles avec leurs noms des paramètres de n'importe quel type interrompue par return une valeur de retour (ou None ) Fonctions Récursives et Pile d'Appels 13 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc 14 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Programme Sans Fonctions 1 2 3 4 5 planetes = [ # x, y, masse, nom [0, 0, 5.9736E24, "terre"], [3.844E5, 0, 7.3477E22, "lune"] G = 6.6742E-11 * 1E-6 # N km2 kg-2 ZERO = [0, 0] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ] bob = [0, 6378.137] # km bobm = 100 # kg for pl in planetes: dx = pl[0] - bob[0] dy = pl[1] - bob[1] d = (dx * dx + dy * dy)**0.5 print("Bob est a", d, "km du centre de", pl[3]) somme_forces = ZERO for pl in planetes: dx = pl[0] - bob[0] dy = pl[1] - bob[1] d = (dx * dx + dy * dy)**0.5 u = [dx / d, dy / d] # vecteur unitaire df = [G * bobm * pl[2] / d / d * u[0], G * bobm * pl[2] / d / d * u[1]] somme_forces = [somme_forces[0] + df[0], somme_forces[1] + df[1]] print("Somme des forces sur Bob :", somme_forces, "newtons") 16 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Fonctions : Répétitions Contrôlées 1 2 3 4 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 planetes = [ # x, y, masse, nom [0, 0, 5.9736E24, "terre"], [3.844E5, 0, 7.3477E22, "lune"] G = 6.6742E-11 * 1E-6 # N km2 kg-2 ZERO = [0, 0] ] def info_bob(bob, bobm): for pl in planetes: dx = pl[0] - bob[0] dy = pl[1] - bob[1] d = (dx * dx + dy * dy)**0.5 print("Bob est a", d, "km du centre de", pl[3]) somme_forces = ZERO for pl in planetes: dx = pl[0] - bob[0] dy = pl[1] - bob[1] d = (dx * dx + dy * dy)**0.5 u = [dx / d, dy / d] # vecteur unitaire df = [G * bobm * pl[2] / d / d * u[0], G * bobm * pl[2] / d / d * u[1]] somme_forces = [somme_forces[0] + df[0], somme_forces[1] + df[1]] print("Somme des forces sur Bob :", somme_forces, "newtons") info_bob([0, 6378.137], 100) info_bob([6378.137, 0], 100) 17 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Fonctions : Ne Pas Se Répéter 1 2 3 4 5 planetes = [ # x, y, masse, nom [0, 0, 5.9736E24, "terre"], [3.844E5, 0, 7.3477E22, "lune"] G = 6.6742E-11 * 1E-6 # N km2 kg-2 ZERO = [0, 0] ] def dist(a, b): dx = b[0] - a[0] dy = b[1] - a[1] return ( dx**2 + dy**2 )**0.5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def info_bob(bob, bobm): for pl in planetes: d = dist(pl, bob) print("Bob est a", d, "km du centre de", pl[3]) somme_forces = ZERO for pl in planetes: d = dist(pl, bob) u = [ (pl[0] - bob[0]) / d, (pl[1] - bob[1]) / d] df = [G * bobm * pl[2] / d / d * u[0], G * bobm * pl[2] / d / d * u[1]] somme_forces = [somme_forces[0] + df[0], somme_forces[1] + df[1]] print("Somme des forces sur Bob :", somme_forces, "newtons") info_bob([0, 6378.137], 100) Fonctions : Meilleures Abstractions 1 2 3 4 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 planetes = [ # x, y, masse, nom [0, 0, 5.9736E24, "terre"], [3.844E5, 0, 7.3477E22, "lune"] G = 6.6742E-11 * 1E-6 # N km2 kg-2 ZERO = [0, 0] def vec_addmul(a, m, b): # retourne a + m*b (en 2d) return [ a[0]+m*b[0], a[1]+m*b[1] ] def dist(a, b): d = vec_addmul(b, -1, a) return ( d[0]**2 + d[1]**2 )**0.5 Infos Fonctions en Python Fonctions et Programmes Fonctions Comme Outils d'Abstraction Technique de la Fonction Principale Technique de la Simulation Fonctions Récursives et Pile d'Appels # b - a def info_bob(bob, bobm): for pl in planetes: d = dist(pl, bob) print("Bob est a", d, "km du centre de", pl[3]) somme_forces = ZERO for pl in planetes: d = dist(pl, bob) u = vec_addmul(bob, -1, pl) # pl - bob u = vec_addmul(ZERO, 1/d, u) # u / d df = vec_addmul(ZERO, G * bobm * pl[2] / d / d, u) somme_forces = vec_addmul(somme_forces, 1, df) print("Somme des forces sur Bob :", somme_forces, "newtons") info_bob([0, 6378.137], 100) 18 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Programmation Impérative 7 : Plan ] 19 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Portée et Visibilité des Variables 1 a = 1 2 b = 2 3 c = 3 4 def fun(b, d): 5 print(a) # 6 c = 10 # global 7 print(c) # 8 e = 3.14 # 9 10 fun(1, 1) # 11 print(c) # # b cache le b global lecture seulement -> lit le a global affectation -> nouvelle, qui cache le c 10 variable locale 1 10 3 Variable globale définie (affectées) dans la partie principale du programme (sans indentation, ou dans un if, for, while) visible de partout dans le programme Variable locale définie dans une fonction (ou en paramètre d'une fonction) visible uniquement dans la fonction, changée à chaque appel cache possiblement une variable globale du même nom 20 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Technique de la fonction « principale » But : n'avoir aucune variable globale pas de risque de partager des variables sans le savoir moins de risque d'erreur programme plus sûr Technique définir une fonction « principale » (dont le nom est au choix mais est souvent principale ou main ) se limiter dans son fichier python à des définitions de fonctions un appel à la fonction « principale » 1 2 3 4 5 6 7 8 9 10 def puissance(a, b): print("notons que a vaut", a) return a**b Ne pas utiliser trop de variables globales ! 21 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Programmation Impérative 7 : Plan Infos Fonctions en Python Fonctions et Programmes Fonctions Comme Outils d'Abstraction Technique de la Fonction Principale Technique de la Simulation Fonctions Récursives et Pile d'Appels def principale(): v = puissance(2*21, 4) v2 = puissance(v, 2) print(v, v2) principale() 22 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc 23 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Une « simulation » ? Technique de la simulation Étape 1 : initialisation de l'état Imitation du comportement d'un système au cours du temps Étape 2 :, en boucle Exemples physique : pendule, gravité, fusée au décollage, … chimie : cinétique, dosage, évaporation, molécules 3d, … jeux : chomp, snake, tetris, angry birds, … Principes de bases le système a un état le temps ou les événements externes changent l'état on peut représenter l'état du système Questions à se poser à quels événements réagit le système ? que faut-il pour afficher l'état du système ? que faut-il pour réagir aux événements/temps ? ⇒ de quoi est fait l'état du système ? 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16 17 18 19 20 21 22 23 affichage de l'état attente et gestion d'événements (externes et temps) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # Imports des modules nécessaires ... # Définitions de fonctions utilitaires ... def main(): # Technique de la fonction principale # initialisation de l'état du système ... while not «condition-de-fin»: # affichage de l'état du système ... # attente d'un événement (ou du temps) ... # mise à jour de l'état du système ... main() # Appel de la fonction principale 24 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc 25 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Simulation : mouvement linéaire Simulation : avec rebond # Imports des modules nécessaires from qtido import * # Définitions de fonctions utilitaires def main(): # Technique de la fonction principale f = creer(800, 600) # initialisation de l'état du système pos = [400, 300] while not est_fermee(f): # affichage de l'état du système effacer(f) disque(f, pos[0], pos[1], 20) # attente d'un événement (ou du temps) attendre_pendant(f, 10) # mise à jour de l'état du système pos = [ pos[0]+3, pos[1]-1 ] main() # Appel de la fonction principale Comment gérer le rebond à droite ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # Imports des modules nécessaires from qtido import * # Définitions de fonctions utilitaires def main(): # Technique de la fonction principale f = creer(800, 600) # initialisation de l'état du système pos = [400, 300] vit = [3, 1] while not est_fermee(f): # affichage de l'état du système effacer(f) disque(f, pos[0], pos[1], 20) # attente d'un événement (ou du temps) attendre_pendant(f, 10) # mise à jour de l'état du système if pos[0] > 790: # on a touché à droite # changer de direction vit = [ -vit[0], vit[1] ] # déplacer pos dans la bonne direction pos = [ pos[0]+vit[0], pos[1]-vit[1] ] main() # Appel de la fonction principale 26 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc 27 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Simulation : et le chomp ? Programmation Impérative 7 : Plan État du système quelles cases sont mangées un tableau à deux dimensions (liste de liste), 1 si mangé Infos Fonctions en Python Fonctions et Programmes Initialisation rien de mangé, creer_liste_de_listes(...) Affichage effacer la fenêtre tracer chaque carreau non mangé en marron Attente d'événements attente d'un click souris ⇒ manger des cases ignorer tout le reste Fonctions Comme Outils d'Abstraction Technique de la Fonction Principale Technique de la Simulation Fonctions Récursives et Pile d'Appels Imports qtido , random , … Fonctions utilitaires coordonnees_click , dessiner_carre , … 28 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc 29 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc Pile d'Appels de Fonctions Qu'affiche ce programme ? 1 2 3 4 5 6 7 8 9 10 11 12 x=42 def mystere(x, p): print(x) if x <= 1: res = 1 else: res = x * mystere(x-1, p+1) print(p*" ", res) return res x = mystere(4, 0) print(x) Pile d'appels Points Clés Définition de nos propres fonctions Principe de l'appel d'une fonction chaque appel de fonction a ses propres variables x et y chaque appel de fonction a sa propre variable d return donne la valeur par laquelle sera remplacée l’appel Différences entre fonction et programme Technique de la fonction principale Technique de la simulation chaque appel de fonction a ses propres variables copie des valeurs passées en argument stockage dans une pile en cas d'appels récursifs 30 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc 31 / 31 − Rémi Emonet − Programmation Impérative Fonctions, etc