Les séquences

Revenons à l’écriture binaire d’un entier fournie par la fonction bin().

Que vaut bin(42) ? Plus exactement quel type de variable est renvoyé et quelle est la valeur renvoyée ?

Réponse ?

Accéder à un élément d’une séquence

Quel est le 3ème bit du nombre 42 en partant de la gauche (bit de poids fort compris) ?

Les strings

Il faut savoir qu’en Python une chaîne de caractères ou string est une séquence de caractères dont leur position est identifiée par un numéro (appelé index). On peut faire le lien avec les suites en mathématiques.

Dans une séquence, l’index de référence est celui du premier élément de gauche qui a pour index 0. En mathématiques, le premier élément de la suite serait \(u_0\).

En pratique,

bin(42) notée ch '0' 'b' '1' '0' '1' '0' '1' '0'
Position/Index 0 1 2 3 4 5 6 7

Ainsi, le bit qui est demandé est en position 4. On le récupère avec ch[4].

Que vaut ch[1] ?

Réponse ?

Que valent ch[7] et ch[8] ?

Réponse ?

L’indexation d’une séquence (de gauche à droite) ne peut pas dépasser la longueur de celle-ci.

Quel est le bit de poids faible ? Comment le récupèrer dans la séquence ?

  • Si on connaît la longueur de la séquence, le dernier élément de la séquence est donné par ch[longueur - 1].

  • Et si on ne la connaît pas ce qui est généralement le cas, Python autorise à faire appel à des positions négatives par rapport au premier élément.

>>> ch[-1]
'0'

ch[-1] renvoie le dernier élément (celui qui est le plus à droite) de la séquence ch.

Que va retourner ch[-6] ? ch[-11] ?

Réponse ?

Les tuples

Les uplets ou tuples sont également des séquences.

>>> t = ('N', 'S', 'I')
>>> t[0]
'N'

Accéder à la totalité ou une partie des élèments d’une séquence

Méthode 1: la boucle bornée FOR

>>> ch = '0b101010'
>>> for element in ch:
        print(element)  # permet d'afficher chaque élément
0
b
1
0
1
0
1
0

Écrire une fonction nommée longueur qui retourne la longueur d’une chaîne de caractères donnée en paramètre.

Jeu de test:

>>> longueur('abcde')
5
Une solution ?

Il est bon de savoir que Python fournit déjà une fonction donnant la longueur d’une séquence: len().

>>> ch = '0b101010'
>>> len(ch)
8

Méthode 2: la boucle bornée FOR avec usage de la fonction range()

>>> ch = '0b101010'
>>> for i in range(len(ch)):
        print(ch[i], end='')  # permet d'afficher chaque élément sans passer à la ligne
0b101010

On a utilisé une nouvelle fonction range().

Pour a, b et p trois entiers,

  • range(a,b,p) renvoie la séquence* des entiers de a **inclus** à b **exclus** avec un pas égal à p.

  • range(a,b) est équivalent à range(a,b,1),

  • range(a) est équivalent à range(0,a,1). Ainsi, range(8) est la séquence des entiers de 0 inclus à 8 exlus.

Écrire une fonction occurrences() de paramètres mot une chaîne de caractères et lettre un caractère et qui retourne le nombre d’occurrences de ce dernier dans la chaîne donnée.

Jeu de test:

>>> occurrences('0b101010', '0')
4
Réponse ?

Il est aussi bon de savoir que Python fournit pour certains types d’objets des méthodes qui sont spécifiques à ceux-ci. Par exemple, il existe une méthode spécifique aux strings pour compter le nombre d’occurrences d’un string dans un autre: count(). Pour appliquer cette méthode à ch (qui vaut 0b101010), on écrit:

>>> ch = '0b101010'
>>> ch.count('0')
4

Méthode 3: les tranches aussi appelées slices

>>> ch = '0b101010'
>>> ch[2:5]  # la tranche constituée de ch[2], ch[3], ... jusqu'à ch[5] exclus
'101'
>>> ch[5:] #  la tranche constituée de ch[5], ch[6], ... jusqu'au dernier élément
'010'
>>> ch[:5] # la tranche constituée du premier élement inclus jusqu'à ch[5] exclus
'0b101'
>>> ch[1:6:2] # la tranche constituée de ch[1], ch[3], ... jusqu'à ch[6] exclus
'b00'
>>> ch[::3] # la tranche constituée de ch[0], ch[3], ... jusqu'au dernier si son index est un multiple de 3
'001'

Modifier un élement d’une séquence

Modifier un élément d’une chaîne de caractères ? Impossible !

… à moins de créer une nouvelle chaîne de caractères.

Heureusement que c’est le cas ! une chaîne de caractères est constituée de caractères. Permettrela modification d’un caractère chamboulerait tout l’alphabet !

Les strings sont non mutables.

En détails,

Source: PythonTutor

