Plan du site  
français  English
pixel
pixel

Articles - Étudiants SUPINFO

Chapitre 04 - Structures séquentielles de données

Généralités sur les séquences en Python

On va dans cette partie introduire des structures de données dites complexes. Au sein d’une même entité on va ainsi pouvoir stocker plusieurs données les unes à la suite des autres, et les traiter de façon optimale.

Notion de séquence

La motivation première est de pouvoir réunir au sein d’une même variable plusieurs valeurs différentes.

L’objectif étant d’optimiser certaines opérations comme la recherche d’un élément, le tri de ces valeurs, le calcul de leur maximum, etc.

[Note]

Cette "réunion" de valeurs peut se faire de plusieurs façons fort différentes. On étudiera ainsi d’autres structures de données dans le septième chapitre de ce cours, puis dans les cours de programmation orientée objet 2OOP et de théorie des graphes 2GRA.

Commençons par définir la notion de séquence : il s'agit d'une suite d'éléments accessibles par leur position. On utilise également les termes de rang ou d'indice.

Chaque élément, à part le premier, a un prédécesseur et, à part le dernier, a un successeur.

Figure 1.1. Visualisation d'une séquence de n éléments

Visualisation d'une séquence de n éléments

[Note]

Comme dans quasiment tous les langages de programmations ces indices commencent à 0. La particularité du Python est que l’on peut accéder aux caractères avec des indices négatifs, en partant de la fin de la séquence.

L’accès à un élément d’une séquence se fait en utilisant la position de cet élément et des crochets [ ] :

maSequence[maPositionVoulue]

Les trois principaux types de séquences

En Python on dénombre trois types principaux de séquences :

  1. Les listes dont les éléments sont quelconques et modifiables.

  2. Les t-uples dont les éléments sont quelconques et non modifiables.

  3. Les chaînes de caractères dont les éléments sont des caractères et ne sont pas modifiables.

[Note]

Le lecteur attentif se rappellera que les chaînes de caractères ont été étudiées dans le premier module de ce cours.

[Note]

Il existe d'autres types de séquences en Python : range, bytes et bytearray. On ne les étudiera pas en détail dans ce cours.

Voici quelques syntaxes possibles pour déclarer une liste :

maListeVide = []

maListeAvecUnSeulElement = [element]

maListe = [element1,element2,...,elementN]

Example 1.1. Déclaration et manipulation d'une liste

On déclare une liste, on modifie la valeur de l'un de ses éléments, et l'on réalise divers affichages :

>>> print(maListe)
[2, -3, ['xox', 69], 11]
>>> print(maListe[-1])
11
>>> maListe[1] = 666
>>> print(maListe[1])
666
>>> print(maListe[2][0][1])
o

Pour bien fixer les idées, voici une représentation de la liste précédente :


[Note]

L'exemple précédent nous a pemis de constater que l’imbrication de séquences est tout à fait possible.

Voici maintenant quelques syntaxes possibles pour déclarer un t-uple :

monTupleVide = ()

monTupleAvecUnSeulElement = (element,)

monTuple = (element1,element2,...,elementN)
[Note]

Ne pas oublier la virgule dans la déclaration d’un t-uple avec un seul élément, car sinon l’interpréteur considère qu’il s’agit d’une variable "classique".

Un t-uple étant non modifiable, en déclarer un vide n'est pas d'une grande utilité. C'est cependant possible.

Example 1.2. Déclaration et manipulation d'un t-uple

On déclare un t-uple, et l'on constate que l'on ne peut pas modifier l'une de ses valeurs :

>>> monTuple = (2.718, 3.14, 1.414)
>>> print(monTuple)
(2.718, 3.14, 1.414)
>>> print(monTuple[2])
1.414
>>> monTuple[2] = 1.732
Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    monTuple[2] = 1.732
TypeError: 'tuple' object does not support item assignment

Opérations communes aux séquences

Comme mentionné précédemment, l'accès à un élément se fait en indiquant la position de celui-ci entre crochets. On peut avec une syntaxe très proche accéder à une sous-partie d'une séquence, grâce à une technique dite de slicing :

