site de Fabien Torre


Notes de cours sur le langage Python

Introduction à la programmation en Python : syntaxe générale, structures de données, méthodes de tri, manipulation de fichiers en Python et modules importants (pour la documentation et les tests du code, l'aléatoire, les expressions régulières, la manipulation de documents xml, le traitement automatique de la langue, etc.).

Révision en cours... (hiver 2025).

Contexte du cours

Dans ce cours, nous passons en revue les éléments de base du langage Python, en parallèle avec le langage de description vu en cours d'algorithmique (variables, types, structures de contrôle, procédures et fonctions, etc.).

Nous nous intéressons particulièrement aux traitements des textes à l'aide de Python : chaînes de caractères, gestion des fichiers, expressions régulières, manipulation des documents semi-structurés (XML) et traitement automatique des langues (TAL) avec le module NLTK de Python.

Types simples, variables, expressions, instructions

Instructions et blocs d'instructions

Dans le langage Python, chaque instruction occupe une ligne : il n'y a pas de symbole de fin, nous passons simplement à la ligne après chaque instruction. C'est la règle générale mais nous verrons qu'il est possible d'écrire une chaîne de caractères ou une condition sur plusieurs lignes pour une bonne lisibilité du code Python.

Les blocs d'instructions, eux, ne sont pas délimités par un symbole particulier mais répérés par l'indentation des instructions :

  • des instructions qui sont dans le même bloc ont le même nombre d'espaces à leur gauche,
  • pour marquer le début d'un nouveau bloc, on va rajouter quelques espaces par rapport à l'instruction précédente.

Idéalement, il faut utiliser un éditeur qui, après un appui sur la touche tabulation du clavier, amène le curseur à l'endroit adéquat en produisant le nombre d'espaces nécessaires.

Types et variables

Python autorise la manipulation de types classiques : booléens (bool), entiers (int), réels (float) et chaîne de caractères (str). À noter que les noms des types indiqués sont aussi des opérateurs de conversion.

Ni les variables ni leurs types n'ont besoin d'être déclarés.

msg   = "toto"  # affectation d'une chaîne de caractères
pi    = 3.14    # déclaration et affectation d'un nombre

Notons la syntaxe permettant d'écrire des commentaires dans le code Python : le signe # indique que la suite de la ligne n'est pas destinée à Python mais à un lecteur humain. Nous verrons que des commentaires bien formatés permettent la production de commentaires et des tests automatiques.

Comme suggéré ci-dessus, le symbole = est réservé à l'affectation d'une valeur à une variable. Le symbole ==, lui, permet d'exprimer un test d'égalité qui ne modifie en rien les variables.

Lorsque nous souhaiterons des conversions explicites d'un type à l'autre, nous utiliserons str pour obtenir une chaîne de caractères (à partir d'un nombre) et int pour obtenir un entier (à partir d'un texte par exemple).

pitxt    = str(pi)         # obtention de la chaîne de caractères "3.14"
sixtxt   = "6"             # une chaîne de caractères
résultat = 7 * int(sixtxt) # ... convertie en entier pour calcul
réponse  = str(résultat)   # ... et retour en chaîne pour affichage

Opérateurs

Nous disposons en Python des opérateurs arithmétiques classiques : +, -, *, /, // pour la division entière et % pour l'opération modulo (reste de la division).

salaire      = 2000
augmentation = 7 * salaire / 100

Nous retrouvons également les habituels opérateurs logiques (and, or et not) pour manipuler les booléens qui, en Python, sont notés True et False.

ok = False
ko = not(ok)

Premières chaînes de caractères et instruction d'affichage

En Python, les chaînes de caractères doivent être délimitées, au choix, par des apostrophes ou des guillemets.

"coucou hé !"
'ça va ?'

Nous reviendrons en détail sur la manipulation des chaînes de caractères en Python dans une section dédiée.

Les affichages sont en Python réalisés à l'aide de l'instruction print() : elle affiche les éléments qu'on lui confie puis passe à la ligne, les éléments sont séparés par un espace.

print("coucou hé !")  # affiche et passe à la ligne
print("toto","titi")  # titi suit toto, passage à la ligne
print()               # simple passage à la ligne

En fait, le passage à la ligne en fin d'affichage et l'espace séparateur sont des paramètres du print que l'on peut modifier. Voici quelques exemples qui illustrent différentes utilisations possibles de print.

print("toto",end="!")        # termine par un ! et pas par un passage à la ligne
print("titi")                # titi s'ajoute à toto et passage à la ligne
print("lulu","lala",sep="+") # affiche lulu+lala et passe à la ligne

Cette instruction print nous permet deux observations sur les procédures en Python :

  1. un paramètre peut être optionnel avec une valeur par défaut,
  2. les paramètres peuvent être nommés au moment d'un appel à une procédure, on se dispense ainsi de l'ordre fixé dans la définition de la procédure.

Structures de contrôle en Python

Modulo les notations propres à Python, nous retrouvons les structures de contrôle classiques, en particulier celles vues en cours d'algorithmique.

Structure conditionnelle : le si alors sinon

Le si alors sinon introduit une condition et deux blocs d'instructions : le premier bloc sera exécuté si la condition est vraie, le second si la condition est fausse. C'est l'occasion d'observer le délimitation des blocs en Python qui utilise l'indentation, c'est-à-dire le décalage des instructions d'un bloc vers la droite.

# forme générale
if (une condition ici):
    # ...
    # des instructions ici
    # ...
else:
    # ...
    # des instructions ici
    # ...

Si le second bloc ne contient pas d'instructions, on peut se dispenser du else :

# affichage si un test est vrai
temperature = 28
if temperature>25:
    print('il fait chaud !')

La condition doit être interprétée à vrai ou à faux, c'est-à-dire comme un booléen. On peut donc y trouver des variables booléennes et des opérateurs booléens.

# affichages distincts selon un test
temperature = 28
if temperature>25:
    print('il fait chaud !')
else:
    print('il fait frais...')

Si l'on doit enchaîner plusieurs tests, Python propose elif en plus de if et de else :

# enchaînement de tests
temperature = 28
if temperature>25:
    print('il fait chaud !')
elif temperature>20:
    print('il fait bon.')
else:
    print('il fait frais...')

Les elif peuvent être utilisés en nombre quelconque, ce qui permet de limiter les imbrications du code et donc d'augmenter sa lisibilité.

En Python, une condition doit s'exprimer sur une seule ligne mais, encore une fois pour faciliter la lisibilité du code, il est possible de masquer la fin de ligne à l'aide du caractère d'échappement backslash (signe \) et ainsi étaler des tests sur plusieurs lignes.

if    (lettre == 'a') or (lettre == 'e') \
   or (lettre == 'i') or (lettre == 'o') \
   or (lettre == 'u') or (lettre == 'y') :

    print("«",lettre,"» est une voyelle.")
	
else :

    print("«",lettre,"» N'est PAS une voyelle.")
	

Structure itérative : la boucle tant que

On retrouve la boucle tant que avec sa condition et le bloc d'instructions à exécuter tant que la condition est vraie, indenté vers la droite.

# forme générale
while (une condition ici):
    # ...
    # des instructions ici
    # ...

# exemple : on compte de 1 à 10
i = 1
while (i<=10):
    print(i)
    i = i + 1

Structure itérative : la boucle pour

Dans une utilisation courante, la boucle for ... in ... parcourt un intervalle défini par l'instruction range.

  • range peut prendre jusqu'à trois arguments entiers : début, fin et pas.
  • range va fournir les entiers depuis min, avancer de pas en pas et s'arrêter avant fin.
  • début et pas sont optionnels, ils valent par défaut respectivement 0 et 1.
  • pas peut être négatif mais pas nul.
# forme générale
for i in range(début,fin,pas):
    # ...
    # des instructions ici
    # ...

# on compte de 0 à 4
for i in range(5):
    print(i)

# on compte de 1 à 10
for i in range(1,11):
    print(i)

# on compte à rebours 5 à 0
for i in range(5,-1,-1):
    print(i)

# affichage de 10 étoiles
for i in range(10):
    print('*')

Une utilisation plus générale de cette boucle est possible, lorsque l'objet donné après le in est itérable. C'est le cas du range et ce sera le cas des chaînes de caractères et des listes.

Fonctions/procédures, modules, syntaxe objet

Nous nous intéressons ici aux différents moyens proposés par python pour mettre en commun, rassembler, isoler et protéger du code. Même si l'on ne se place pas en créateur de ces objets, il est important d'en connaître la syntaxe car il est difficile d'en éviter l'utilisation en Python.

Procédures et fonctions

Les procédures et les fonctions ont en commun de rassembler des instructions pour une réutilisation future. Elles utilisent des paramètres pour généraliser le code. Une fonction doit toujours se terminer par le renvoi d'un résultat (à l'aide du mot-clef return en Python), ce qui n'est jamais le cas pour une procédure. Cela signifie en particulier qu'un appel à une fonction se trouvera souvent dans la partie droite d'une affectation, en revanche un appel à une procédure ne pourra pas être à cette position.

