Python ****** Vous pouvez tester en ligne les exemples grâce aux sites suivant : * https://www.onlinegdb.com/online_Python_compiler * https://www.online-Python.com/ Lancement ========= Compilation ----------- Python parcourt le fichier source pour : - vérifier la syntaxe, y compris à l'intérieur des fonctions et des classes - vérifier la cohérence de l'indentation du code Plus d'information sur l'indentation est disponible en bas de cette page. Exécution --------- Le progamme est maintenant exécuté ligne à ligne : * Seules sont exécutées les instructions du niveau global (sans indentation) * Lorsque le mot clef *def* est rencontré, le programme note le nom de la fonction, sans l'exécuter * Pour exécuter une fonction, il faut qu'elle soit appelée dans le code * Pour appeler une fonction, il faut qu'elle ait été définie avant dans le code .. code-block:: py a = 5 # création et initialisation de la variable a toto() # erreur car la fonction toto() est inconnue à ce niveau def toto(): # définition de la fonction toto() print("toto") toto() # cet appel ne déclenche plus d'erreur Librairie ========= L'import d'une librairie consiste à charger dans le programme les fonctions et les variables disponibles dans cette librairie. .. list-table:: :widths: 100 * - import math c = math.cos(math.pi) Certaines librairies sont si importantes qu'elles sont redivisées en sous-librairies : .. list-table:: :widths: 100 * - import numpy t = numpy.random.rand(3) Il est possible d'utiliser un alias pour simplifier le code : .. list-table:: :widths: 100 * - import numpy as np t = np.random.rand(3) .. warning:: Évitez la syntaxe : *from numpy import \** car elle est source de nombreux problèmes. Mutable ======= Un objet **mutable** peut être modifié après sa création : on peut modifier son contenu sans le recréer. Dans le cas contraire, on parle d'objet **immutable**. .. list-table:: :widths: 25 50 * - mutable - Listes, dictionnaires * - immutable - Entiers, chaînes de caractères, tuples Une variable n’est ni mutable ni immutable, c’est l’objet auquel elle fait référence qui est mutable/immutable. Structures de contrôle ====================== Rappel en fin de cette page * Branchements * Boucles .. quiz:: quizzpython3 :title: Mise en pratique Indiquez la valeur de la variable *tot* à la fin du code suivant : .. code-block:: py tot = 0 for i in range(3,11,4): if i > 5 : tot += i :quiz:`{"type":"FB","answer":"7"}` Parcours d'un container ----------------------- .. list-table:: :widths: 25 50 * - for e in data : - Syntaxe du foreach en Python On peut ainsi parcourir les éléments de tout container dit "iterable" : liste, tuple, dictionnaire... Les containers ============== Rappel en fin de cette page * Liste * Tuple * Dictionnaire .. quiz:: quizzpython :title: Questionnaire Pour chaque affirmation, indiquez si elle est vraie ou fausse. .. csv-table:: :widths: 40, 10 :delim: ! La fonction len() donne le nombre d'éléments d'une liste, d'un tuple ou d'un dictionnaire ! :quiz:`{"type":"TF","answer":"T"}` On peut modifier le nombre d'éléments d'un tuple. ! :quiz:`{"type":"TF","answer":"F"}` La fonction print() liste les informations stockées dans un container ! :quiz:`{"type":"TF","answer":"T"}` On peut créer une liste contenant des dictionnaires ! :quiz:`{"type":"TF","answer":"T"}` Un tuple contient uniquement des éléments de même type ! :quiz:`{"type":"TF","answer":"F"}` Dans une liste, on peut insérer un élément uniquement en fin de liste ! :quiz:`{"type":"TF","answer":"F"}` Il est possible de savoir si une clef est déjà utilisée dans un dictionnaire ! :quiz:`{"type":"TF","answer":"T"}` En associant une valeur à une clef, la valeur précédemment associée à cette clef est écrasée ! :quiz:`{"type":"TF","answer":"T"}` La syntaxe suivante est valide : x,y = 1,2 ! :quiz:`{"type":"TF","answer":"T"}` Variable globale ================ A l'intérieur d'une fonction : * Vous avez accès en lecture à toutes les variables globales * Pour modifier une variable globale, il faut utiliser le mot-clef **global** : .. code-block:: py g = 4 def fnt(): global g # autorise la modification de la variable globale g = 6 fnt() print(g) # >> 6 .. warning:: Si vous oubliez le mot-clef **global**, cela va entrâiner la création d'une variable locale *g*. Il n'y aura aucun message d'erreur et le programme ne fonctionnera pas comme attendu. Passage ======= Tout est objet -------------- En Python, **tout est objet**. Ainsi les variables correspondent uniquement à des références. Pour tester cela, nous utilisons la fonction *id(..)* qui retourne l'adresse mémoire associé à la référence. .. code-block:: py a = 6 # a est une référence vers un objet de type int valant 6 print(type(a), id(a)) # 139792681752000 b = a # b référence le même objet print(id(a)) # 139792681752000 Passage et retour ----------------- La mécanique de base ^^^^^^^^^^^^^^^^^^^^ Chaque paramètre d'une fonction correspond à une variable locale qui fait référence à l’objet passé en argument. .. code-block:: py L = [1,2] def fnt(LL): LL = [3,4] fnt(L) print(L) >> [1,2] .. warning:: En utilisant ce mécanisme, aucun retourn n'est possible ! Option 1 ^^^^^^^^ Cependant, une liste reste un objet mutable, on peut donc modifier son contenu : .. code-block:: py L = [1,2] def fnt(LL): LL[:] = [3,4] fnt(L) print(L) >> [3,4] Option 2 ^^^^^^^^ On peut aussi retourner le résultat: .. code-block:: py L = [1,2] def fnt(): return [3,4] L = fnt() print(L) >> [3,4] Clonage ======= Problématique ------------- Dans l'écriture *L=[1,2]* la variable *L* référence la liste [1,2]. En écrivant *T = L*, la variable *T* référence la liste initiale et à aucun moment une nouvelle liste a été créée. Ainsi, on constate ce genre de problématique : .. code-block:: py L = [1, 2] T = L L.append(3) print(L) >> [1, 2, 3] print(T) >> [1, 2, 3] .. image:: ex1.png Effectuer une copie ------------------- La fonction **copy()** crée une nouvelle liste et copie les références contenues dans la liste initiale. La nouvelle liste est indépendante de la première, si on insère un élément, il n'apparait que dans celle-la : .. code-block:: py L = [1, 2, 3] T = L.copy() T.append(4) print(L) >> [1, 2, 3] print(T) >> [1, 2, 3, 4]] .. image:: ex2.png Mais attention, il s'agit d'une copie superficielle où seules les références ont été dupliquées : .. code-block:: py L = [ [1,2,3], [4,5,6] ] T = L.copy() L[0][0] = 9 print(L) >> [ [9,2,3], [4,5,6] ] print(T) >> [ [9,2,3], [4,5,6] ] .. image:: ex3.png :scale: 84% Effectuer une copie profonde ---------------------------- Pour dupliquer un objet en construisant des copies de manière récursive, il faut utiliser la fonction **copy.deepcopy()** : .. code-block:: py import copy L = [ [1,2], [3,4] ] T = copy.deepcopy(L) L[0][0] = 9 L[1][1] = 8 print(L) >> [ [9,2], [3,8] ] print(T) >> [ [1,2], [3,4] ] Les deux listes L et T sont maintenant indépendantes .. image:: ex4.png .. quiz:: quizzpython33 :title: Questionnaire Pour chaque affirmation, indiquez si elle est vraie ou fausse. .. csv-table:: :widths: 40, 10 :delim: ! Le mot clef global permet d'avoir un accès en écriture vers une variable globale ! :quiz:`{"type":"TF","answer":"T"}` Pour effectuer une copie profonde, il faut utiliser la fonction *copy()* ! :quiz:`{"type":"TF","answer":"F"}` Les listes sont de type mutable ! :quiz:`{"type":"TF","answer":"T"}` Les tuples sont de type mutable ! :quiz:`{"type":"TF","answer":"F"}` .. image:: rappels.jpg :scale: 60% :align: center Rappels ======= Indentation ----------- La traditionnelle paire d'accolades a été remplacée en Python par l'indentation. Ainsi, les sources en Python ont une apparence très structurée. En effet, chaque sous-bloc de code est introduit en ajoutant une tabulation ou plusieurs espaces supplémentaires par rapport au bloc parent. A l'intérieur du même bloc, l'indentation doit être identique. Voici le style généré : .. code-block:: py a = 4 # définition d'une variable dans le bloc principal def toto(): # définition de la fonction toto() print("toto") # indentation => cette ligne appartient au corps de la fonction toto() b = 5 # l'indentation est revenue au niveau de la ligne de l'instruction a=4 => cette ligne appartient au bloc principal def titi(): # définition de la fonction titi() for i in range (10): # indentation supplémentaire => cette boucle appartient à la fonction titi() print(i) # indentation supplémentaire => la fonction print() est dans le corps de boucle print(i) # l'indentation est identique à celle de la ligne précédente => on reste dans le corps de boucle toto() # l'indentation diminue et revient au niveau de la boucle for, cette instruction sera appelée après la fin de la boucle titi() # l'indentation diminue et revient au niveau le plus à gauche, cette ligne appartient au bloc principal Structures de contrôle ---------------------- Les branchements ^^^^^^^^^^^^^^^^ * Il n'est pas nécessaire de parenthèser les conditions contrairement aux autres langages type C++/Java * Les mots-clefs **and**, **or** et **not** désignent les opérateurs booléens * Les constantes booléennes sont : **True** et **False** .. list-table:: :widths: 25 50 * - if i == 3 or i == 5 : - Double test avec un OU logique Les boucles ^^^^^^^^^^^ .. list-table:: :widths: 25 50 * - for i in range(5): - i : 0 1 2 3 4 * - for i in range(3,10,2): - i : 3 5 7 9 Les containers -------------- La liste ^^^^^^^^ Une liste permet : * de stocker des éléments de types **hétérogènes** * d'accéder aux éléments par un index entier : *L[i]* * de modifier les éléments qu'elle contient : *L[i] = ...* * d'ajouter ou de retirer des éléments dynamiquement En contrepartie de cette souplesse, elles sont bien plus lentes que les vecteurs du C++ ou les arrayList du Java. .. list-table:: :widths: 25 50 * - L = [1, 2, 5, 2] - Création et initialisation * - L = [1, \"toto\", 3.1415, [1,2] ] - Création d'une liste contenant des types hétérogènes * - L.append(5) - Ajout de l'élément 5 en fin de liste * - L.insert(2,9) - Insère la valeur 9 à l'index 2 * - L.remove(2) - Retire la première valeur 2 trouvée dans la liste * - L.pop() - Retourne et retire le dernier élément de la liste * - len(L) - Nombre d'éléments dans la liste * - L.sort() - Trie la liste inplace * - L[0] - Accès par indexation * - L.clear() - Vide la liste * - [1, 2] + [4 , 5] - L'opérateur + concatène les deux listes : [1, 2, 4, 5] * - print(L) - Affiche le contenu de la liste Les tuples ^^^^^^^^^^ Une tuple est une restriction des listes : * impossible d'insérer ou de retirer des éléments : le tuple est immutable, il est donc de taille fixe * impossible de modifier ses éléments après la création : *T[i] =* Cependant, les éléments mutables d'un tuple peuvent voir leur contenu modifier : .. list-table:: :widths: 25 50 * - ``T = (1, [2, 3], 5)`` - ``T[1].append(4)`` >> ``T = (1, [2, 3, 4], 5)`` .. list-table:: :widths: 25 50 * - L = (1, 2, [4,5]) - Création d'un tuple contenant des types hétérogènes * - len(L) - Nombre d'éléments dans le tuple * - L[0] - Accès par indexation * - L[2][0] += 1 - Accès à la valeur 4 de la liste [4,5] ⇒ L devient (1, 2, [5,5]) * - print(L) - Affiche le contenu du tuple * - x, y, z = L - Dépaquetage : x = 1, y = 2 et z = [5,5] * - K = x, y - Empaquetage : K = (1,2) * - x, y, z = 1, 2, 3 - Initialisation rapide de 3 variables Les tuples permettent de retourner plusieurs éléments comme résultat d'une fonction. Cette facilité est très pratique : .. code-block:: py def toto(): return 1,"toto" a,b = toto() Les dictionnaires ^^^^^^^^^^^^^^^^^ Un dictionnaire associe une valeur à une clef. Ainsi, il permet : * de stocker des éléments de types **hétérogènes** * d'accéder à un élément par une clef *k* de type quelconque : *D[k]* * d'ajouter, modifier ou retirer des éléments dynamiquement , clefs comme valeurs peuvent être de types hétérogènes. Ainsi un dictionnaire correspond à une de liste dont les index peuvent être autre chose que des entiers. Les dictionnaires offrent plus de souplesse que les listes, au détriment de la performance. Voici les syntaxes des dictionnaires : .. list-table:: Exemples :widths: 25 50 * - D = {} - Création d'un dictionnaire à partir d'une paire d'accolades * - D['PV'] = 4 - Associe la valeur 4 à la clef PV * - D['PV'] = 8 - Modifie la valeur associée à la clef PV * - D[9] = 'ARC' - Associe la valeur 'ARC' à la clef 9 * - print(D) - Affiche le contenu du dictionnaire : {'PV': 4, 9: 'ARC'} * - if 'PV' in D - Teste si la clef PV existe dans le dictionnaire * - L = {'PV': 4, 'OR': 2} - Initialisation d'un dictionnaire par passage de paires clefs/valeurs * - len(L) - Indique le nombre d'entrées dans le dictionnaire