Opération Résultat
s[i] i-ème élément de s
s[i:j] Sous-séquence de s constituée des éléments entre le i-ème (inclus) et le j-ème (exclus)
s[i:j:k] Sous-séquence de s constituée des éléments entre le i-ème (inclus) et le j-ème (exclus) pris avec un pas de k

Voici quelques compléments d'informations sur ces opérations :

  • Les deux dernières opérations peuvent renvoyer une séquence vide.

  • La première utilisée avec un indice incorrect (typiquement trop grand) retourne une erreur. Pour éviter ce genre de problème on va bientôt présenter une fonction calculant le nombre d’éléments d’une séquence. On pourra donc toujours vérifier la validité de nos indices.

  • Si l’on omet le premier argument dans l’une des deux opérations de slicing, il vaut par défaut 0, et si l’on omet le second il vaut par défaut le nombre d’éléments de la séquence.

Example 1.3. Opérations de slicing sur une séquence

>>> t = (7, -3, 2, 11, 666, -1975)
>>> t[3:]
(11, 666, -1975)
>>> t[1:4]
(-3, 2, 11)
>>> t[1::2]
(-3, 11, -1975)
>>> t[23]
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    t[23]
IndexError: tuple index out of range

L'erreur provient du fait que l'on souhaite accéder au vingt-quatrième élément d'un t-uple qui n'en comporte que six.


On va présenter maintenant les principales fonctions natives du langage Python permettant le traitement des séquences :

Opération Résultat
x in s Teste si x appartient à s
x not in s Teste si x n’appartient pas à s
s + t Concaténation de s et t
s * n ou n * s Concaténation de n copies de s
len(s) Nombre d’éléments de s
min(s) Plus petit élément de s
max(s) Plus grand élément de s
s.count(x) Nombre d’occurences de x dans s
s.index(x) Indice de x dans s

Voici quelques compléments d'informations sur ces opérations :

  • Pour pouvoir utiliser les opérations min et max, il faut bien sûr que les éléments des séquences soient comparables deux à deux.

  • Si l’élément x n’est pas dans la séquence s, s.index(x) retourne une erreur. S’il y est plusieurs fois s.index(x) retournera la position de sa première occurence.

Example 1.4. Quelques manipulations de séquences

>>> t = (7, -3, 2)
>>> 11 not in t
True
>>> max(t)
7
>>> tt = 2*t
>>> print(tt)
(7, -3, 2, 7, -3, 2)
>>> tt.count(-3)
2

[Note]

On ne va pas donner des exemples de toutes les opérations précédentes, au lecteur de les tester par lui-même.

Parcours d'une séquence avec "for"

On a introduit la structure itérative for dans le second chapitre de ce cours afin de réaliser un nombre d'itérations fixe et connu.

On va ici l'utiliser afin de parcourir un à un les éléments et/ou indices d'une séquence.

Itération sur les éléments d'une séquence

On parcourt successivement tous les éléments d'une séquence :

for x in maSequence:
    traitement de l’élément x

Au fil des itérations, la variable x prendra successivement pour valeur tous les éléments de la séquence. Le nombre d'itérations sera égal au nombre d'élements de la séquence.

Example 1.5. Itération sur les éléments

l = [-2, 3, 11]

for x in l:
    print(x**2)
4
9
121

Itération sur les couples (indices, éléments) d'une séquence

On parcourt successivement et simultanément tous les indices et éléments d'une séquence à l'aide de l'instruction enumerate :

for i,x in enumerate(maSequence):
    traitement de l’élément x et/ou de l’indice i

Au fil des itérations, la variable i prendra successivement pour valeur tous les indices des éléments de la séquence et la variable x tous les éléments en eux-mêmes. Le nombre d'itérations sera là encore égal au nombre d'élements de la séquence.

Example 1.6. Itération sur les couples (indices, éléments)

l = (-2, 3, 11)

for i, x in enumerate(l):
    print("Carré de l'élément n°",i+1,":",x**2)
Carré de l'élément n° 1 : 4
Carré de l'élément n° 2 : 9
Carré de l'élément n° 3 : 121

Itération sur les indices des éléments d'une séquence

On parcourt successivement tous les indices des éléments d'une séquence :