# forme générale d'une procédure
def nom_de_la_procédure (paramètres):
    # ...
    # des instructions ici
    # ...

# procédure qui affiche entre étoiles un texte donné
def affiche_joliment (msg):
    print('***',msg,'***')

# on appelle la procédure et on renseigne son paramètre
affiche_joliment('coucou')

En Python un paramètre peut être optionnel, il convient alors de préciser la valeur à utiliser si elle n'est pas précisée lors de l'appel. De plus, les paramètres peuvent être nommés au moment de l'appel à une procédure, on se dispense ainsi de respecter l'ordre fixé dans la définition de la procédure.

# procédure qui affiche un carré
def carré (taille, symbole="*"):
       for l in range(taille):
           for c in range(taille):
               print(symbole,end="")
           print()

# appels à la procédure
carré(10,"·")
carré(5)
carré(symbole="o",taille=7)

Comme indiqué, une fonction se doit de renvoyer un résultat avec l'instruction return et l'appel à cette fonction pourra se trouver dans la partie droite d'une affectation.

# forme générale d'une fonction
def nom_de_la_fonction (paramètres):
    # ...
    # des instructions ici
    # ...
    return(résultat)

# fonction qui calcule la somme de deux entiers et la renvoie
def addition (a,b):
    s = a+b
    return(s)