Modifier un élément d’un tuple ? Impossible !

… à moins de créer un nouveau tuple.

Les tuples sont définis ainsi dans Python. Les tuples sont non mutables.

Mais alors, comment modifier un élément d’une séquence sans devoir tout recréer ? Une solution est d’utiliser un nouveau type de variable définie dans Python que sont les listes ou lists.

>>> ls = ['0', 'b', '1', '0', '1', '0', '1', '0']  # une liste de chaînes de caractères
>>> type(ls)
<class 'list'>
>>> ls[1]
'b'
>>> type(ls[1])
<class 'string'>

Modifier un élément d’une liste

Les listes ont été définies comme étant mutables.

>>> ls = ['0', 'b', '1', '0', '1', '0', '1', '0']
>>> lst[1] = 'x'
>>> lst
['0', 'x', '1', '0', '1', '0', '1', '0']

Avec quelques détails supplémentaires,

Source: PythonTutor

Vous pouvez faire le lien avec ce que l’on a vu avec le système de fichiers géré par l’OS et les commandes ln et cp:

  • ln copie en profondeur ou deep copy: on a deux liens qui pointent vers un seul même fichier au niveau de l’adresse mémoire. Toute modification sur ce fichier sera visible naturellement par ces deux liens;
  • cp copie en surface ou shallow copy: on a deux liens qui pointent vers deux fichiers différents au niveau de l’adresse mémoire mais avec le même contenu à la création sauf modification de l’un des deux.

Fabriquer une séquence

Fabriquer une séquence en partant de zéro:

1) Création explicite avec usage des fonctions range() ou len() si besoin

Exemples avec la création d’une liste:

  • La liste des 5 entiers positifs impairs:
>>> liste_impairs = [1, 3, 5, 7, 9]
>>> liste_impairs
[1, 3, 5, 7, 9]
  • La même liste créée avec range()
>>> liste_impairs = [0, 0, 0, 0, 0]      # initialisation de la liste avec 5 éléments
>>> for i in range(len(liste_impairs)):
...     liste_impairs[i] = 2*i+1         # on modifie chacun de ces éléments
... 
>>> liste_impairs
[1, 3, 5, 7, 9]
  • Encore la même liste créer en partant d’une autre séquence avec usage de fonctions ou méthodes spécifiques au type de la séquence donnée:
>>> ch_impairs = '13579'
>>> liste_impairs = list(ch_impairs)
>>> liste_impairs
['1', '3', '5', '7', '9']
>>> for i in range(len(liste_impairs)):
...     liste_impairs[i] = int(liste_impairs[i])
...
>>> liste_impairs
[1, 3, 5, 7, 9]

Voir aussi les fonctions tuple(), str() et la méthode spécifique aux strings split() qui découpe la chaîne de caractères en une liste de mots.

>>> phrase = "La NSI, c'est cool !" # obligation d'utiliser des "" (paire de guillemets) ou des ''' ''' (paire de triples apostrophes) en lieu et place des '' (simples quotes/apostrophes) en raison de la présence du ' après le c
>>> phrase.split()
['La', 'NSI,', "c'est", 'cool', '!']
>>> phrase                          # la variable phrase n'est pas modifiée d'ailleurs le pourrait-on vue la non mutabilité des chaînes de caractères ?
"La NSI, c'est cool !"
>>> mots = phrase.split() # pour mémoriser la liste des mots

Autre exemple bien pratique afin de réaliser des simulations en particulier des expériences aléatoires:

  • Simuler de 3 lancers d’un dé à 6 faces numérotées de 1 à 6 ? Rien de plus simple !
>>> import random
>>> lancers = [0, 0, 0]
>>> for i in range(3):
...     lancers[i] = random.randint(1,6)
... 
>>> lancers
[3, 4, 2]
  • Choisir au hasard 3 caractères dans une chaîne de caractères ? C’est parti !
>>> import random
>>> phrase = "La NSI, c'est cool !"
>>> choix = [0, 0, 0]
>>> for i in range(3):
...     choix[i] = random.choice(phrase)
... 
>>> choix
['o', 'N', 'c']

Construire la liste de longueur 10 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] où les deux premiers elements sont égaux à 1 et chacun des éléments suivants est égal à la somme des deux précédents (ex: \(1+1=2, 1+2=3, 3+5=8, 3+5=8, …\)).

Réponse possible

2) Création d’une séquence par compréhension

Reprenons les exemples précédents

>>> liste_impairs = [2*i+1 for i in range(5)]
>>> liste_impairs
[1, 3, 5, 7, 9]
>>> import random
>>> lancers = [random.randint(1,6) for _ in range(3)]
>>> lancers
[3, 5, 6]

Écrire la liste par compréhension obtenue par le choix aléatoire de 3 caractères dans la phrase "La NSI, c'est cool !".

Déroulez-moi...

Fabriquer une séquence à partir d’autres séquences

