8.3. collections
— High-performance container datatypes¶
Nouveau dans la version 2.4.
Source code: Lib/collections.py and Lib/_abcoll.py
Ce module implémente des types de données de conteneurs spécialisés qui apportent des alternatives aux conteneurs natifs de Python plus généraux dict
, list
, set
et tuple
.
fonction permettant de créer des sous-classes de |
Nouveau dans la version 2.6. |
|
conteneur se comportant comme une liste avec des ajouts et retraits rapides à chaque extrémité |
Nouveau dans la version 2.4. |
|
sous-classe de |
Nouveau dans la version 2.7. |
|
sous-classe de |
Nouveau dans la version 2.7. |
|
sous-classe de |
Nouveau dans la version 2.5. |
In addition to the concrete container classes, the collections module provides abstract base classes that can be used to test whether a class provides a particular interface, for example, whether it is hashable or a mapping.
8.3.1. Objets Counter
¶
Ce module fournit un outil pour effectuer rapidement et facilement des dénombrements. Par exemple :
>>> # Tally occurrences of words in a list
>>> cnt = Counter()
>>> for word in ['red', 'blue', 'red', 'green', 'blue', 'blue']:
... cnt[word] += 1
>>> cnt
Counter({'blue': 3, 'red': 2, 'green': 1})
>>> # Find the ten most common words in Hamlet
>>> import re
>>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
('you', 554), ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]
-
class
collections.
Counter
([iterable-or-mapping])¶ La classe
Counter
est une sous-classe dedict
qui permet le dénombrement d’objets hachables. Il s’agit d’une collection non ordonnée dans laquelle les éléments sont stockés comme des clés de dictionnaire et leurs nombres d’occurrences respectifs comme leurs valeurs. Ceux-ci peuvent être des entiers relatifs (positifs, négatifs ou nuls). La classeCounter
est similaire aux sacs ou aux multiensembles dans d’autres langages.Les éléments sont comptés à partir d’un itérable ou initialisés à partir d’un autre dictionnaire (ou compteur) :
>>> c = Counter() # a new, empty counter >>> c = Counter('gallahad') # a new counter from an iterable >>> c = Counter({'red': 4, 'blue': 2}) # a new counter from a mapping >>> c = Counter(cats=4, dogs=8) # a new counter from keyword args
Les objets Counter ont une interface de dictionnaire, à l’exception près qu’ils renvoient zéro au lieu de lever une exception
KeyError
pour des éléments manquants :>>> c = Counter(['eggs', 'ham']) >>> c['bacon'] # count of a missing element is zero 0
Mettre un comptage à zéro pour un élément ne le retire pas de l’objet Counter. Il faut utiliser
del
pour le supprimer complètement :>>> c['sausage'] = 0 # counter entry with a zero count >>> del c['sausage'] # del actually removes the entry
Nouveau dans la version 2.7.
En plus des méthodes disponibles pour tous les dictionnaires, les objets compteurs gèrent trois méthodes supplémentaires :
-
elements
()¶ Renvoie un itérateur sur chaque élément en le répétant autant de fois que la valeur du compteur associé. Les éléments sont renvoyés dans un ordre arbitraire. Si le comptage d’un élément est strictement inférieur à 1, alors
elements()
l’ignore.>>> c = Counter(a=4, b=2, c=0, d=-2) >>> list(c.elements()) ['a', 'a', 'a', 'a', 'b', 'b']
-
most_common
([n])¶ Return a list of the n most common elements and their counts from the most common to the least. If n is omitted or
None
,most_common()
returns all elements in the counter. Elements with equal counts are ordered arbitrarily:>>> Counter('abracadabra').most_common(3) [('a', 5), ('r', 2), ('b', 2)]
-
subtract
([iterable-or-mapping])¶ Les éléments sont soustraits à partir d’un itérable ou d’un autre dictionnaire (ou compteur). Cette méthode se comporte comme
dict.update()
mais soustrait les nombres d’occurrences au lieu de les remplacer. Les entrées et sorties peuvent être négatives ou nulles.>>> c = Counter(a=4, b=2, c=0, d=-2) >>> d = Counter(a=1, b=2, c=3, d=4) >>> c.subtract(d) >>> c Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
Les méthodes usuelles des dictionnaires sont disponibles pour les objets
Counter
à l’exception de deux méthodes qui fonctionnent différemment pour les compteurs.-
update
([iterable-or-mapping])¶ Les éléments sont comptés à partir d’un itérable ou ajoutés d’un autre dictionnaire (ou compteur). Cette méthode se comporte comme
dict.update()
mais additionne les nombres d’occurrences au lieu de les remplacer. De plus, l’itérable doit être une séquence d’éléments et non une séquence de paires(clé, valeur)
.
-
Opérations usuelles sur les objets Counter
:
sum(c.values()) # total of all counts
c.clear() # reset all counts
list(c) # list unique elements
set(c) # convert to a set
dict(c) # convert to a regular dictionary
c.items() # convert to a list of (elem, cnt) pairs
Counter(dict(list_of_pairs)) # convert from a list of (elem, cnt) pairs
c.most_common()[:-n-1:-1] # n least common elements
c += Counter() # remove zero and negative counts
Quelques opérations mathématiques sont fournies pour combiner des objets Counter
afin de créer des multiensembles (des compteurs dont les dénombrements des éléments sont strictement supérieurs à zéro). Les additions et soustractions combinent les compteurs en ajoutant ou retranchant les nombres d’occurrences des éléments correspondants. Les intersections et unions renvoient les minimums et maximums des comptages correspondants. Chaque opération peut accepter des entrées avec des comptages relatifs, mais la sortie exclut les résultats avec des comptages négatifs ou nuls.
>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d # add two counters together: c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>> c - d # subtract (keeping only positive counts)
Counter({'a': 2})
>>> c & d # intersection: min(c[x], d[x])
Counter({'a': 1, 'b': 1})
>>> c | d # union: max(c[x], d[x])
Counter({'a': 3, 'b': 2})
Note
Les compteurs ont été conçus essentiellement pour fonctionner avec des entiers naturels pour représenter les dénombrements en cours ; cependant, les cas d’utilisation nécessitant d’autres types ou des valeurs négatives n’ont pas été écartés. Pour vous aider dans ces cas particuliers, cette section documente la plage minimale et les restrictions de type.
La classe
Counter
est elle-même une sous-classe de dictionnaire sans restriction particulière sur ces clés ou valeurs. Les valeurs ont vocation à être des nombres représentants des comptages, mais il est possible de stocker n’importe quel type de valeur.The
most_common()
method requires only that the values be orderable.For in-place operations such as
c[key] += 1
, the value type need only support addition and subtraction. So fractions, floats, and decimals would work and negative values are supported. The same is also true forupdate()
andsubtract()
which allow negative and zero values for both inputs and outputs.Les méthodes de multiensembles sont uniquement conçues pour les cas d’utilisation avec des valeurs positives. Les entrées peuvent contenir des valeurs négatives ou nulles, mais seules les sorties avec des valeurs positives sont créées. Il n’y a pas de restriction de type, mais les types des valeurs doivent gérer l’addition, la soustraction et la comparaison.
The
elements()
method requires integer counts. It ignores zero and negative counts.
Voir aussi
Counter class adapted for Python 2.5 and an early Bag recipe for Python 2.4.
Bag class in Smalltalk.
L’article Wikipédia sur les multiensembles sur Wikipédia (ou l’article en anglais).
Des guides et exemples à propos des multiensembles en C++.
Pour les opérations mathématiques sur les multiensembles et leurs applications, voir Knuth, Donald. The Art of Computer Programming Volume II, Section 4.6.3, Exercise 19.
To enumerate all distinct multisets of a given size over a given set of elements, see
itertools.combinations_with_replacement()
.map(Counter, combinations_with_replacement(“ABC”, 2)) –> AA AB AC BB BC CC
8.3.2. Objets deque
¶
-
class
collections.
deque
([iterable[, maxlen]])¶ Renvoie un nouvel objet deque initialisé de gauche à droite (en utilisant
append()
) avec les données d”iterable. Si iterable n’est pas spécifié, alors la nouvelle deque est vide.Les deques sont une généralisation des piles et des files (deque se prononce « dèque » et est l’abréviation de l’anglais double-ended queue) : il est possible d’ajouter et retirer des éléments par les deux bouts des deques. Celles-ci gèrent des ajouts et des retraits utilisables par de multiples fils d’exécution (thread-safe) et efficients du point de vue de la mémoire des deux côtés de la deque, avec approximativement la même performance en O(1) dans les deux sens.
Bien que les les objets
list
gèrent des opérations similaires, ils sont optimisés pour des opérations qui ne changent pas la taille de la liste. Les opérationspop(0)
etinsert(0, v)
qui changent la taille et la position de la représentation des données sous-jacentes entraînent des coûts de déplacement de mémoire en O(n).Nouveau dans la version 2.4.
Si maxlen n’est pas spécifié ou vaut None, les deques peuvent atteindre une taille arbitraire. Sinon, la deque est limitée par cette taille maximale. Une fois que celle-ci est atteinte, un ajout d’un ou plusieurs éléments engendre la suppression du nombre correspondant d’éléments à l’autre extrémité de la deque. Les deques à longueur limitée apportent des fonctionnalités similaire au filtre
tail
d’Unix. Elles sont aussi utiles pour le suivi de transactions et autres lots de données où seule l’activité récente est intéressante.Modifié dans la version 2.6: Added maxlen parameter.
Les objets deques gèrent les méthodes suivantes :
-
append
(x)¶ Ajoute x à l’extrémité droite de la deque.
-
appendleft
(x)¶ Ajoute x à l’extrémité gauche de la deque.
-
clear
()¶ Supprime tous les éléments de la deque et la laisse avec une longueur de 0.
-
count
(x)¶ Compte le nombre d’éléments de la deque égaux à x.
Nouveau dans la version 2.7.
-
extend
(iterable)¶ Étend la deque en ajoutant les éléments de l’itérable en argument à son extrémité droite.
-
extendleft
(iterable)¶ Étend la deque en ajoutant les éléments d”iterable à son extrémité gauche. Dans ce cas, notez que la série d’ajouts inverse l’ordre des éléments de l’argument itérable.
-
pop
()¶ Retire et renvoie un élément de l’extrémité droite de la deque. S’il n’y a aucun élément, lève une exception
IndexError
.
-
popleft
()¶ Retire et renvoie un élément de l’extrémité gauche de la deque. S’il n’y a aucun élément, lève une exception
IndexError
.
-
remove
(value)¶ Remove the first occurrence of value. If not found, raises a
ValueError
.Nouveau dans la version 2.5.
-
reverse
()¶ Inverse le sens des éléments de la deque sans créer de copie et renvoie
None
.Nouveau dans la version 2.7.
-
rotate
(n=1)¶ Rotate the deque n steps to the right. If n is negative, rotate to the left.
When the deque is not empty, rotating one step to the right is equivalent to
d.appendleft(d.pop())
, and rotating one step to the left is equivalent tod.append(d.popleft())
.
Les objets deques fournissent également un attribut en lecture seule :
-
maxlen
¶ La taille maximale d’une deque, ou
None
si illimitée.Nouveau dans la version 2.7.
-
En plus des méthodes précédentes, les deques gèrent l’itération, la sérialisation, len(d)
, reversed(d)
, copy.copy(d)
, copy.deepcopy(d)
, le test d’appartenance avec l’opérateur in
, et les références en indice comme d[-1]
. L’accès par indice est en O(1) aux extrémités mais en O(n) au milieu. Pour des accès aléatoires rapides, il est préférable d’utiliser des listes.
Exemple :
>>> from collections import deque
>>> d = deque('ghi') # make a new deque with three items
>>> for elem in d: # iterate over the deque's elements
... print elem.upper()
G
H
I
>>> d.append('j') # add a new entry to the right side
>>> d.appendleft('f') # add a new entry to the left side
>>> d # show the representation of the deque
deque(['f', 'g', 'h', 'i', 'j'])
>>> d.pop() # return and remove the rightmost item
'j'
>>> d.popleft() # return and remove the leftmost item
'f'
>>> list(d) # list the contents of the deque
['g', 'h', 'i']
>>> d[0] # peek at leftmost item
'g'
>>> d[-1] # peek at rightmost item
'i'
>>> list(reversed(d)) # list the contents of a deque in reverse
['i', 'h', 'g']
>>> 'h' in d # search the deque
True
>>> d.extend('jkl') # add multiple elements at once
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
>>> d.rotate(1) # right rotation
>>> d
deque(['l', 'g', 'h', 'i', 'j', 'k'])
>>> d.rotate(-1) # left rotation
>>> d
deque(['g', 'h', 'i', 'j', 'k', 'l'])
>>> deque(reversed(d)) # make a new deque in reverse order
deque(['l', 'k', 'j', 'i', 'h', 'g'])
>>> d.clear() # empty the deque
>>> d.pop() # cannot pop from an empty deque
Traceback (most recent call last):
File "<pyshell#6>", line 1, in -toplevel-
d.pop()
IndexError: pop from an empty deque
>>> d.extendleft('abc') # extendleft() reverses the input order
>>> d
deque(['c', 'b', 'a'])
8.3.2.1. Cas pratiques utilisant deque
¶
Cette partie montre diverses approches afin de travailler avec les deques.
Les deques à taille limitée apportent une fonctionnalité similaire au filtre tail
d’Unix :
def tail(filename, n=10):
'Return the last n lines of a file'
return deque(open(filename), n)
Une autre approche d’utilisation des deques est de maintenir une séquence d’éléments récemment ajoutés en les ajoutant à droite et en retirant les anciens par la gauche :
def moving_average(iterable, n=3):
# moving_average([40, 30, 50, 46, 39, 44]) --> 40.0 42.0 45.0 43.0
# http://en.wikipedia.org/wiki/Moving_average
it = iter(iterable)
d = deque(itertools.islice(it, n-1))
d.appendleft(0)
s = sum(d)
for elem in it:
s += elem - d.popleft()
d.append(elem)
yield s / float(n)
The rotate()
method provides a way to implement deque
slicing and
deletion. For example, a pure Python implementation of del d[n]
relies on
the rotate()
method to position elements to be popped:
def delete_nth(d, n):
d.rotate(-n)
d.popleft()
d.rotate(n)
To implement deque
slicing, use a similar approach applying
rotate()
to bring a target element to the left side of the deque. Remove
old entries with popleft()
, add new entries with extend()
, and then
reverse the rotation.
With minor variations on that approach, it is easy to implement Forth style
stack manipulations such as dup
, drop
, swap
, over
, pick
,
rot
, and roll
.
8.3.3. Objets defaultdict
¶
-
class
collections.
defaultdict
([default_factory[, ...]])¶ Renvoie un nouvel objet qui se comporte comme un dictionnaire.
defaultdic
est une sous-classe de la la classe nativedict
. Elle surcharge une méthode et ajoute une variable d’instance modifiable. Les autres fonctionnalités sont les mêmes que celles des objetsdict
et ne sont pas documentées ici.Le premier argument fournit la valeur initiale de l’attribut
default_factory
qui doit être un objet appelable sans paramètre ouNone
, sa valeur par défaut. Tous les autres arguments sont traités comme si on les passait au constructeur dedict
, y compris les arguments nommés.Nouveau dans la version 2.5.
En plus des opérations usuelles de
dict
, les objetsdefaultdict
gèrent les méthodes supplémentaires suivantes :-
__missing__
(key)¶ Si l’attribut
default_factory
estNone
, lève une exceptionKeyError
avec key comme argument.Si
default_fatory`
ne vaut pasNone
, cet attribut est appelé sans argument pour fournir une valeur par défaut pour la key demandée. Cette valeur est insérée dans le dictionnaire avec pour clé key et est renvoyée.Si appeler
default_factory
lève une exception, celle-ci est transmise inchangée.Cette méthode est appelée par la méthode
__getitem__()
de la classedict
lorsque la clé demandée n’est pas trouvée. Ce qu’elle renvoie ou lève est alors renvoyé ou levé par__getitem__()
.Remarquez que
__missing__()
n’est pas appelée pour les opérations autres que__getitem__()
. Cela signifie queget()
renvoieNone
comme les dictionnaires natifs dans les cas triviaux et n’utilise pasdefault_factory
.
Les objets
defaultdict
gèrent la variable d’instance :-
default_factory
¶ Cet attribut est utilisé par la méthode
__missing__()
; il est initialisé par le premier argument passé au constructeur, s’il est spécifié, sinon parNone
.
-
8.3.3.1. Exemples utilisant defaultdict
¶
Using list
as the default_factory
, it is easy to group a
sequence of key-value pairs into a dictionary of lists:
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
... d[k].append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
When each key is encountered for the first time, it is not already in the
mapping; so an entry is automatically created using the default_factory
function which returns an empty list
. The list.append()
operation then attaches the value to the new list. When keys are encountered
again, the look-up proceeds normally (returning the list for that key) and the
list.append()
operation adds another value to the list. This technique is
simpler and faster than an equivalent technique using dict.setdefault()
:
>>> d = {}
>>> for k, v in s:
... d.setdefault(k, []).append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
Setting the default_factory
to int
makes the
defaultdict
useful for counting (like a bag or multiset in other
languages):
>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
... d[k] += 1
...
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]
When a letter is first encountered, it is missing from the mapping, so the
default_factory
function calls int()
to supply a default count of
zero. The increment operation then builds up the count for each letter.
The function int()
which always returns zero is just a special case of
constant functions. A faster and more flexible way to create constant functions
is to use itertools.repeat()
which can supply any constant value (not just
zero):
>>> def constant_factory(value):
... return itertools.repeat(value).next
>>> d = defaultdict(constant_factory('<missing>'))
>>> d.update(name='John', action='ran')
>>> '%(name)s %(action)s to %(object)s' % d
'John ran to <missing>'
Setting the default_factory
to set
makes the
defaultdict
useful for building a dictionary of sets:
>>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
>>> d = defaultdict(set)
>>> for k, v in s:
... d[k].add(v)
...
>>> d.items()
[('blue', set([2, 4])), ('red', set([1, 3]))]
8.3.4. namedtuple()
: fonction de construction pour n-uplets (tuples) avec des champs nommés¶
Les tuples nommés assignent une signification à chacun de leur élément, ce qui rend le code plus lisible et explicite. Ils peuvent être utilisés partout où les tuples natifs sont utilisés, et ils ajoutent la possibilité d’accéder à leurs champs grâce à leur nom au lieu de leur index de position.
-
collections.
namedtuple
(typename, field_names[, verbose=False][, rename=False])¶ Renvoie une nouvelle sous-classe de
tuple
appelée typename. Elle est utilisée pour créer des objets se comportant comme les tuples qui ont des champs accessibles par recherche d’attribut en plus d’être indexables et itérables. Les instances de cette sous-classe possèdent aussi une docstring explicite (avec type_name et les field_names) et une méthode__repr__()
pratique qui liste le contenu du tuple au formatnom=valeur
.field_names peut être une séquence de chaînes de caractères telle que
['x', 'y']
ou bien une unique chaîne de caractères où les noms de champs sont séparés par un espace et/ou une virgule, par exemple'x y'
ou'x, y'
.Any valid Python identifier may be used for a fieldname except for names starting with an underscore. Valid identifiers consist of letters, digits, and underscores but do not start with a digit or underscore and cannot be a
keyword
such as class, for, return, global, pass, print, or raise.Si rename vaut
True
, alors les noms de champs invalides sont automatiquement renommés en noms positionnels. Par exemple,['abc', 'def', 'ghi', 'abc']
est converti en['abc, '_1', 'ghi', '_3']
afin d’éliminer le mot-clédef
et le doublon deabc
.If verbose is true, the class definition is printed just before being built.
Les instances de tuples nommés n’ont pas de dictionnaires propres, elles sont donc légères et ne requièrent pas plus de mémoire que les tuples natifs.
Nouveau dans la version 2.6.
Modifié dans la version 2.7: added support for rename.
Exemple :
>>> Point = namedtuple('Point', ['x', 'y'], verbose=True)
class Point(tuple):
'Point(x, y)'
__slots__ = ()
_fields = ('x', 'y')
def __new__(_cls, x, y):
'Create new instance of Point(x, y)'
return _tuple.__new__(_cls, (x, y))
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new Point object from a sequence or iterable'
result = new(cls, iterable)
if len(result) != 2:
raise TypeError('Expected 2 arguments, got %d' % len(result))
return result
def __repr__(self):
'Return a nicely formatted representation string'
return 'Point(x=%r, y=%r)' % self
def _asdict(self):
'Return a new OrderedDict which maps field names to their values'
return OrderedDict(zip(self._fields, self))
def _replace(_self, **kwds):
'Return a new Point object replacing specified fields with new values'
result = _self._make(map(kwds.pop, ('x', 'y'), _self))
if kwds:
raise ValueError('Got unexpected field names: %r' % kwds.keys())
return result
def __getnewargs__(self):
'Return self as a plain tuple. Used by copy and pickle.'
return tuple(self)
__dict__ = _property(_asdict)
def __getstate__(self):
'Exclude the OrderedDict from pickling'
pass
x = _property(_itemgetter(0), doc='Alias for field number 0')
y = _property(_itemgetter(1), doc='Alias for field number 1')
>>> p = Point(11, y=22) # instantiate with positional or keyword arguments
>>> p[0] + p[1] # indexable like the plain tuple (11, 22)
33
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessible by name
33
>>> p # readable __repr__ with a name=value style
Point(x=11, y=22)
Les tuples nommés sont particulièrement utiles pour associer des noms de champs à des tuples renvoyés par les modules csv
ou sqlite3
:
EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
import csv
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
print emp.name, emp.title
import sqlite3
conn = sqlite3.connect('/companydata')
cursor = conn.cursor()
cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
for emp in map(EmployeeRecord._make, cursor.fetchall()):
print emp.name, emp.title
In addition to the methods inherited from tuples, named tuples support three additional methods and one attribute. To prevent conflicts with field names, the method and attribute names start with an underscore.
-
classmethod
somenamedtuple.
_make
(iterable)¶ Méthode de classe qui construit une nouvelle instance à partir d’une séquence ou d’un itérable existant.
>>> t = [11, 22] >>> Point._make(t) Point(x=11, y=22)
-
somenamedtuple.
_asdict
()¶ Return a new
OrderedDict
which maps field names to their corresponding values:>>> p = Point(x=11, y=22) >>> p._asdict() OrderedDict([('x', 11), ('y', 22)])
Modifié dans la version 2.7: Renvoie un
OrderedDict
au lieu d’undict
natif.
-
somenamedtuple.
_replace
(**kwargs)¶ Renvoie une nouvelle instance du tuple nommé en remplaçant les champs spécifiés par leurs nouvelles valeurs :
>>> p = Point(x=11, y=22) >>> p._replace(x=33) Point(x=33, y=22) >>> for partnum, record in inventory.items(): ... inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())
-
somenamedtuple.
_fields
¶ Tuple de chaînes de caractères listant les noms de champs. Pratique pour l’introspection et pour créer de nouveaux types de tuples nommés à partir d’existants.
>>> p._fields # view the field names ('x', 'y') >>> Color = namedtuple('Color', 'red green blue') >>> Pixel = namedtuple('Pixel', Point._fields + Color._fields) >>> Pixel(11, 22, 128, 255, 0) Pixel(x=11, y=22, red=128, green=255, blue=0)
Pour récupérer un champ dont le nom est une chaîne de caractères, utilisez la fonction getattr()
:
>>> getattr(p, 'x')
11
Pour convertir un dictionnaire en tuple nommé, utilisez l’opérateur double-étoile (comme expliqué dans Séparation des listes d’arguments) :
>>> d = {'x': 11, 'y': 22}
>>> Point(**d)
Point(x=11, y=22)
Il est aisé d’ajouter ou de modifier les fonctionnalités des tuples nommés grâce à l’héritage puisqu’il s’agit de simples classes. Voici comment ajouter un champ calculé avec une longueur fixe d’affichage :
>>> class Point(namedtuple('Point', 'x y')):
... __slots__ = ()
... @property
... def hypot(self):
... return (self.x ** 2 + self.y ** 2) ** 0.5
... def __str__(self):
... return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)
...
>>> for p in Point(3, 4), Point(14, 5/7.):
... print p
Point: x= 3.000 y= 4.000 hypot= 5.000
Point: x=14.000 y= 0.714 hypot=14.018
La sous-classe ci-dessus définit __slots__
comme un tuple vide. Cela permet de garder une emprunte mémoire faible en empêchant la création de dictionnaire d’instance.
Subclassing is not useful for adding new, stored fields. Instead, simply
create a new named tuple type from the _fields
attribute:
>>> Point3D = namedtuple('Point3D', Point._fields + ('z',))
Default values can be implemented by using _replace()
to
customize a prototype instance:
>>> Account = namedtuple('Account', 'owner balance transaction_count')
>>> default_account = Account('<owner name>', 0.0, 0)
>>> johns_account = default_account._replace(owner='John')
Enumerated constants can be implemented with named tuples, but it is simpler and more efficient to use a simple class declaration:
>>> Status = namedtuple('Status', 'open pending closed')._make(range(3))
>>> Status.open, Status.pending, Status.closed
(0, 1, 2)
>>> class Status:
... open, pending, closed = range(3)
Voir aussi
Named tuple recipe adapted for Python 2.4.
8.3.5. Objets OrderedDict
¶
En plus de se comporter comme des dictionnaires natifs, les dictionnaires ordonnés mémorisent l’ordre dans lequel les éléments ont été insérés. Quand on itère sur un dictionnaire ordonné, les éléments sont renvoyés dans l’ordre d’insertion des clés.
-
class
collections.
OrderedDict
([items])¶ Renvoie une instance d’une sous-classe de
dict
qui gère les méthodes usuelles dedict
. Un objet OrderedDict est un dictionnaire qui mémorise l’ordre d’insertion des clés. Si une nouvelle entrée en écrase une autre, sa position reste inchangé. Si une entrée est supprimée puis réinsérée, elle est placée en dernière position.Nouveau dans la version 2.7.
-
OrderedDict.
popitem
(last=True)¶ The
popitem()
method for ordered dictionaries returns and removes a (key, value) pair. The pairs are returned in LIFO order if last is true or FIFO order if false.
En plus des méthodes usuelles des dictionnaires, les dictionnaires ordonnés gèrent l’itération en sens inverse grâce à reversed()
.
Equality tests between OrderedDict
objects are order-sensitive
and are implemented as list(od1.items())==list(od2.items())
.
Equality tests between OrderedDict
objects and other
Mapping
objects are order-insensitive like regular
dictionaries. This allows OrderedDict
objects to be substituted
anywhere a regular dictionary is used.
The OrderedDict
constructor and update()
method both accept
keyword arguments, but their order is lost because Python’s function call
semantics pass-in keyword arguments using a regular unordered dictionary.
Voir aussi
Equivalent OrderedDict recipe that runs on Python 2.4 or later.
8.3.5.1. Exemples et cas pratiques utilisant OrderDict
¶
Puisqu’un dictionnaire ordonné mémorise l’ordre d’insertion de ses éléments, il peut être utilisé conjointement avec un classement pour créer un dictionnaire trié :
>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple': 4, 'pear': 1, 'orange': 2}
>>> # dictionary sorted by key
>>> OrderedDict(sorted(d.items(), key=lambda t: t[0]))
OrderedDict([('apple', 4), ('banana', 3), ('orange', 2), ('pear', 1)])
>>> # dictionary sorted by value
>>> OrderedDict(sorted(d.items(), key=lambda t: t[1]))
OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
>>> # dictionary sorted by length of the key string
>>> OrderedDict(sorted(d.items(), key=lambda t: len(t[0])))
OrderedDict([('pear', 1), ('apple', 4), ('orange', 2), ('banana', 3)])
Les nouveaux dictionnaires triés gardent leur classement quand des entrées sont supprimées, mais si de nouvelles clés sont ajoutées, celles-ci sont ajoutée à la fin et le classement est perdu.
Il est également facile de créer une variante de dictionnaire ordonné qui retient l’ordre dans lequel les clés ont été insérées en dernier. Si une nouvelle entrée écrase une existante, la position d’insertion d’origine est modifiée et déplacée à la fin :
class LastUpdatedOrderedDict(OrderedDict):
'Store items in the order the keys were last added'
def __setitem__(self, key, value):
if key in self:
del self[key]
OrderedDict.__setitem__(self, key, value)
Un dictionnaire ordonné peut être combiné avec la classe Counter
afin de mémoriser l’ordre dans lequel les éléments ont été ajoutés pour la première fois :
class OrderedCounter(Counter, OrderedDict):
'Counter that remembers the order elements are first encountered'
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
8.3.6. Classes de base abstraites de collections¶
Le module collections apporte les ABC suivantes :
ABC |
Hérite de |
Méthodes abstraites |
Méthodes mixin |
---|---|---|---|
|
|||
|
|||
|
|||
|
|
||
|
|||
|
|||
|
|
||
|
Méthodes héritées de |
||
|
|
||
|
Méthodes héritées de |
||
|
|
||
|
Méthodes héritées de |
||
|
|||
|
|||
|
|||
|
-
class
collections.
Container
¶ -
class
collections.
Hashable
¶ -
class
collections.
Sized
¶ -
class
collections.
Callable
¶ ABC pour les classes qui définissent respectivement les méthodes
__contains__()
,__hash__()
,__len__()
et__call__()
.
-
class
collections.
Iterable
¶ ABC for classes that provide the
__iter__()
method. See also the definition of iterable.
-
class
collections.
Iterator
¶ ABC for classes that provide the
__iter__()
andnext()
methods. See also the definition of iterator.
-
class
collections.
Sequence
¶ -
class
collections.
MutableSequence
¶ ABC pour les séquences immuables et muables.
-
class
collections.
Mapping
¶ -
class
collections.
MutableMapping
¶ ABC pour les tables de correspondances immuables et muables.
-
class
collections.
MappingView
¶ -
class
collections.
ItemsView
¶ -
class
collections.
KeysView
¶ -
class
collections.
ValuesView
¶ ABC pour les vues de mappings (tableaux de correspondances), d’éléments, de clés et de valeurs.
Ces ABC permettent de demander à des classes ou à des instances si elles fournissent des fonctionnalités particulières, par exemple
size = None
if isinstance(myvar, collections.Sized):
size = len(myvar)
Several of the ABCs are also useful as mixins that make it easier to develop
classes supporting container APIs. For example, to write a class supporting
the full Set
API, it only necessary to supply the three underlying
abstract methods: __contains__()
, __iter__()
, and __len__()
.
The ABC supplies the remaining methods such as __and__()
and
isdisjoint()
class ListBasedSet(collections.Set):
''' Alternate set implementation favoring space over speed
and not requiring the set elements to be hashable. '''
def __init__(self, iterable):
self.elements = lst = []
for value in iterable:
if value not in lst:
lst.append(value)
def __iter__(self):
return iter(self.elements)
def __contains__(self, value):
return value in self.elements
def __len__(self):
return len(self.elements)
s1 = ListBasedSet('abcdef')
s2 = ListBasedSet('defghi')
overlap = s1 & s2 # The __and__() method is supported automatically
Notes à propos de l’utilisation de Set
et MutableSet
comme mixin :
Comme une partie des opérations sur les ensembles créent de nouveaux ensembles, les méthodes mixins par défaut ont besoin d’un moyen de créer de nouvelles instances à partir d’un itérable. Le constructeur de classe est supposé avoir une signature de la forme
ClassName(iterable)
. Cette supposition est faite par une méthode de classe interne appelée_from_iterable()
qui appellecls(iterable)
pour construire un nouvel ensemble. Si leSet
mixin est utilisé dans une classe avec un constructeur de signature différente, vous devrez surcharger_from_iterable()
avec une méthode de classe qui peut construire de nouvelles instances à partir d’un argument itérable.Pour surcharger les comparaisons (a priori pour la rapidité, puisque la sémantique est fixe), il faut redéfinir
__le__()
et__ge__()
, puis les autres opérations seront automatiquement adaptées.La classe mixin
Set
apporte une méthode_hash()
pour calculer une valeur de hachage pour l’ensemble ; cependant__hash__()
n’est pas défini car tous les ensembles ne sont pas hachables ou immuables. Pour rendre un ensemble hachable en utilisant les mixins, héritez deSet()
et deHashable()
, puis définissez__hash__ = Set._hash
.
Voir aussi
OrderedSet recipe pour un exemple construit sur
MutableSet
.Pour plus d’informations à propos des ABC, voir le module
abc
et la PEP 3119.