# on appelle la fonction en renseignant ses paramètres et on récupère le résultat
somme = addition(2,2)
print('le résultat est',somme)
print('le résultat est',addition(1,3))

Enfin, il est possible en Python d'associer aux procédures et aux fonctions des commentaires bien formatés permettent la production de documentation et des tests automatiques.

Accès aux éléments d'un module

Un module est un fichier qui regroupe des variables, des procédures et des fonctions, pour que celles-ci puissent être utilisées dans différents scripts Python. Plusieurs syntaxes sont possibles pour charger ces modules et utiliser les procédures/fonctions en provenance de ces modules.

# nous précisons la fonction qui nous intéresse dans le module
from module import fonction
...
# appel de la fonction sans rappeler le nom du module
fonction()
...
# plusieurs fonctions sont récupérées et appelées
from module import f1,f2
...
f1()
...
f2()
...
# toutes les fonctions du module sont récupérées et appelées
from module import *
...
f1()
...
f2()
...
f3()
...

Il peut devenir délicat de comprendre un code Python si l'on importe une variable ou une fonction depuis un module alors que notre propre code définit un objet du même nom, avant ou après l'importation du module. Il est préférable d'utiliser les espaces de noms (comme en XML) pour préciser systématiquement le module d'origine d'une variable ou d'une fonction.

# on va utiliser des fonctions du module
import module
...
# on précise à nouveau le nom du module
# avec chaque utilisation d'une fonction de ce module
module.fonction()
...

Voyons un exemple avec les fonctions mathématiques proposées par Python à travers le module math.

import math         # importation du module de mathématiques de Python

math.sqrt(2)        # utilisation de la fonction racine carré du module math
math.floor(math.pi) # arrondi de la valeur de π

Nous verrons en détail des modules Python d'utilisation courante.

Syntaxe objet

En programmation objet, les variables embarquent en elles des caractéristiques qui les décrivent (les propriétés de l'objet) et des procédures et fonctions qui permettent de les traiter (les méthodes de l'objet).

Nous ne voyons pas dans le cadre de ce cours les techniques de programmation orientée objet que permettent Python. Cependant, nous sommes contraints d'utiliser la syntaxe objet pour manipuler certaines variables Python, qui de fait sont des objets. La syntaxe pour appeler une méthode d'un objet est : le nom de la variable, suivi d'un point, suivi d'un appel à la procédure ou à la fonction propre à l'objet.

Sur l'exemple suivant, nous voyons que les chaînes de caractères sont en Python des objets, et que l'on peut s'adresser à leurs méthodes.

prénom = "Fabien"  # création d'un objet chaîne de caractères
prénom.upper()     # demande à l'objet de fournir une version en majuscules de lui-même

Nous retrouvons la syntaxe pointée et les espaces de noms vus avec les modules, mais objet et module sont bien deux notions différentes.

Chaînes de caractères en Python

Écriture des chaînes de caractères en Python

Le langage Python permet de délimiter les chaînes de caractères soit par des apostrophes, soit par des guillemets. Il est pratique d'utiliser les guillemets lorsque le texte contient une apostrophe, et vice-versa.

prénom = 'Toto'
print("salut",prénom)
print("ça va aujourd'hui ?")

Il est aussi possible d'utiliser le caractère d'échappement backslash (signe \) pour changer la signification Python du caractère qui le suit. Cela permet d'indiquer qu'un guillemet ou une apostrophe ne sont pas des délimitations de fin de chaînes mais des caractères quelconques à l'intérieur de la chaîne. Cela permet également d'ajouter des instructions dans les chaînes de caractères comme un passage à la ligne (\n) ou une tabulation (\t).

print('oui, ça va aujourd\'hui !')  # échappement de l'apostrophe grâce au backslash
print("\t super !")                 # ajout d'une tabulation en début de ligne

En conséquence, le caractère backslash a une signification particulière et doit être protégé (par un backslash !) si l'on veut simplement l'inclure dans une chaîne de caractère. Python propose une autre solution, les raw strings ou chaînes brutes dans lesquelles il est convenu que le backslash n'a pas de signification particulière. Ces chaînes sont préfixées par la lettre « r ».

