Rappel : les bases du langage 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 :

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 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