Séquences Python

Il n’y a pas à proprement parler de type séquence en Python, mais on désigne comme tels les objets qui appartiennent (entre autres) à l’un des quatre types suivants : les chaînes de caractères, les listes, les tuples et les intervalles (c’est-à-dire les objets créés par la fonction range). Au-delà des différences entre ces types de données, les séquences ont un certain nombre de propriétés importantes en commun :

  • Elles sont composées d’un nombre fini d’éléments auxquels on peut accéder par un indice. Ainsi seq[k] désigne l’élément situé en position k dans la séquence seq (attention car c’est très important : la numérotation commence à 0).
  • Un indice négatif signifie qu’on compte à partir de la fin. Ainsi seq[-1] désigne le dernier élément d’une séquence.
  • On peut effectuer des coupes (le terme anglais est slice). Ainsi seq[i:j] désigne le segment (chaîne, liste ou tuple) formé des éléments qui sont en position i (inclus) à (exclu, attention à ça !) dans la séquence seq.
  • On peut tester l’appartenance d’un élément à une séquence. La syntaxe est : elt in seq (résultat booléen).
  • On peut parcourir une séquence au sein d’une boucle for. La syntaxe est: for elt in seq .
  • La longueur d’une séquence seq (le nombre d’éléments dont elle est constituée) est donnée par len(seq).

Opérations communes sur les séquences

Dans le tableau ci-dessous, s et t désignent des séquences (chaînes, listes ou tuples ou range), x désigne un objet pouvant appartenir à s, et on note i, j, k, n des entiers.