# deux variables qui contiennent la même chaîne de caractère : 'Voici un backslash protégé : \\ ok ?'
info_1 = "Voici un backslash protégé : \\ ok ?"
info_2 = r"Voici un backslash protégé : \ ok ?"
# print donne des affichages identiques
print(info_1) # affichage : Voici un backslash protégé : \ ok ?
print(info_2) # affichage : Voici un backslash protégé : \ ok ?

texte_1 = r"\n" # définition d'une chaîne de caractères brute
texte_1         # contient \\n
len(texte_1)    # donne la valeur 2
print(texte_1)  # affiche \n

texte_2 = "\n"  # définition d'une chaîne de caractères ordinaire
texte_2         # contient \n
len(texte_2)    # donne la valeur 1
print(texte_2)  # affiche une ligne vide (deux passages à la ligne)

Ces raw strings seront particulièrement pertinentes quand nous aurons à écrire des expressions régulières.

Il y aussi en Python les chaînes formatées préfixées par la lettre f. Elles permettent d'abord d'embarquer des expressions Python dans les chaînes de caractères. Ces expressions sont placées entre accolades, elles sont évaluées et le résultat remplace les accolades et leur contenu dans la chaîne. À noter les expressions particulières qui se terminent par le symbole égal (=).

f"essai 1 : {2+2}"    # "essai 1 : 4"
f"essai 2 : {2+2 = }" # "essai 2 : 2+2 = 4"

prénom = "Fabien"
f"Je m'appelle {prénom}."         # "Je m'appelle Fabien."
f"Je m'appelle {prénom.upper()}." # "Je m'appelle FABIEN."
f"{prénom.lower() = }"            # "prénom.lower() = 'fabien'"

Dans les chaînes formatées, il est possible d'ajouter des indications de formatage pour chaque expression entre accolades. Le format souhaité se place lui aussi dans les accolades : à la suite de l'expression à évaluer, en les séparant par le caractère « deux points » (:). Ces formats permettent de spécifier des alignements, des séparateurs, des places occupées, des conversions, etc.

f"Prénom : {'Fabien':<10} !"  # "Prénom : Fabien     !"
f"Prénom : {'Fabien':>10} !"  # "Prénom :     Fabien !"

f"Résultat : {1/4:+}"         # "Résultat : +0.25"
f"Résultat : {-1/4:+}"        # "Résultat : -0.25"

f"Prix : {45000:,} €."        # "Prix : 45,000 €."
    
f"Pourcentage : {0.225:5.2%}" # "Pourcentage : 22.50%"

f"Entier : {2*12:10d} !"      # "Entier :         24 !"
f"Entier : {2*12:<10d} !"     # "Entier : 24         !"

f"Réel : {1/3:6.2f} !"        # "Réel :   0.33 !"
f"Réel : {1/3:<6.2f} !"       # "Réel : 0.33   !"										  

Enfin, Python autorise les chaînes de caractères de sur plusieurs lignes : la convention est d'encadrer ces chaînes par des triples guillemets (""").

"""coucou
ça va ?
ou bien ?
"""
# c'est la chaîne de caractères 'coucou\nça va ?\nou bien ?\n'

Opérations sur les chaînes de caractères en Python

Codage et décodage des caractères en Python. Il est possible de repérer un caractère par son numéro UNICODE. Par exemple, les lettres de a à z en minuscules correspondent aux codes de 97 à 122. La fonction Python chr permet de passer de l'entier au caractère correspondant, la fonction ord réalise la conversion inverse.

print(chr(100)) # affichage du caractère 100 : "d"
print(chr(425)) # affichage du caractère 425 : "Ʃ"

print(ord("m")) # affiche le code UNICODE du "m" : 109
print(ord("œ")) # affiche le code UNICODE du "œ" : 339

De premières comparaisons entre chaînes de caractères peuvent être réalisées avec < et >... mais ces comparaisons sont basées sur les codes UNICODE des caractères !

ord("a"), ord("â"), ord("z") #(97, 226, 122)

"a" < "b" # True
"â" < "z" # False

Nous verrons plus loin une méthode plus pertinente, basée sur l'ordre alphabétique de la langue manipulée.

Sur les chaînes de caractères, nous trouvons l'opérateur de concaténation noté par un plus (symbole +, comme pour l'addition entre entiers) et un opérateur de répétition des chaînes avec un fois (symbole *, comme pour la multiplication entre entiers),

température = 25
    
texte       = 'La variable « température » vaut ' + str(température)
texte       = "\n" + texte + "\n"
print(texte)

print("coucou ! " * 3) # répéter une chaîne : coucou ! coucou ! coucou !

La longueur d'une chaîne de caractères est obtenue à l'aide de la fonction len.

len("coucou")               # 6
len("coucou")+len("Fabien") # 12
len("coucou"+"Fabien")      # 12

température = 25
texte       = 'La variable « température » vaut ' + str(température)
len(texte)  # 35