for i in range(len(maSequence)):
    traitement de l’élément maSéquence[i] et/ou de l’indice i

Au fil des itérations, la variable i prendra successivement pour valeur tous les indices des éléments de la séquence. Le nombre d'itérations sera là encore égal au nombre d'élements de la séquence.

Example 1.7. Itération sur les indices

l = (-2, 3, 11)

for i in range(len(l)):
    print("Carré de l'élément n°",i+1,":",l[i]**2)
Carré de l'élément n° 1 : 4
Carré de l'élément n° 2 : 9
Carré de l'élément n° 3 : 121

[Note]

Cette façon de faire n'est pas la préférée des puristes du Python qui préfèrent (quand c'est compatible avec le problème donné) manipuler les éléments plutôt que les indices.

Dans beaucoup de langages on n'aura par contre pas le choix, et on devra effectuer une itération sur les indices. Voir par exemple le cours de langage C 1GCC.

Itération sur les éléments de deux séquences

On parcourt successivement et simultanément tous les éléments de deux séquences à l'aide de l'instruction zip :

for x,y in zip(maSequence1,maSequence2):
    traitement des éléments x et y

Au fil des itérations, la variable x prendra successivement pour valeur tous les éléments de la première séquence et la variable y tous ceux de la seconde. Le nombre d'itérations sera égal au nombre d'élements de la séquence la plus petite.

Example 1.8. Itération sur deux séquences

l = (-2, 3, 11)
m = 'Keith'
for x,y in zip(l,m):
    print(x,y)
-2 K
3 e
11 i

Exercice

On propose ici au lecteur un petit exercice d'application immédiate afin qu'il puisse tester sa bonne compréhension des bases.

Exercice corrigé

1.1.

Ecrire une fonction prenant une séquence de nombre entiers en paramètre, et qui retourne le nombre d’entiers pairs de cette séquence.

Un simple parcours des éléments de la séquence conduit au résultat.

def nbPairs(s):
    n = 0
    for x in s:
        if x%2 == 0:
            n += 1
    return n

monTuple = (-4, 5, 2, 4, 1)
print(nbPairs(monTuple))
3

Les listes

On va ici s'intéresser aux spécificités des listes, et en particulier à leur caractère muable.

Les listes sont muables

Les listes sont muables et cela a deux conséquences :

  1. On peut modifier les éléments d’une liste, en supprimer, en ajouter d’autres.

  2. Une liste transmise en paramètre à un sous-programme peut être modifiée par ce dernier.

Le premier point a déjà été abordé et le sera encore dans la suite.

Le second point n'est pas anodin, car comme nous l'avons vu dans le chapitre précédent certains types de paramètres de sous-programme sont immuables. C'était le cas pour les types élémentaires de variables.

Example 1.9. Une liste modifiée par un sous-programme

Cette procédure échange les éléments de la liste passée en paramètre car cette dernière est muable :

def swap(l,i,j):
    l[i], l[j] = l[j], l[i]

maListe = [1, 2, 3, 4]
print("avant échange :",maListe)
swap(maListe,0,3)
print("après échange :",maListe)
avant échange : [1, 2, 3, 4]
après échange : [4, 2, 3, 1]

Opérations propres aux listes

On a pour l'instant utilisé la technique de slicing pour accéder aux éléments (ou à une partie) d'une liste, mais on peut également s'en servir pour modifier une liste :

Opération Résultat
s[i] = x Remplacement de l’élément s[i] par x
s[i:j] = t Remplacement des éléments de s[i:j] par ceux de la séquence t
del(s[i:j]) Suppression des éléments de s[i:j]
s[i:j:k] = t Remplacement des éléments de s[i:j:k] par ceux de la séquence t. Nécessite que le nombre d’éléments de s[i:j:k] soit le même que celui de t.
del(s[i:j:k]) Suppression des éléments de s[i:j:k]
[Note]

Cette technique est propre au Python, on ne la retrouvera pas nativement dans la plupart des autres langages.

Example 1.10. Modification d'une liste par slicing

>>> maListe = [1, 2, 3, 4, 5]
>>> maListe[2:4] = (6,'x',7)
>>> print(maListe)
[1, 2, 6, 'x', 7, 5]
>>> maListe[1:6:2] = 'sup'
>>> print(maListe)
[1, 's', 6, 'u', 7, 'p']