x in sTrue si x est dans s, False sinon
x not in sFalse si x est dans s, True sinon
s+tConcaténation de s et t
s*n, n*sconcatène n copies de s
len(s)longueur de la séquence s
s[i]le i-ème élément de s
s[i:j]coupe de s pour indices [i, j[
s[i:j:k]idem, mais avec un “pas” k
min(s)le plus petit élément de s
max(s)le plus grand élément de s
s.index(x)le 1er indice où x est dans s
s.count(x)le nombre de x dans s

Dans ce qui suit, on reviendra en détail sur l’utilisation spécifique des listes, des tuples et des chaînes de caractères, mais voici un bref aperçu :

  • Les chaînes de caractères sont délimitées par des guillemets doubles (“abc”) ou simples (‘abc’). Elles sont constituées de caractères au format unicode (qui permet de représenter les lettres de tous les alphabets).
  •  Les listes sont des successions d’objets (eux-mêmes séparés par des virgules), délimitées par des crochets [ et ]. Elles peuvent contenir des objets de type quelconque. Un exemple de liste est [1,’a’,[3.14,’xyz’]].
  • Les tuples sont des successions d’objets (séparés par des virgules), délimitées par des parenthèses ( et ).
    Les tuples peuvent contenir des objets de type quelconque. Un exemple de tuple est : (1,’a’,[3.14,’xyz’]).

Contrairement aux listes, les chaînes et les tuples ne sont pas mutables (voir plus loin), c’est-à-dire qu’on ne peut donc pas modifier ou supprimer leurs éléments individuellement (on peut juste redéfinir une chaîne ou un tuple dans sa totalité).

Les fonctions intégrées listtuple et str permettent la conversion d’un type de séquence à un autre. Voici quelques exemples (en choisissant le type “chaîne”) et notamment des exemples de “slicing”.

Notion de “méthode”

On sait qu’une fonction, comme au sens mathématique, est un mécanisme qui permet, à partir d’un ou de plusieurs arguments donnés en entrée, de renvoyer une valeur.

Python est un langage qui obéit à un certain nombre de caractéristiques, parmi lesquelles la “programmation orientée objet”. Sans entrer dans le détail, les types que nous avons évoqués en Python sont en fait des “classes”. Chaque élément d’une classe (l’entier 2018 dans la classe int par exemple) est ce qu’on appelle un “objet” de la classe (ou une “instance”).La définition d’une classe comporte un certain nombre de “méthodes” dont héritent chacun des objets de la classe.

Cette notion s’applique particulièrement aux séquences (chaînes, listes, etc).
Pour appeler une méthode sur un objet, et pour bien marquer que c’est l’objet lui même qui possède cette méthode, on utilise une syntaxe du type objet.methode (bien noter le point décimal séparateur). Le résultat de cette construction syntaxique est l’application de cette méthode à cet objet.

Les chaînes de caractères

Dans cette section, on évoque les fonctions intégrées à Python et qui traitent des chaînes de caractères. L’essentiel des fonctions de Python qui agissent sur des chaînes sont des méthodes.

Les chaînes possèdent un très grand nombre de méthodes qui leur sont propres ; ces méthodes ont souvent un comportement par défaut qui peut être personnalisé en précisant la valeur de paramètres facultatifs. En voici une sélection :

str.endswith(suffix)renvoie True si la chaîne str se termine par la chaîne suffix
str.startswith(prefix)renvoie True si la chaîne str commence par la chaîne prefix
str.isalnum()renvoie True si str est formée uniquement de caractères alphanumériques
str.isalpha()renvoie True si str est formée uniquement de caractères alphabétiques
str.isdigit()renvoie True si str est formée uniquement de chiffres
str.lower()renvoie une chaîne obtenue par passage en minuscules
str.upper()renvoie une chaîne obtenue par passage en majuscules
str.replace(old,new[,n])renvoie une chaîne obtenue en remplaçant old par new, au plus n fois
str.find(sub,[p])indice de la 1ère occurence de sub à partir position p (et -1 si non trouvé)
str.index(sub)comme find, mais erreur ValueError si non trouvé
str.rfind(sub)indice de la dernière occurence de sub (et -1 si non trouvé)

Et voici quelques exemples d’utilisation:

Les méthodes split, join, format

La méthode split permet de découper une chaîne en une liste de sous-chaînes, en effectuant les coupures sur des caractères bien précis (par défaut les espaces)

La méthode join est l’inverse de la méthode split. L’expression sep.join(iterable) regroupe les chaînes éléments de l’objet iterable (une liste de chaînes, par exemple), en utilisant la chaîne sep comme séparateur.

La méthode join doit être considérée comme une méthode de la chaîne qui est spécifiée comme séparateur. La méthode join est économique en mémoire et doit être préférée à une boucle mettant les chaînes bout à bout.

La méthode format permet de formater une chaîne (pour l’afficher, le plus souvent), en utisant un canevas contenant des champs (qui servent à spécifier le format) et des arguments pour renseigner ces champs.

La syntaxe est canevas.format(arguments). Les champs de formatage (dans la chaîne canevas) sont délimités par des accolades, et chaque champ est renseigné par l’argument qui lui correspond. Il y a énormément de variantes !

Voici quelques exemples simples :

Les « range »

Un range (ou encore un “intervalle” même si le terme prête à confusion) désigne une succession de valeurs entières.

  • La syntaxe est où abh sont des entiers;
  • La valeur a (le début de l’intervalle) est facultative, et par défaut elle vaut 0. Si a est présent, la valeur h (le pas de l’intervalle) est facultative, et vaut 1 par défaut;
  • L’intervalle range(a,b,h) est formé des valeurs x = a + kh, avec k entier tel que ax < b si a < b, et ax > b si a > b;
  • Retenons que la valeur b est toujours exclue de range(a,b,h).

Ainsi range(a,b,h) doit être vu comme une succession de valeurs, en partant de a, et en progressant vers b (sans jamais l’atteindre !), dans le sens croissant ou décroissant selon que le pas h est positif ou négatif. Ainsi :

  • range(7) représente la succession des valeurs 0, 1, 2, 3, 4, 5, 6
  • range(1,7) représente 1, 2, 3, 4, 5, 6 ;
  • range(1,7,2) représente 1, 3, 5
  • range(7,2) est vide, range(7,2,-1) représente 7, 6, 5, 4, 3

Si a ≤ b, alors range(a,b) est formé de b − a valeurs (et vide si a = b)

Pour tester l’appartenance d’une valeur à un intervalle, on utilise le mot réservé in (résultat True ou False).

Les listes

Une liste Python se présente sous la forme [x0, x1,…, xn], où x0, x1,…, xn sont des objets quelconques (et pourquoi pas des listes, par exemple) mais qui peuvent être de types distincts.

Les listes comme cas particuliers de séquences

Les listes Python sont des cas particuliers d’objets de type “séquence”. En particulier, si L est une liste :

  • L[k] est l’élément situé en position k (la numérotation commence à 0). La longueur de L est len(L);
  • Si l’indice k est négatif, on compte à partir de la fin. Ainsi L[-1] est le dernier élément;
  • L[i:j:h] est la sous-liste des éléments en position i (inclus) à j (exclu, attention !) dans L, avec un pas de h;
  • On peut tester l’appartenance d’un élément à L, avec elt in (résultat booléen);
  • On peut parcourir L au sein d’une boucle for, avec for elt in L.

La formation des listes

Les listes peuvent être formées :

  • En évaluant l’expression list() ou [] : on obtient alors la liste vide;
  • En combinant des éléments [elt0, elt1,…, eltn], ou en convertissant une séquence par list(seq);
  • En “compréhension”, par [expr for indice in iterable], ou [expr for indice in iterable if condition]. On obtient alors la liste des valeurs de expr quand indice parcourt iterable (et où condition est facultative).

Opérations de mutation des listes

Dans le tableau suivant, L désigne une variable dont le contenu est une liste, et x est un objet qu’on écrit, ajoute, supprime ou recherche dans L. On note t un objet “itérable” dont les éléments sont écrits dans L ou ajoutés à la fin de L.

L[i] = xremplace L[i] par x
del L[i]supprime l’élément L[i]
L[i:j] = tremplace L[i] ,…, L[j−1] par les élts de t
L[i:j:k] = tidem mais avec le pas k
del L[i:j]supprime L[i], L[i+1], …, L[j−1]
del L[i:j:k]idem mais avec le pas k
L.append(x)ajoute un élément x à L
L.clear()efface tous les éléments de L
L.copy()copie indépendante de L (idem L[:])
L.extend(t)ajoute les élts de l’itérable t à L
L.insert(i,x) insère x en position i dans L
L.pop(i)supprime et renvoie le i-ème élt de L
L.remove(x)supprime la 1ère occurence de x dans L
L.reverse()inverse l’ordre des éléments de L
L.sort(x)trie la liste L “sur place”
sorted(L)renvoie L triée, mais sans modifier L

Attention : la plupart des instructions précédentes renvoient la valeur None mais mutent la liste (sans changer son adresse en mémoire). Prenons quelques exemples, en plaçant une même liste dans s et t, et en faisant une copie “fraîche” de cette liste dans u. Les modifications sur s se répercutent dans t mais pas dans u :