Pour accéder à un caractère d'une chaînes de caractères, Python propose la syntaxe « crochets » ([]), laquelle permet de préciser la position du caractère qui nous intéresse. La numérotation des caractères commence à 0.

prénom = "Fabien"
print(prénom[0]) # "F"
print(prénom[5]) # "n"

Cette notation se généralise en Python pour permettre l'extraction de sous-chaînes de caractères, on parle alors de slices (des « tranches »).

# syntaxe générale pour les slices
chaîne[début:fin:pas]
# construit une nouvelle chaîne avec les caractères extrait entre début et fin, en avançant de pas en pas

prénom = "Fabien"

print(prénom[0:2]) # "Fa"
print(prénom[5:6]) # "n"

# un caractère sur deux, dans un sens puis dans un autre
print(prénom[0:6:2])  # "Fbe"
print(prénom[5:0:-2]) # "nia"

# début et fin sont optionnels et ont donc des valeurs par défaut
print(prénom[2:])   # "ien"
print(prénom[:3])   # "Fab"
print(prénom[:])    # "Fabien"
print(prénom[::-1]) # "neibaF"

# on peut se repérer par rapport à la longueur de la chaîne...
print(prénom[len(prénom)-2:]) # "en"
# ... et en raccourci indiquer des positions négatives
print(prénom[-2:])            # "en"

Les chaînes de caractères en Python ne sont pas modifiables. Il est donc impossible d'utiliser la syntaxe « crochets » pour modifier un caractère particulier dans une chaîne. Toute modification implique alors la création d'une nouvelle chaîne de caractères. Ainsi, modifications/suppressions dans les chaînes de caractères passent par les opérations déjà vues (concaténation et multiplication), ou par l'extraction des parties à conserver avec des slices suivie de la construction d'une nouvelle chaîne. Éventuellement, la nouvelle chaîne peut être stockée dans la variable d'origine.

question = "ça va"
question = question + " ?"    # ajout d'un caractère en fin : "ça va ?"

question = "Ç" + question[1:] # changement de la première lettre : "Ça va ?"

nq = question[:5] + " ou bien" + question[5:] # nouvelle question : "Ça va ou bien ?"

Ci-dessous, quelques méthodes des chaînes de caractères qui nous seront utiles.

  • lower, upper, capitalize et title : passent des caractères de la chaîne en minuscules ou majuscules,
  • strip, rstrip et lstrip : suppriment les caractères spécifiés, par défaut des espaces au sens large (espace, tabulation, passage à la ligne, etc.), en début ou en fin de chaîne,
  • replace : remplace toutes les occurrences d'une sous-chaîne dans une chaîne
  • find : fournit la position de la première occurrence d'une sous-chaîne (-1 si la cible n'est pas présente).
# jeux sur les majuscules/minuscules
phrase = "Je m'appelle Fabien."
phrase.upper()      # "Je m'appelle FABIEN."
phrase.lower()      # "je m'appelle fabien."
phrase.title()      # "Je M'Appelle Fabien."
phrase.capitalize() # "Je m'appelle fabien."

# la chaîne de caractères d'origine n'a pas été modifiée
phrase # "Je m'appelle Fabien."

# texte sur plusieurs lignes puis nettoyage des espaces au début ou à la fin
texte = """
    coucou
bonjour chez vous !

"""
texte.strip()  # "coucou\nbonjour chez vous !"
texte.lstrip() # "coucou\nbonjour chez vous !\n\n"
texte.rstrip() # "\n    coucou\nbonjour chez vous !"

# nettoyage du début et de la fin des caractères précisés
phrase.strip("eJn. ") # "m'appelle Fabi"

# remplacement
phrase.replace("e","X") # "JX m'appXllX FabiXn.

# trouve la position d'une sous-chaîne
phrase.find("a")    # 5
phrase.find("e ")   # 1
phrase.find("rien") # -1

Pour effectuer, le parcours d'une chaîne de caractères nous retrouvons une boucle for ... in ... :

# définition d'une chaîne de caractères
mot = "coucou"

# parcours d'une chaîne caractère par caractère
for lettre in mot:
    print(lettre)
# chaque lettre du mot est affichée sur une ligne différente

Plus proche de la méthode algorithmique, il est possible de boucler sur les indices des caractères et d'y accéder à l'aide de la notation « crochets » ([]). Mais cela est jugé peu « pythonique ».

# autre parcours caractère par caractère
for i in range(0,len(mot)):
    print(mot[i],end="-")
print()
# affiche "c-o-u-c-o-u-" et passe à la ligne

Nous verrons d'autres instructions qui utilisent les chaînes des caractères au cours de l'apprentissage des listes.

Structures de données Python : les listes

Les listes sont l'équivalent des tableaux vus en algorithmique : des cases numérotées avec chacune un contenu.

