Complément - niveau basique¶
Voici quelques unes des méthodes disponibles sur le type list.
Trouver l’information¶
Pour commencer, rappelons comment retrouver la liste des méthodes définies sur le type list :
help(list)Help on class list in module builtins:
class list(object)
| list(iterable=(), /)
|
| Built-in mutable sequence.
|
| If no argument is given, the constructor creates a new empty list.
| The argument must be an iterable if specified.
|
| Methods defined here:
|
| __add__(self, value, /)
| Return self+value.
|
| __contains__(self, key, /)
| Return bool(key in self).
|
| __delitem__(self, key, /)
| Delete self[key].
|
| __eq__(self, value, /)
| Return self==value.
|
| __ge__(self, value, /)
| Return self>=value.
|
| __getattribute__(self, name, /)
| Return getattr(self, name).
|
| __getitem__(self, index, /)
| Return self[index].
|
| __gt__(self, value, /)
| Return self>value.
|
| __iadd__(self, value, /)
| Implement self+=value.
|
| __imul__(self, value, /)
| Implement self*=value.
|
| __init__(self, /, *args, **kwargs)
| Initialize self. See help(type(self)) for accurate signature.
|
| __iter__(self, /)
| Implement iter(self).
|
| __le__(self, value, /)
| Return self<=value.
|
| __len__(self, /)
| Return len(self).
|
| __lt__(self, value, /)
| Return self<value.
|
| __mul__(self, value, /)
| Return self*value.
|
| __ne__(self, value, /)
| Return self!=value.
|
| __repr__(self, /)
| Return repr(self).
|
| __reversed__(self, /)
| Return a reverse iterator over the list.
|
| __rmul__(self, value, /)
| Return value*self.
|
| __setitem__(self, key, value, /)
| Set self[key] to value.
|
| __sizeof__(self, /)
| Return the size of the list in memory, in bytes.
|
| append(self, object, /)
| Append object to the end of the list.
|
| clear(self, /)
| Remove all items from list.
|
| copy(self, /)
| Return a shallow copy of the list.
|
| count(self, value, /)
| Return number of occurrences of value.
|
| extend(self, iterable, /)
| Extend list by appending elements from the iterable.
|
| index(self, value, start=0, stop=9223372036854775807, /)
| Return first index of value.
|
| Raises ValueError if the value is not present.
|
| insert(self, index, object, /)
| Insert object before index.
|
| pop(self, index=-1, /)
| Remove and return item at index (default last).
|
| Raises IndexError if list is empty or index is out of range.
|
| remove(self, value, /)
| Remove first occurrence of value.
|
| Raises ValueError if the value is not present.
|
| reverse(self, /)
| Reverse *IN PLACE*.
|
| sort(self, /, *, key=None, reverse=False)
| Sort the list in ascending order and return None.
|
| The sort is in-place (i.e. the list itself is modified) and stable (i.e. the
| order of two equal elements is maintained).
|
| If a key function is given, apply it once to each list item and sort them,
| ascending or descending, according to their function values.
|
| The reverse flag can be set to sort in descending order.
|
| ----------------------------------------------------------------------
| Class methods defined here:
|
| __class_getitem__(...)
| See PEP 585
|
| ----------------------------------------------------------------------
| Static methods defined here:
|
| __new__(*args, **kwargs)
| Create and return a new object. See help(type) for accurate signature.
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| __hash__ = None
Ignorez les méthodes dont le nom commence et termine par __ (nous parlerons de ceci en semaine 6), vous trouvez alors les méthodes utiles listées entre append et sort.
Certaines de ces méthodes ont été vues dans la vidéo sur les séquences, c’est le cas notamment de count et index.
Nous allons à présent décrire les autres, partiellement et brièvement. Un autre complément décrit la méthode sort. Reportez-vous au lien donné en fin de notebook pour obtenir une information plus complète.
Donnons-nous pour commencer une liste témoin :
liste = [0, 1, 2, 3]
print('liste', liste)The history saving thread hit an unexpected error (OperationalError('attempt to write a readonly database')).History will not be written to the database.
liste [0, 1, 2, 3]
Avertissements :
soyez bien attentifs au nombre de fois où vous exécutez les cellules de ce notebook ;
par exemple une liste renversée deux fois peut donner l’impression que
reversene marche pas ;n’hésitez pas à utiliser le menu Cell -> Run All pour réexécuter en une seule fois le notebook entier.
append¶
La méthode append permet d’ajouter un élément à la fin d’une liste :
liste.append('ap')
print('liste', liste)liste [0, 1, 2, 3, 'ap']
extend¶
La méthode extend réalise la même opération, mais avec tous les éléments de la liste qu’on lui passe en argument :
liste2 = ['ex1', 'ex2']
liste.extend(liste2)
print('liste', liste)liste [0, 1, 2, 3, 'ap', 'ex1', 'ex2']
append vs +¶
Ces deux méthodes append et extend sont donc assez voisines ; avant de voir d’autres méthodes de list, prenons un peu le temps de comparer leur comportement avec l’addition + de liste. L’élément clé ici, on l’a déjà vu dans la vidéo, est que la liste est un objet mutable. append et extend modifient la liste sur laquelle elles travaillent, alors que l’addition crée un nouvel objet.
# pour créer une liste avec les n premiers entiers, on utilise
# la fonction built-in range(), que l'on convertit en liste
# on aura l'occasion d'y revenir
a1 = list(range(3))
print(a1)[0, 1, 2]
a2 = list(range(10, 13))
print(a2)[10, 11, 12]
# le fait d'utiliser + crée une nouvelle liste
a3 = a1 + a2# si bien que maintenant on a trois objets différents
print('a1', a1)
print('a2', a2)
print('a3', a3)a1 [0, 1, 2]
a2 [10, 11, 12]
a3 [0, 1, 2, 10, 11, 12]
Comme on le voit, après une addition, les deux termes de l’addition sont inchangés. Pour bien comprendre, voyons exactement le même scénario sous pythontutor :
%load_ext ipythontutorNote : une fois que vous avez évalué la cellule avec %%ipythontutor, vous devez cliquer sur le bouton Next pour voir pas à pas le comportement du programme.
%%ipythontutor height=230 ratio=0.7
a1 = list(range(3))
a2 = list(range(10, 13))
a3 = a1 + a2Alors que si on avait utilisé extend, on aurait obtenu ceci :
%%ipythontutor height=200 ratio=0.75
e1 = list(range(3))
e2 = list(range(10, 13))
e3 = e1.extend(e2)Ici on tire profit du fait que la liste est un objet mutable : extend modifie l’objet sur lequel on l’appelle (ici e1). Dans ce scénario on ne crée en tout que deux objets, et du coup il est inutile pour extend de renvoyer quoi que ce soit, et c’est pourquoi e3 ici vaut None.
C’est pour cette raison que :
l’addition est disponible sur tous les types séquences - on peut toujours réaliser l’addition puisqu’on crée un nouvel objet pour stocker le résultat de l’addition ;
mais
appendetextendne sont par exemple pas disponibles sur les chaînes de caractères, qui sont immuables - sie1était une chaîne, on ne pourrait pas la modifier pour lui ajouter des éléments.
Digression : les magic de IPython¶
Arrêtons-nous une seconde pour commenter l’usage qu’on vient de faire de %load_ext et %%ipythontutor.
Ces commandes, qui commencent par un signe pourcent %, sont des commandes magiques (magic) de IPython; du coup elles ne sont disponibles que dans IPython ou un notebook.
Et je signale pour finir, pour les curieux, que
vous pouvez trouver une liste de ces commandes ici
et qu’une commande peut exister sous deux formes : avec un seul pourcent, la commande s’applique à la ligne, alors qu’avec deux pourcent cela concerne toute la cellule.
Ainsi notamment la commande magique %timeit, qui permet de faire des benchmarks et comparer finement des temps d’exécution, s’utilise comme ceci
# avec un seul pourcent une commande magique concerne une seule ligne
# un peu de patience, c'est un petit peu long à exécuter
%timeit L1 = list(range(1000))
L2 = list(range(1000))19.4 μs ± 2.64 μs per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
%%timeit
# avec deux pourcent, cela concerne toute la cellule
L1 = list(range(1000))
L2 = list(range(1000))36.9 μs ± 14.1 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
# et comme vous le voyez ici il faut dans ce cas-là
# la mettre en première ligne de la cellule
# il y a une certaine logique à cela, mais bon
%%timeit
L1 = list(range(1000))
L2 = list(range(1000))UsageError: Line magic function `%%timeit` not found.
Vous remarquez surtout que %timeit exécute l’instruction un grand nombre de fois, c’est pour pouvoir faire une moyenne qui soit pertinente (on peut modifier ce nombre en passant des options à timeit, mais ne nous égarons pas…)
insert¶
Mais reprenons notre inventaire des méthodes de list, et pour cela rappelons nous le contenu de la variable liste :
liste[0, 1, 2, 3, 'ap', 'ex1', 'ex2']La méthode insert permet, comme le nom le suggère, d’insérer un élément à une certaine position ; comme toujours les indices commencent à zéro et donc :
# insérer à l'index 2
liste.insert(2, '1 bis')
print('liste', liste)liste [0, 1, '1 bis', 2, 3, 'ap', 'ex1', 'ex2']
On peut remarquer qu’un résultat analogue peut être obtenu avec une affectation de slice ; par exemple pour insérer au rang 5 (i.e. avant ap), on pourrait aussi bien faire :
liste[5:5] = ['3 bis']
print('liste', liste)liste [0, 1, '1 bis', 2, 3, '3 bis', 'ap', 'ex1', 'ex2']
remove¶
La méthode remove détruit la première occurrence d’un objet dans la liste :
liste.remove(3)
print('liste', liste)liste [0, 1, '1 bis', 2, '3 bis', 'ap', 'ex1', 'ex2']
pop¶
La méthode pop prend en argument un indice ; elle permet d’extraire l’élément à cet indice. En un seul appel on obtient la valeur de l’élément et on l’enlève de la liste :
popped = liste.pop(0)
print('popped', popped, 'liste', liste)popped 0 liste [1, '1 bis', 2, '3 bis', 'ap', 'ex1', 'ex2']
Si l’indice n’est pas précisé, c’est le dernier élément de la liste qui est visé :
popped = liste.pop()
print('popped', popped, 'liste', liste)popped ex2 liste [1, '1 bis', 2, '3 bis', 'ap', 'ex1']
reverse¶
Enfin reverse renverse la liste, le premier élément devient le dernier :
liste.reverse()
print('liste', liste)liste ['ex1', 'ap', '3 bis', 2, '1 bis', 1]
On peut remarquer ici que le résultat se rapproche de ce qu’on peut obtenir avec une opération de slicing comme ceci :
liste2 = liste[::-1]
print('liste2', liste2)liste2 [1, '1 bis', 2, '3 bis', 'ap', 'ex1']
À la différence toutefois qu’avec le slicing c’est une copie de la liste initiale qui est retournée, la liste de départ quant à elle n’est pas modifiée.
Pour en savoir plus¶
https://
Note spécifique aux notebooks¶
help avec ?¶
Je vous signale en passant que dans un notebook vous pouvez obtenir de l’aide avec un point d’interrogation ? inséré avant ou après un symbole. Par exemple pour obtenir des précisions sur la méthode list.pop, on peut faire soit :
# fonctionne dans tous les environnements Python
help(list.pop)Help on method_descriptor:
pop(self, index=-1, /) unbound builtins.list method
Remove and return item at index (default last).
Raises IndexError if list is empty or index is out of range.
# spécifique aux notebooks
# l'affichage obtenu est légèrement différent
# tapez la touche 'Esc' - ou cliquez la petite croix
# pour faire disparaitre le dialogue qui apparaît en bas
list.pop?Complétion avec Tab¶
Dans un notebook vous avez aussi la complétion ; si vous tapez, dans une cellule de code, le début d’un mot connu dans l’environnement, vous voyez apparaître un dialogue avec les noms connus qui commencent par ce mot ici li; utilisez les flèches pour choisir, et ‘Return’ pour sélectionner.
# placez votre curseur à la fin de la ligne après 'li'
# et appuyez sur la touche 'Tab'
li---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[25], line 3
1 # placez votre curseur à la fin de la ligne après 'li'
2 # et appuyez sur la touche 'Tab'
----> 3 li
NameError: name 'li' is not defined