Très pratique puisque

  • cela dispense d’initialiser la longueur de la séquence à construire au départ;
  • cela permet la construction de séquences dont la longueur varie.

1) Création par concaténation

Exemple applicable à tous les types de séquences

>>> t1 = (1, 3, 5, 7)
>>> t2 = (9,)
>>> t1 = t1 + t2
>>> t1
(1, 3, 5, 7, 9)
>>> t2 = t1 * 3
>>> t2
(1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9)

Vigilance avec les séquences de listes en raison de la mutabilité de ces dernières !

>>> t=([1, 2, 5], )*2    # fabrication d'un tuple contenant 2 copies profondes
                         # qui pointent vers la seule liste [1, 2, 5]
>>> t
([1, 2, 5], [1, 2, 5])
>>> t[0]
[1, 2, 5]
>>> id(t[0]) == id(t[1])
True
>>> t[0][1] = 3 
>>> t
([1, 3, 5], [1, 3, 5])  # pas de surprise car les listes pointent vers la même 
                        # liste (même adresse) sur laquelle on apporte la modif

Exemple spécifique au listes avec l’emploi des méthodes append() et insert():

>>> liste_impairs = [1, 3, 7]
>>> liste_impairs.append(9)       # ajoute 9 en fin de liste
>>> liste_impairs
[1, 3, 7, 9]
>>> liste_impairs.insert(2, 5)    # insérer dans la liste en index 2 la valeur 5
>>> liste_impairs
[1, 3, 5, 7, 9]

Reprenons la construction de la liste des entiers impairs mais strictement inférieurs à 14.

  • par concaténation
def impairs_v1(n):
    """
    Retourne la liste des entiers impairs strictement inférieurs à n.
    
    :param n: (int) la borne supérieure à ne pas dépasser
    :return resultat: (list) la liste désirée
    """
    resultat = []
    for i in range(n):  # il est certain que la liste cherchée contient moins de n éléments
        if 2*i+1 < n:
            resultat.append(2*i+1)
        else: break
    return resultat

def impairs_v2(n):
    """
    Retourne la liste des entiers impairs strictement inférieurs à n.
    
    :param n: (int) la borne supérieure à ne pas dépasser
    :return resultat: (list) la liste désirée
    """
    resultat = []
    i = 0
    while 2*i+1 < n:
       resultat.append(2*i+1)
       i = i + 1
    return resultat
    

>>> impairs_v2(14)
[1, 3, 5, 7, 9, 11, 13]
  • par compréhension
def impairs_v3(n):
    """
    Retourne la liste des entiers impairs strictement inférieurs à n.
    
    :param n: (int) la borne supérieure à ne pas dépasser
    :return: (list) la liste désirée
    """
    return [2*i+1 for i in range(n) if 2*i+1<n]


>>> impairs_v3(14)
[1, 3, 5, 7, 9, 11, 13]
Remarque: construction explicite possible !

Créer la liste de termes de la suite de Fibonacci strictement inférieurs à 1000.

Déroulez-moi...

Autre exemple: créer les 52 cartes à jouer ? C’est parti !

>>> valeurs = [str(_+1) for _ in range(10)] + ['J', 'Q', 'K']
>>> couleurs = ['S', 'H', 'D', 'C']
>>> cartes = []
>>> for c in couleurs:
...     for v in valeurs:
...             cartes.append(v+c)
... 
>>> cartes
['1S', '2S', '3S', ..., '9C', '10C', 'JC', 'QC', 'KC']
>>> len(cartes)
52

Petit bonus: vous voulez battre les cartes ?

>>> random.shuffle(cartes)
>>> cartes
['JS', '8H', 'JC', '4C', ..., '1S', '7H', '5C', 'KH']

2 ) Création par suppression d’élèments

  • Seule façon commune à tous les types de séquences: le tranchage/slicing (déjà vu)

  • Les autres moyens sont spécifiques au type de la séquence

Exemple avec les méthodes sur les strings:

>>> ch1 = '  0123    '   # chaîne de longueur 10 avec 6 caractères espaces
>>> ch2 = ch1.strip()    # les strings étant non mutables, cela définit un
                         # nouveau string
>>> ch2
'0123'
>>> ch1
'  0123    '

Exemple avec les fonctions et méthodes sur les listes:

>>> liste_impairs = [1, 3, 5, 9]
>>> element = liste_impairs.pop()  # récupère le dernier élément de la liste et
                                   # l'enlève de la liste
>>> element
9
>>> liste_impairs
[1, 3, 5]

Voir la fonction sur les listes del() et la méthode remove().

Aide-mémoire:

Document rassemblant les principales fonctions et méthodes sur les séquences notamment1


Notes de bas de page:

  1. Source du document: le MOOC “Apprendre à coder avec Python” sur la plateforme FUN qui rouvre régulièrement et qui est accessible gratuitement. ↩︎