En Python, il n'y a pas de contrainte sur le contenu des cases, en particulier ces contenus ne sont nécessairement du même type. Les cases sont numérotées à partir de 0. Il y a différentes manières de créer une liste et de lui affecter des valeurs.

# une liste de notes
notes = [5,12,8,20,10] # on définit une liste
notes[2] = 9           # on modifie la 2ème case
    
# création d'une liste vide et définition de trois cases
l = []
l.append(2)
l.append(3.14)
l.append('coucou')

# liste obtenue à partir d'un intervalle décrit par range (entiers de 1 à 100)
premiers = list(range(1,101))

On note d'emblée une différence par rapport aux chaînes de caractères : on peut modifier les listes, on dit qu'elles sont « mutables ».

Nous retrouvons l'instruction len qui cette fois fournit la taille d'une liste.

Python propose plusieurs syntaxes pour parcourir une liste, toutes basées sur la boucle for in.

# accès direct aux contenus des cases
for note in notes:
    print(note)

# en obtenant indices et contenus des cases
for i,note in enumerate(notes) :
    print("La case",i,"contient la note",note)

# en utilisant les indices et la longueur de la liste
for i in range(0,len(notes)) :
    print(notes[i])

Méthodes Python dédiées aux listes :

  • list : copie une liste existante pour en créer une nouvelle,
  • remove : efface la première occurrence d'un élément dans une liste,
  • del : supprime une case d'après son numéro,
  • insert : ajoute un élément à une position donnée d'une liste,
  • append : ajoute un élément en fin de liste,
  • pop : supprime le dernier élément d'une liste et le fournit.
notes = [5,12,9,20,12,10] # définition d'une liste de notes
l = list(notes)           # faire une copie de la liste de notes

l.append(12)   # ajout de 12 en fin de liste
l.insert(3,14) # ajout de 14 en position 3
del(l[2])      # suppression de la case 2
l.remove(12)   # suppression du premier 12
l.pop()        # suppression du dernier élément
print(l)       # résultat des modifications : [5, 14, 20, 12, 10]

# la liste initiale n'a pas été modifiée
print(notes)   # donne [5, 12, 9, 20, 12, 10]

Reste à discuter des liens entre listes et chaînes de caractères. Il est facile de voir un chaîne de caractères comme une liste de caractères, et effectivement Python met en commun certaines opérations. Mais nous avons déjà noté que les listes étaient mutables, ce qui n'est pas le cas des chaînes de caractères.

L'opérateur + permet de fusionner des listes, tandis que l'opérateur * les répètent.

[1,2,3] + [4,5,6] # fusion des listes : [1, 2, 3, 4, 5, 6]

[1,2,3] * 3       # répétition d'une liste : [1, 2, 3, 1, 2, 3, 1, 2, 3]

Terminons avec deux opérations intéressantes qui font le lien entre listes et chaînes de caractères :

  • split : découper une chaîne de caractères en une liste de sous-chaînes.
  • join : concaténer les chaînes de caractères d'une liste en une nouvelle chaîne unique.
# découpages avec split
phrase = "Je m'appelle Fabien."
phrase.split()    # ["Je", "m'appelle", "Fabien."]
phrase.split("'") # ["Je m", "appelle Fabien."]

# concaténation avec join
mots = ["ceci","est","un","dernier","exemple"]
"".join(mots)  # concaténation sans séparateur : "ceciestundernierexemple"
" ".join(mots) # concaténation avec l'espace comme séparateur : "ceci est un dernier exemple"

séparateur = "-"
séparateur.join(mots) # concaténation avec une variable pour stocker le séparateur

Fichiers en Python

Écriture

Voici les instructions Python de base pour créer un fichier texte : voir le print avec précision du flux dans lequel écrire.

# ouverture du fichier en écriture
flux_out = open('horla.html',mode='w',encoding="utf-8")

print("<br><br>",file=flux_out)
    
flux_out.close()

À oublier ? write ne traite que des chaînes de caractères, nous devons donc convertir tout autre type de données en chaîne à l'aide de la fonction str.

# écritures dans le fichier
f.write("coucou ! ") # on écrit coucou dans le fichier 
f.write(str(12))     # on convertit 12 en texte et on l'écrit 
f.write("\n")        # on passe à la ligne dans le fichier

f.close() # fermeture du fichier

Lecture

À rédiger.

flux_in = open('horla.txt',mode='r',encoding="utf-8")

# for ligne in flux_in:
while ligne := flux_in.readline():
    ligne = ligne.rstrip()
    
flux_in.close() # fermeture du fichier

voir aussi lecture flux pipe

Structures de données Python : les dictionnaires

Les dictionnaires sont des listes dont la particularité est que les cases ne sont plus indicées par des numéros mais par des objets plus complexes, comme des textes. Ces textes qui servent d'indices sont appelés les clefs du dictionnaire.

Premiers dictionnaires

Premiers exemples avec la définition d'un carnet d'adresses mails, les clefs du dictionnaire sont les noms des personnes :

