Constructions classiques¶
Le module collections
propose d’autres types d’objets
qui en contiennent d’autres. Ils sont très proches des types
standards liste ou dictionnaires mais sont optimisés pour un usage
en particulier. Cela les rend plus efficaces pour celui-ci et
souvent plus lent pour les autres. Ce chapitre en recense les
plus utilisés.
OrderedDict¶
collections.OrderedDict
est un dictionnaire qui conservent
l’ordre dans lequel les éléments y ont été insérés.
Cette distinction était effective jusqu’à Python 3.7 mais
depuis cette version, le type standard dict conserve
également l’ordre d’insertion comme le montre l’exemple suivant.
<<<
import random
from collections import OrderedDict
rnd = [random.randint(0, 10) for i in range(10)]
dico = {}
for i, h in enumerate(rnd):
dico[h] = i
print(list(dico))
print(list(dico.items()))
dico = OrderedDict()
for i, h in enumerate(rnd):
dico[h] = i
print(list(dico))
print(list(dico.items()))
>>>
[8, 2, 9, 1, 4, 0]
[(8, 0), (2, 5), (9, 3), (1, 7), (4, 8), (0, 9)]
[8, 2, 9, 1, 4, 0]
[(8, 0), (2, 5), (9, 3), (1, 7), (4, 8), (0, 9)]
Néanmoins, cette distinctions est importante à connaître pour des langages plus bas niveau comme le C++.
namedtuple¶
collections.namedtuple()
est un tuple, donc immuable,
mais chaque élément est associé un nom.
La fonction collections.namedtuple()
retourne une classe
et non une instance de classe.
<<<
from collections import namedtuple
ClassePersonne = namedtuple("Personne", ["nom", "prenom"])
p = ClassePersonne("George", "Boole")
print(p)
print(p.nom, p.prenom)
print(p[0], p[1])
try:
p.nom = "A"
except AttributeError as e:
print(e)
>>>
Personne(nom='George', prenom='Boole')
George Boole
George Boole
can't set attribute
On accède à chaque élément avec un nom ou un indice. Et on peut récupérer la liste des attributs de la classe.
<<<
from collections import namedtuple
ClassePersonne = namedtuple("Personne", ["nom", "prenom"])
print(ClassePersonne._fields)
>>>
('nom', 'prenom')
Ce type de construction ne change pas un programme mais elle le rend plus lisible.
Counter¶
collections.Counter
est un dictionnaire spécifique dans les valeurs
sont entières. Il est très pratique pour compter les éléments.
L’exemple comptage s’écrit en une ligne.
<<<
from collections import Counter
ensemble = ["A", "B", "A", "AA", "C"]
c = Counter(ensemble)
print(c)
>>>
Counter({'A': 2, 'B': 1, 'AA': 1, 'C': 1})
deque¶
collections.deque
est une liste qui supporte l’insertion
d’éléments en bout de liste et au début également
(liste chaînée).
<<<
from collections import deque
ens = deque(["A", "B"])
ens.append("C")
ens.appendleft("D")
print(ens)
>>>
deque(['D', 'A', 'B', 'C'])
Il faut retenir que ce qu’on gagne en agilité se perd souvent en performance ou en espace mémoire. La différence n’est pas flagrante. Encore une fois, le langage Python est lent et rend ces différences parfois négligeables. Ces différences sont souvent significatives pour des langages plus bas niveau.
<<<
import sys
from collections import deque
import timeit
def append_time_list():
ens = list()
for i in range(0, 10000):
ens.append(i)
return ens
def append_time_deque():
ens = deque()
for i in range(0, 10000):
ens.append(i)
return ens
print("list", timeit.timeit(append_time_list, number=100))
print("deque", timeit.timeit(append_time_deque, number=100))
>>>
list 0.0948047800002314
deque 0.07056761799958622