La technique de slicing n'est pas la seule façon de modifier une liste. En voici d'autres parmi les plus courantes :

Opération Résultat
Iist(s) Transforme une séquence s en une liste
s.append(x) Ajoute l’élément x à la fin de s
s.extend(t) Étend s avec la séquence t
s.insert(i,x) Insère l’élément x à la position i
s.clear() Supprime tous les éléments de s
s.remove(x) Retire l’élement x de s
s.pop(i) Renvoie l’élément d’indice i et le supprime
s.reverse() Inverse l’ordre des éléments de s
s.sort() Trie les éléments de s par ordre croissant

Voici quelques compléments d'informations sur ces opérations :

  • L’opération s.remove(x) renvoie une erreur si x n’appartient pas à s.

  • Par défaut s.pop() retourne le dernier élément de la liste et le supprime.

  • On peut ajouter d’autres arguments à la fonction sort, pour par exemple trier la liste par ordre décroissant. Voir la documentation officielle pour plus de détails.

Example 1.11. Quelques modifications de listes

>>> maListe = [1, 3, 5]
>>> maListe.append(7)
>>> print(maListe)
[1, 3, 5, 7]
>>> maListe.extend((8, 11))
>>> print(maListe)
[1, 3, 5, 7, 8, 11]
>>> maListe.remove(8)
>>> maListe.insert(4,9)
>>> print(maListe)
[1, 3, 5, 7, 9, 11]
>>> maListe = list(range(1,10,2))
>>> maListe
[1, 3, 5, 7, 9]
>>> taListe = list('The Strypes')
>>> taListe
['T', 'h', 'e', ' ', 'S', 't', 'r', 'y', 'p', 'e', 's']
>>> taListe.sort()
>>> taListe
[' ', 'S', 'T', 'e', 'e', 'h', 'p', 'r', 's', 't', 'y']

Le délicat problème des copies de listes

La problématique de copier une liste dans une autre est plus subtile qu'on ne pourrait le penser. La tentative de copie d’une liste avec la syntaxe naturelle

maListe2 = maListe1

ne crée en effet qu’un alias. Les deux noms pointeront vers le même emplacement mémoire et il n’y aura donc en réalité qu’une seule liste existante.

Example 1.12. Une tentative insatisfaisante pour copier une liste

Avec la syntaxe précédente, on ne fait que créer un alias :

>>> maListe1 = [1, 2, 3, 4]
>>> maListe2 = maListe1
>>> maListe2[3] = 666
>>> print(maListe1)
[1, 2, 3, 666]
>>> maListe1[0] = 'Python'
>>> print(maListe2)
['Python', 2, 3, 666]

On a donc qu'une seule liste en mémoire, et celle-ci est modifiée via n'importe lequel de ses noms.


[Note]

Dans l'exemple précédent, on aurait aussi pu constater que l'on avait qu'une seule liste en mémoire en utilisant la fonction id. Celle-ci prend une variable en paramètre et retourne son adresse en mémoire.

Cet constat n'est bien sûr pas satisfaisant. En effet, on aimerait disposer une fois la copie effectuée de deux listes possédant leur propre identité.

Pour remédier à cette difficulté, le langage Python nous offre plusieurs possibilités. En voici quelques-unes :

maListe2 = maListe1.copy()
import copy
maListe2 = copy.copy(maListe1)
maListe2 = list(maListe1)
maListe2 = []
maListe2.extend(maListe1)
maListe2 = maListe1[:]
[Note]

Ces solutions sont classées par ordre décroissant de durée.

On a omis d’autres techniques consistant à copier les éléments un par un.

Example 1.13. Une copie réussie de liste

On adopte une des syntaxes précédentes pour effectuer notre copie de liste :

>>> maListe1 = [1, 2, 3, 4]
>>> maListe2 = maListe1[:]
>>> maListe2[3] = 666
>>> print(maListe1)
[1, 2, 3, 4]
>>> maListe1[0] = 'Python'
>>> print(maListe2)
[1, 2, 3, 666]