# définition d'un dictionnaire vide
mails = {}

# définition du mail de Titi
mails['Titi'] = 'titi@univ.fr'

# définition du mail de Toto
mails['Toto']  = 'toto.machin@free.fr'

# affichage du mail de Toto
print('Mail de toto :',mails['Toto']);

Autre exemple, l'implémentation d'un type abstrait « produit », ici un type « livre » :

# définition d'un premier livre
livre1 = {}
livre1['titre'] = 'Apprendre Python'
livre1['année'] = 2010
print(livre1['titre'])

# autre syntaxe pour un second livre
livre2 = { 'titre': 'Algorithmique' , 'année': 1970 }

# procédure dédiée à ce type
def affiche_livre (l):
  print('titre :',l['titre'])
  print('année :',l['année'])

# appel à la procédure sur le livre1
affiche_livre(livre1)

Opérations Python sur les dictionnaires

  • keys donne les clefs d'un dictionnaire,
  • values donne les valeurs d'un dictionnaire,
  • items fournit clefs et valeurs du dictionnaire sous forme de couples,
  • len donne le nombre de couples dans le dictionnaire,
  • get extrait la valeur associée à une clef, comme on le fait avec la notation crochets mais permet de prévoir une valeur par défaut pour le cas où la clef n'existe pas dans le dictionnaire,
  • in dit si la clef existe ou non dans le dictionnaire,
  • del permet de supprimer une entrée du dictionnaire.
# définition d'un dictionnaire
d = { 'Titi':'titi@univ.fr' , 'Toto':'toto.truc@free.fr' }

print(d.keys())   # ['Toto', 'Titi']
print(d.values()) # ['toto.truc@free.fr', 'titi@univ.fr'] 
print(d.items())
# [('Toto','toto.truc@free.fr') , ('Titi','titi@univ.fr')]

# parcours de clefs et affichage des couples nom/mail
for nom in d:
    print(nom,':',d[nom])

print(len(d)) # affiche la valeur 2

print('Toto' in d) # True
print('Lulu' in d) # False

print(d['Toto']) # toto.truc@free.fr
print(d['Lulu']) # KeyError: 'Lulu'

print(d.get("Toto","contact inconnu")) # toto.truc@free.fr
print(d.get("Lulu","contact inconnu")) # contact inconnu

del(d['Toto']) # suppression des infos sur Toto
print(d.get("Toto","contact inconnu")) # contact inconnu

Test d'existence et comptage à l'aide des dictionnaires Python

À rédiger.

Tris en Python

À rédiger. En informatique, « trier » signifie ordonner des éléments, sans en éliminer : par exemple des notes de plus petite à la plus grande, des mots par ordre alphabétique, etc.

l.sort()      : tri sur place
newl = sorted(l) : nouvelle liste triée
paramètres key (fonction) et reverse (booléen)

# sur les nombres
>>> l = [1,12,10,50,3]
>>> sorted(l)
[1, 3, 10, 12, 50]
>>> sorted(l,reverse=True)
[50, 12, 10, 3, 1]


# sur les textes
l = ["favori","école","abri"]

# selon ordre lexicographique + codes UNICODE
sorted(l)
['abri', 'favori', 'école']

sorted("bachibouzouk") # sur les caractères des chaînes
['a', 'b', 'b', 'c', 'h', 'i', 'k', 'o', 'o', 'u', 'u', 'z']
"".join(sorted("bachibouzouk"))
'abbchikoouuz'

# selon la taille des mots !
sorted(l,key=len)
['zoo', 'abri', 'école', 'favori']

Avec les dictionnaires : tris sur les clefs ou sur les valeurs.

Expliquer key. Expliquer fonctions lambda.

Quelques modules Python

Nous avons déjà vu comment bénéficier d'un module dans son code Python. Ci-dessous sont décrits les modules suivants :

Documentation et tests automatiques : le module doctest

À développer. Lors de la définition d'une procédure/fonction, on peut ajouter après la première ligne une docstring. Il s'agit d'une chaîne de caractères, délimitée par des triples guillemets, qui décrit la fonction et propose des tests à travers des exemples d'utilisation.

Gestion de l'aléatoire : le module random

  • random.randint choisit aléatoirement un entier dans un intervalle donné,
  • random.randrange choisit aléatoirement entre 0 et un entier donné (exclu), permet aussi de préciser une borne inférieure autre que 0 et un pas de progressions,
  • random.choice fournit aléatoirement un élément parmi ceux d'une liste,
  • random.shuffle mélange sur place les éléments d'une liste.
import random

print(random.randint(1,10))       # un entier entre 1 et 10

print(random.randrange(10))       # un entier entre 0 et 9
print(random.randrange(10,100,2)) # entier pair entre 10 et 98

notes = [5,12,8,20,10]            # on définit une liste

print(random.choice(notes))       # une note au hasard

