Rappels Python
Vous pouvez tester en ligne les exemples grâce aux sites suivant :
Ce chapitre a été mis en place pour les personnes venant d’un autre langage. Il peut être sauté par les personnes familières avec le langage Python. Cependant, le chapitre suivant intitulé Les pièges du langage Python doit être consulté par tout le monde. Dans tous les cas, les questions des QCM doivent être préparées.
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é :
a = 4 # déclaration d'une variable dans le bloc principal
def toto(): # définition de la fonction toto()
print("toto") # 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
Lancement du programme
Stockage dynamique des variables/fonctions
En Python, les variables globales, les fonctions, ainsi que les librairies sont créés dynamiquement durant l’exécution du programme. On peut considérer que l’interpréteur Python utilise un dictionnaire pour les stocker les noms de ces différentes entités ; la fonction vars() permet ainsi d’afficher la liste des noms déclarés jusqu’ici. L’exécution d’un source Python se déroule ligne à ligne depuis la première ligne du fichier. Lorsque qu’une définition de fonction apparaît, son nom est créé mais en aucun cas cette fonction est exécutée. L’exécution continue à la prochaine ligne du bloc principal, le corps de la fonction n’est pas exécuté. Au lancement, les variables et les fonctions présentes dans votre code n’existent pas encore.
print(vars()) # (...)
a = 5 # création et initialisation de la variable a
print(vars()) # { ..., 'a': 5}
toto() # cette ligne déclenche une erreur car la fonction toto() est inconnue à ce niveau
def toto(): # définit toto() comme fonction
print("toto")
print(vars()) # { ..., 'a': 5, 'toto': <function toto at 0x000002AB4A1CDEE8>}
toto() # cet appel ne déclenche plus d'erreur
Import de librairies
L’import d’une librairie en Python grâce au mot clef import entraîne le chargement des fonctions/variables exportées par cette librairie. Les fonctions et les variables exportées par cette librairie deviennent alors accessibles dans le code du programme en utilisant la syntaxe : nom_librairie.fonction(…).
import numpy # charge la librairie numpy
t = numpy.random.rand(3)) # appel de la fonction rand de la librairie numpy
Avertissement
Évitez la syntaxe : from numpy import * car elle est source de nombreux problèmes insoupçonnables.
Il est possible de de choisir un alias pour remplacer le nom de la librairie lors de la commande import :
import numpy as np
t = np.random.rand(3) # écrire np est suffisant pour appeler les fonctions de la librairie
Du point de vue technique, on distingue deux scénarios en Python :
Un fichier unique contenant des définitions : on parle alors de module simple
Un répertoire contenant plusieurs fichiers ainsi qu’un fichier spécial organisant leurs chargements : on parle alors de package
Donnez l’affichage produit par le code maladroit suivant :
def toto():
print("V1")
toto()
def toto():
print("V2")
toto()
A : V1 / V1
B : V1 / V2
C : V2 / V1
D : V2 / V2
E : erreur
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 avec des majuscules.
for i in range(100):
if i % 3 == 0 and i % 7 == 0 :
print(i)
>> 0 21 42 63
Les boucles
for i in range(5):
print(i) # 0 1 2 3 4
for i in range(3,10,2):
print(i) # 3 5 7 9
Indiquez la valeur de la variable tot à la fin du code suivant :
tot = 0
for i in range(3,11,4):
if i > 5 :
tot += i
Les containers
Immutable / mutable
Si l’on consulte la documentation officielle Python on peut trouver cette information :
Objects whose value can change are said to be mutable
Objects whose value is unchangeable once they are created are called immutable
Les listes
Objet Python très commun, la liste permet de stocker et d’indexer plusieurs éléments de types hétérogènes. Les listes permettent 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.
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
Un tuple représente une liste de taille fixe non modifiable une fois créé (immutable). Un tuple peut stocker des éléments de types hétérogènes.
L = (1, 2, [4,5]) |
Création d’un tuple contenant des types hétérogènes |
len(L) |
Nombre d’éléments dans la liste |
L[0] |
Accès par indexation |
L[2][0] +=1 |
Accès à la valeur 4 de la liste [4,5] => L: (1, 2, [5,5]) |
print(L) |
Affiche le contenu du tuple |
Pour faciliter l’empaquetage et le dépaquetage d’éléments, des syntaxes compactes sont proposées :
L = (1, 2, [4,5])
x,y,z = L # dépaquetage
>> x: 1
>> y: 2
>> z: [5,5]
L = x,z # empaquetage
>> (2,[5,5])
Les tuples sont sensés être plus performant en rapidité que les listes.
En utilisant la syntaxe compacte des tuples, on peut effectuer plusieurs affectations en 1 ligne :
x,y,z = 1,2,3
Les tuples permettent de retourner plusieurs éléments comme résultat d’une fonction. Cette facilité est très pratique :
def toto():
return 1,"toto"
a,b = toto()
Note
On trouve des tuples et des listes dans tous les programmes Python. On peut cependant s’interroger sur l’intérêt de proposer ces deux objets très similaires. Il n’est pas toujours évident pour le développeur débutant de savoir quel container choisir. En cas de doute, choisissez une liste.
Les dictionnaires
Un dictionnaire associe une valeur à une clef, 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 :
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 ou de clefs dans le dictionnaire |
Boucle sur les containers
On peut parcourir les éléments d’un container s’il est dit iterable. Les containers comme les listes, les tuples ou les dictionnaires appartiennent à cette catégorie. On peut ainsi écrire un algorithme à base de boucles for pouvant fonctionner avec différents types de container sans changer le code associé. Voici un exemple :
def Aff(data):
for e in data : # syntaxe du foreach en Python
print(e, " / " end="")
L = [4,5,6] # container liste
Aff(L)
>> 4 / 5 / 6 /
L = (1,2) # container tuple
Aff(L)
>> 1 / 2 /
L = {'PV': 4, 'OR': 2} # container dictionnaire
Aff(L)
>> PV / OR /
Pour chaque affirmation, indiquez si elle est vraie ou fausse.
La fonction len() donne le nombre d’éléments d’une liste, d’un tuple ou d’un dictionnaire |
|
On peut modifier le nombre d’éléments d’un tuple. |
|
La fonction print() liste les informations stockées dans un container |
|
On peut créer une liste contenant des dictionnaires |
|
Un tuple contient uniquement des éléments de même type |
|
Un même dictionnaire doit contenir uniquement des clefs de même type |
|
Dans une liste, on peut insérer un élément uniquement en fin de liste |
|
Il est possible de savoir si une clef est déjà utilisée dans un dictionnaire |
|
En associant une valeur à une clef, la valeur précédemment associée à cette clef est écrasée |