Cette fois-ci on a deux listes en mémoire et la modification de l'une n'impacte pas l'autre.


Les copies précédentes sont dites superficielles, ce qui signifie qu'elles n'ont qu'un niveau de profondeur. Dans le cas de listes imbriquées elles sont insuffisantes, comme le montre l'exemple suivant :

Example 1.14. Une copie superficielle de listes imbriquées

On utilise une des syntaxes précédentes pour créer une copie superficielle :

>>> maListe1 = [1, [11, 22]]
>>> maListe2 = list(maListe1)
>>> maListe2[0] = 666
>>> print(maListe1)
[1, [11, 22]]
>>> maListe2[1][0] = 33
>>> print(maListe1)
[1, [33, 22]]

La première modification de "maListe2" n'impacte pas "maListe1" car elle se situe au premier niveau de profondeur. Ce n'est pas le cas pour la seconde.


Dans le cas de listes imbriquées on devra donc effectuer des copies profondes, qui vont fonctionner à tous niveaux de profondeur. Pour cela on utilisera la fonction deepcopy du module copy :

import copy
maListe2 = copy.deepcopy(maListe1)

Example 1.15. Une copie profonde de listes imbriquées

On réalise maintenant une copie profonde, le problème précédent n'existe plus :

>>> import copy
>>> maListe1 = [1, [11, 22]]
>>> maListe2 = copy.deepcopy(maListe1)
>>> maListe2[1][0] = 33
>>> print(maListe1)
[1, [11, 22]]

Listes définies "en compréhension"

On va présenter ici une technique très élégante pour construire une liste à partir d’une séquence déjà existante. Cette méthode est calquée sur la définition en compréhension d’un ensemble mathématique étudiée dans le cours de théorie des ensembles 1SET.

Plus précisément, on va effectuer une opération sur chacun des éléments d’une séquence pour obtenir une liste constituée des différents résultats.

En voici la syntaxe générale :

[expression for x in sequence if conditionnelle]

A noter qu'il peut y avoir plus d'une structure for. La partie if conditionnelle est facultative.

Example 1.16. Une première liste définie en compréhension

On élève au carré les éléments d'une séquence pour construire une liste :

t = (11, 22, 33, 44)
l = [x**2 for x in t]
print(l)
[121, 484, 1089, 1936]

On produit ici le même résultat mais sans utiliser cette technique. On ne peut que noter que le code est plus lourd et moins intuitif :

t = (11, 22, 33, 44)
l=[]
for x in t:
    l.append(x**2)
print(l)
[121, 484, 1089, 1936]

Example 1.17. Une seconde liste définie en compréhension

On utilise ici deux boucles for et une conditionnelle :

l = [(i,j) for i in range(1,4) for j in range(1,4) if i != j]
print(l)
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

Listes multidimensionnelles

On a déjà constaté sur un exemple que les éléments d'une liste pouvaient être eux-mêmes une liste. On peut ainsi créer des listes multidimensionnelles.

Le cas bidimensionnel sera le plus fréquent puisqu'il s'agit alors de matrices. En pratique de telles listes pourront servir à simuler des plateaux de jeu (échec, go, puissance 4, etc.), ou à effectuer des calculs (simulation 3D par exemple).

[Note]

Voir le cours 1LAL pour une étude du calcul matriciel.

L'accès à un élément d'une telle liste se fait avec une syntaxe de la forme :

maListe[i1][i2]...[iN]

où N est le nombre de dimensions de la liste.

Il va falloir accorder un soin tout particulier à l'initialisation de listes multidimensionnelles, comme nous allons le voir sur un exemple. Sinon le problème déjà soulevé des copies de listes va se poser de nouveau.

Example 1.18. Une initialisation ratée d'une liste bidimensionnelle

On souhaite initialiser une liste à 4 lignes et 3 colonnes avec des 0 partout. On utilise pour se faire l'opération * de concaténation :

plateau = [[0]*3]*4
print(plateau)
plateau[3][2] = 666
print(plateau)
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 0, 666], [0, 0, 666], [0, 0, 666], [0, 0, 666]]

Le problème ici vient du fait que l'on a créé quatre alias de la même liste [0, 0, 0]. La modification de l’un de ces alias entraine donc la modification des autres.