print(notes)
random.shuffle(notes)             # mélange aléatoire
print(notes)

Expressions régulières : le module re

À rédiger.

expressions régulières exprimées comme des chaînes de caractères : il faut utiliser les raw strings. À détailler.

Couleurs dans le terminal : le module termcolor

À rédiger.

Langues et localisations : le module locale

À rédiger.

pb accents dans les tris, expliquer strcoll, strxfrm

import locale
locale.setlocale(locale.LC_ALL,"")            # soit locale par défaut de la machine
locale.setlocale(locale.LC_ALL,"fr_FR.UTF-8") # soit on précise la locale voulue

locale.localeconv()["int_curr_symbol"] # symbole monétaire à utiliser d'après la locale

l = ["favori","école","abri"]
sorted(l,key=locale.strxfrm)
['abri', 'école', 'favori']

Manipulation des documents XML : le module xml

SAX et DOM. À rédiger.

DOM : voir l'API DOM dans le cours de JavaScript.

Nous nous concentrons ici sur le noyau de DOM fournissant des méthodes valables pour tout document XML (en particulier, des documents non-HTML) et les exemples sont donnés en Python).

En Python, le programme minimal qui charge un document XML sous forme de DOM est le suivant :

from xml.dom.minidom import parse

dom = parse("fichier.xml")

Ou, si l'on souhaite lire le nom du fichier depuis la ligne de commande :

from xml.dom.minidom import parse
import sys

xmlfilename = sys.argv[1]
dom         = parse(xmlfilename)

Premiers exemples de programmes Python & DOM

Accéder à un fils textuel
from xml.dom.minidom import parse
import sys

xmlfilename = sys.argv[1]
dom         = parse(xmlfilename)

titres  = dom.getElementsByTagName("titre")
premier = titres[0]
texte   = premier.childNodes[0]

print(texte.nodeValue)
Obtenir des attributs
from xml.dom.minidom import parse
import sys

xmlfilename = sys.argv[1]
dom         = parse(xmlfilename)

sites = dom.getElementsByTagName('site')

for site in sites:
    attrs   = site.attributes
    urlnode = attrs['url']
    print(urlnode.nodeValue)
Lire un fichier plat
from xml.dom.minidom import parse
import sys

xmlfilename = sys.argv[1]
dom         = parse(xmlfilename)

racine = dom.documentElement;
fils   = racine.childNodes

print('racine=',racine.nodeName)

for f in fils:
  if f.nodeType==1:
    print(f.nodeName,'=',f.childNodes[0].nodeValue)

Un nouveau DOM

impl        = getDOMImplementation()
newdoc      = impl.createDocument(None,"laracine",None)
top_element = newdoc.documentElement

Définir un nœud ou un attribut

new_element = newdoc.createElement('nomelement')
new_element.setAttribute('nom_attribut','valeurattribut')
copie = noeud.cloneNode(True)
copie.removeAttribute('nom_attribut_à_supprimer')

Placer un nœud dans la structure

top_element.appendChild(new_element)

Produire du XML

Produire du XML à partir d'un nœud n : n.toxml() ou n.toprettyxml().

newdoc.toxml()
newdoc.toprettyxml()

Traitement automatique des langues : le module nltk

À rédiger.

Échanges avec le système d'exploitation : le module os

os.listdir fournit la liste des fichiers dans un dossier donné.

Récupération du flux produit par un autre programme.

import os
pipe = os.popen('ls -l ~')

while ligne := pipe.readline():
    print(ligne,end="")

Interaction avec l'interprète Python : le module sys

Si nous avons un algorithme récursif qui nécessite d'augmenter le nombre de récursions autorisées, cela se fait de cette manière :

import sys
sys.setrecursionlimit(2000)

Mesure des temps de calcul : le module time

import time

t1 = time.process_time()
...
# ici les instructions à chronométrer
...
t2 = time.process_time()
print((t2 - t1),'sec.')

Déplacements d'une tortue : le module turtle

  • color(c) et width(w) : décider de la couleur et de l'épaisseur du trait,
  • write(t) : écrire un texte,
  • up() et down() : lever et baisser le crayon,
  • forward(d) et backward(d) : avancer et reculer d'une certaine distance,
  • goto(x,y) : se rendre à des coordonnées particulières,
  • circle(r) : dessiner un cercle de rayon donnée,
  • begin_fill() et end_fill() : pour colorier,
  • hideturtle() et exitonclick() : cacher la tortue et attendre un clic,
  • speed(v) : régler la vitesse de la tortue,
  • reset() : réinitialiser.
from turtle import *


Accueil > Enseignement > Cours > Programmation > Python
(contenu mis à jour )
site de Fabien Torre, université de Lille

Description

Survoler un lien de navigation pour lire sa description ici...


Une photo au hasard

Beau samedi à Ostende.

(le 30 août 2008)

Horloge sur la plage d'Ostende.