Table des matières

Séquences, méthodes plus avancées

Dans le chapitre sur les bases on a présenté ce qu'était une séquence et comment on accédait à ses éléments. En Python, on dispose de syntaxe permettant d'aller plus loin.

Indice négatif

Un indice négatif indique que l'on compte depuis la fin :

>>> t = [4, 19, 25, 78, 29]
>>> t[-1]
29
>>> t[-2]
78
>>> t[-5]
4
>>> t[-6]
IndexError: list index out of range

Autrement dit, si n = len(t) alors t[-1] est équivalent à t[n-1].

Slices

Les slices sont des découpage que l'on pourra faire dans les séquences. Python est très efficace pour cela – slice = tranche, comme un tranche de saucisson.

>>> t = [4, 19, 25, 78, 29, 42, 15, 89]
>>> t[2:5]
[25, 78, 29]

En choisissant 2:5 à la place de l'indice, on indique que l'on veut les éléments allant du rang 2 au rang 5 non compris.

C'est une constante de la syntaxe Python. Quand on indique de a à b, il faut comprendre que b est exclus.

Les possibilités sont très nombreuses :

>>> t = [4, 19, 25, 78, 29, 42, 15, 89]
>>> t[:3]    # jusque au rang 3
[4, 19, 25]
>>> t[3:]    # à partir du rang 3
[78, 29, 42, 15, 89]
>>> t[:-1]   # jusqu'au dernier (non compris comme toujours)
[4, 19, 25, 78, 29, 42, 15]
>>> t[-2:]   # les deux derniers
[15, 89]

La syntaxe est la même pour une chaîne de caractères

>>> t = "abcdefghij"
>>> t[:3]    # jusque au rang 3
'abc'
>>> t[3:]    # à partir du rang 3
'defghij'
>>> t[:-1]   # jusqu'au dernier (non compris comme toujours)
'abcdefghi'
>>> t[-2:]   # les deux derniers
'ij'

Un peu surprenant, on n'a pas de IndexError avec une slice :

>>> t = "abcdefghij"
>>> t[5:1000]
'fghij'

Indiquer un pas

On peut également indiquer que l'on souhaite parcourir la séquence de 2 en 2, de 3 en 3…

>>> t = "abcdefghijjlmn"
>>> t[1:8:3]
'beh'

1:8:3 → Du rang 1 au rang 8 (exclus) par pas de 3, donc les rangs 1, 4, 7

En enlevant le 8, 1::3 → Du rang 1 à la fin, par pas de 3.

>>> t = "abcdefghijjlmn"
>>> t[1::3]
'behjn'

Et avec un pas négatif, on peut parcourir à l'envers !

>>> t = "abcdefghijjlmn"
>>> t[8:1:-3]  # parcours les rangs 8, 5, 2
'ifc'
>>> t[::-1]    # totalité, à l'envers !
'nmljjihgfedcba'

Concaténations

Concaténer deux séquences a et b, c'est créer une 3e séquence c constituée de a et b mises bout à bout. On utilise cela l'opérateur +.

>>> [4, 5, 6] + [7, 8, 9]
[4, 5, 6, 7, 8, 9]
>>> "abc" + "def"
'abcdef'
>>> (1, 2) + (7, 8)
(1, 2, 7, 8)

En lisant l'opérateur +, Python examine les opérandes et adapte son comportement.

  • 3 + 7 : les opérandes sont des entiers, Python réalise une addition ordinaire,
  • "abc" + "xyz" : les opérandes sont des chaînes, Python réalise une concaténation,
  • "abc" + 5 : voyant une chaîne, Python tente une concaténation mais cela ne fonctionnera pas avec l'entier → TypeError: can only concatenate str (not "int") to str.

Dans la même logique, on peut utiliser l'opérateur * :

>>> "ab" + "ab" + "ab"
'ababab'
>>> "ab" * 3
'ababab'

Dépaquetage (unpack)

On peut distribuer les items contenus dans une séquence vers des variables, à condition que les variables soient en nombre égal au nombre d'items.

>>> a, b, c = "xyz"
>>> a
'x'
>>> b
'y'
>>> c
'z'

Dans cet exemple, la chaîne "xyz" contient 3 items, des caractères. En écrivant a, b, c = "xyz" on affecte aux variables a, b et c ces 3 caractères, respectivement.

Si on met trop ou pas assez de variables, on a une erreur.

>>> t = 4, 9, 17
>>> a, b, c, d = t
ValueError: not enough values to unpack (expected 4, got 3)
>>> a, b = t
ValueError: too many values to unpack (expected 2)

Ce mécanisme est surtout utilisé avec les tuples – ci dessous, un extrait de p-uplets - tuple

Cas d'utilisation

Je donne ci-dessous quelques cas d'utilisation

Affectation multiple

Au lieu de

x = 3
y = 5
z = 8

On peut écrire

x, y, z = 3, 5, 8

Fonction à sorties multiples

Une fonction qui doit renvoyer deux quantités. Par exemple la somme et le produit de x et y.

def somme_produit(x,y):
    return x + y, x * y

# utilisation
s, p = somme_produit(4,5)
print(s) # affiche 9
print(p) # affiche 20

Remarquez que dans l'exemple en ligne 5, somme_produit(4,5) renvoie le tuple 9, 20 et on a ainsi l'affectation s, p = 9, 20 qui est équivalent à s = 9 ; p = 20.

Intervertir des variables

a et b sont deux variables contenant des données éventuellement différentes et on souhaiterait intervertir les contenus de a et b. En général, on a besoin d'une 3e variable temporaire. Vous pouvez comparer cela au cas de deux bouteilles dont on souhaite intervertir le contenu. Il faut une 3e bouteille.

temp = a # copie le contenu de a dans la variable temporaire
a = b # efface a pour copier le contenu de b
b = c # utilise la copie car a a perdu son contenu d'origine

Un tuple permet de faire cela de façon plus rapide et plus lisible :

b, a = a, b

À droite de =, on crée un tuple contenant une copie de a et de b. Puis on utilise cette copie pour la distribuer sur b et a.