Example 1.19. Une initialisation réussie d'une liste bidimensionnelle

Toujours dans le but d'initialiser une liste à 4 lignes et 3 colonnes avec des 0 partout, on va cette fois-ci répéter quatre fois (à l'aide d'une boucle for) la création d'une liste valant [0, 0, 0] :

plateau = [[0]*3 for i in range(4)]
print(plateau)
plateau[3][2] = 666
print(plateau)
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 666]]

Le problème précédent ne se pose plus car on a créé ici quatre listes différentes.


De façon tout à fait naturelle, le parcours d'une liste multidimensionnelle se fera en imbriquant autant de structures itératives qu'elle a de dimensions.

Example 1.20. Un parcours d'une liste bidimensionnelles

On parcourt chaque élément d'une liste à 4 lignes et 3 colonnes afin de réaliser un affichage "propre" de celle-ci :

plateau = [[0]*3 for i in range(4)]
plateau[3][2] = 666
for ligne in plateau:
    for x in ligne:
        print(x,' ',end='')
    print('\n')
0  0  0  

0  0  0  

0  0  0  

0  0  666

Exercice

On propose ici au lecteur un petit exercice d'application immédiate afin qu'il puisse tester sa bonne compréhension des bases.

Exercice corrigé

1.1.

Ecrire écrire une fonction prenant une séquence de nombre entiers en paramètre, et qui retourne une liste de booléens de la même taille. Le i-ème élément de cette liste retournée vaudra True si le i-ème élément du paramètre est pair, et False sinon.

On utilise une définition de liste en compréhension afin d'avoir un code élégant.

def parite(s):
    return [(n%2 == 0) for n in s]

monTuple = (-4, 5, 2, 4, 1)
print(parite(monTuple))
[True, False, True, True, False]

Les t-uples

On va ici s'intéresser aux spécificités des t-uples, et en particulier à leur caractère immuable.

Les t-uples sont immuables

Les t-tuples sont immuables et cela a deux conséquences :

  1. On ne peut pas modifier les éléments d’un t-uple, en supprimer, en ajouter d’autres.

  2. Un t-uple transmis en paramètre à un sous-programme ne peut pas être modifié par ce dernier.

Le premier point a déjà été abordé et le sera encore dans la suite.

[Note]

Le second point est évidemment une conséquence directe du premier, si l'on ne peut pas modifer un t-uple dans l'absolu, c'est tout à fait logique qu'un sous-programme ne puisse pas le faire en particulier. Ceci dit l'auteur a souhaité mettre ce fait en évidence.

Example 1.21. Un t-uple ne peut pas être modifié par un sous-programme

Cette procédure tente d'échanger les éléments du t-uple passé en paramètre, mais elle échoue car ce dernier est immuable :

def swap(l,i,j):
    l[i], l[j] = l[j], l[i]

monTuple = (1, 2, 3, 4)
print("avant échange :",monTuple)
swap(monTuple,0,3)
print("après échange :",monTuple)
avant échange : (1, 2, 3, 4)
Traceback (most recent call last):
  File "/Users/laurentgodefroy/Desktop/Codes1ADS.py", line 372, in <module>
    swap(monTuple,0,3)
  File "/Users/laurentgodefroy/Desktop/Codes1ADS.py", line 368, in swap
    l[i], l[j] = l[j], l[i]
TypeError: 'tuple' object does not support item assignment

Opérations propres aux t-uples

Les t-uples étant immuables il n'y a nécessairement que très peu d'opérations qui leurs sont propres. Citons celle qui nous permet de déclarer un t-uple à partir d'une séquence :

monTuple = tuple(maSequence)

Example 1.22. Initialisation d'un t-uple à partir d'une séquence

On déclare ici un t-uple à l'aide d'une séquence définie par la fonction range, puis un autre à partir d'une chaîne de caractères :

>>> monTuple = tuple(range(0,9,2))
>>> monTuple
(0, 2, 4, 6, 8)
>>> monTuple = tuple("The Decemberist")
>>> monTuple
('T', 'h', 'e', ' ', 'D', 'e', 'c', 'e', 'm', 'b', 'e', 'r', 'i', 's', 't')

Il n'y pas de définition en compréhension des t-uples comme celle des listes. Pour faire quelque chose d'approchant, on utilisera la construction précédente qui utilise l'instruction tuple.

Example 1.23. Un t-uple (presque) défini en compréhension

On utilise successivement une syntaxe en compréhension et l'instruction tuple :

t = (11, 22, 33, 44)
l = tuple(x**2 for x in t)
print(l)
(121, 484, 1089, 1936)

Intérêts des t-uples

Nous allons présenter quelques éléments qui justifient l'utilisation de t-uples malgré leur caractère immuable et donc moins maniable que les listes :

  • Si on veut définir une séquence de données que l’on ne veut pas modifier, utiliser un t-uple sécurise ce fait et prévient toute erreur de code.

  • Itérer sur les éléments d’un t-uple est plus rapide que sur ceux d’une liste. Si la performance est critique dans la résolution d'un problème donné, ce facteur est à prendre en compte.

  • Une fonction qui retourne plusieurs valeurs, retourne en fait un t-uple.

  • Les t-uples peuvent être utilisés comme des clés de dictionnaire (voir chapitre sept), ce qui ne sera pas le cas des listes.

Sous-programmes avec nombre variable de paramètres

En Python un sous-programme peut admettre un nombre variable de paramètres. Ceux-ci ne possèdent pas alors de noms individuels, et le sous-programme les traite comme étant regroupés dans un t-uple.

Voici comment il convient de déclarer un tel sous-programme :

def monSousProgramme(para1,para2,...,*args):
    bloc d’instructions du sous-programme
    traitant les paramètres 1,2 etc.
    ainsi que les paramètres en nombre
    variable regroupés dans le t-uple
    nommé ici "args".
    (return valeur)

Example 1.24. Une procédure ayant un nombre variable de paramètres

On utilise cette procédure une première fois avec trois paramètres et une seconde fois avec deux :

def relations(ami,*args):
    for i,name in enumerate(args):
        print("mon",ami,"n°",i+1,":",name)

relations("ami","mick","keith","ron")
relations("ennemi","john","paul")
mon ami n° 1 : mick
mon ami n° 2 : keith
mon ami n° 3 : ron
mon ennemi n° 1 : john
mon ennemi n° 2 : paul

Exercices

On propose maintenant au lecteur deux petits exercices d'applications immédiates des t-uples afin qu'il puisse tester sa bonne compréhension des bases.

Exercice corrigé

1.1.

Ecrire une fonction calculant le produit d’un nombre variable de paramètres.

Pour calculer un produit, on initialise une variable à 1 et à chaque itération on multiplie le résultat courant par un nouveau facteur.

def produit(*nombres):
    p = 1
    for x in nombres:
        p *= x
    return p
-120

Exercice corrigé

1.1.

En utilisant le t-uple ('a', 'e', 'i', 'o', 'u'), écrire une fonction calculant le nombre de voyelles d’un texte.

L'utilisation d'un t-uple est légitime car l'ensemble des voyelles est constant.

def voyelles(mot):
    t = ('a','e','i','o','u')
    s = 0
    mot = mot.lower()
    for x in t:
        s += mot.count(x)
    return s

print(voyelles('Alamo'))
3
A propos de SUPINFO | Contacts & adresses | Enseigner à SUPINFO | Presse | Conditions d'utilisation & Copyright | Respect de la vie privée | Investir
Logo de la société Cisco, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société IBM, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Sun-Oracle, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Apple, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Sybase, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Novell, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Intel, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Accenture, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société SAP, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo de la société Prometric, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management Logo du IT Academy Program par Microsoft, partenaire pédagogique de SUPINFO, la Grande École de l'informatique, du numérique et du management

SUPINFO International University
Ecole d'Informatique - IT School
École Supérieure d'Informatique de Paris, leader en France
La Grande Ecole de l'informatique, du numérique et du management
Fondée en 1965, reconnue par l'État. Titre Bac+5 certifié au niveau I.
SUPINFO International University is globally operated by EDUCINVEST Belgium - Avenue Louise, 534 - 1050 Brussels