Figurez-vous qu’on a un chat IRC. Si, si ! freenode#sametmax administré par foxmask, qui est aussi le seul participant du chan.
Bon j’exagère, d’ailleurs tout à l’heure un lien de JEDI_BC m’a donné l’idée de cet article : qu’est-ce qu’un namedtuple et à quoi ça sert.
Les tuples, vous connaissez : c’est une séquence ordonnées non modifiable d’éléments hétérogènes.
Pardon, je recommence. C’est comme une liste, mais plus rapide, et pas modifiable. Ca se créer avec l’opérateur “,
” :
>>> un_tuple = 1, 2, 3 >>> print(un_tuple) (1, 2, 3) >>> type(un_tuple) <type 'tuple'> >>> un_tuple[0] 1 >>> un_tuple[:-1] (1, 2) >>> autre_tuple = ("pomme", 1, True) |
Les parenthèses sont optionnelles mais permettent d’éviter les ambiguïtés.
Bref, les tuples, c’est top : on peut les slicer, les indexer, et en plus c’est très très rapide car non modifiable :
>>> autre_tuple[0] = "banane" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment |
Le tuple est donc une bonne alternative aux listes si on sait que le contenu ne bougera pas. Ca prend moins de mémoire, c’est plus rapide, c’est tout aussi flexible, et comme c’est un itérable on peut le plugger un peu partout.
Un gros défaut du tuple, néanmoins, c’est l’absence d’attributs nommés. Il faut connaitre les indices des valeurs, et c’est pas évident à lire si le tuple est gros.
Pour cette raison, la lib standard vient avec le namedtuple, qui est simplement un tuple dont les valeurs sont nommées.
Ca s’utilise en deux étapes. D’abord, définir un nouveau type de namedtuple avec la liste des attributs qu’il va contenir. Un peu comme définir une classe :
>>> from collections import namedtuple >>> Joueur = namedtuple('Joueur', ['nom', 'age', 'signe_particulier']) |
À partir de là nous avons une nouvelle “classe” de namedtuple appelée Joueur
qui peut créer des namedtuples avec 3 attributs : ‘nom’, ‘age’ et ‘signe_particulier’.
Et ça s’utilise comme un tuple :
>>> jdg = Joueur('M. Grenier', 31, 'Un langage fleuri') >>> jdg[0] 'M. Grenier' >>> nom, age, signe = jdg >>> nom 'M. Grenier' |
Mais aussi comme un objet en read-only :
>>> jdg.nom 'M. Grenier' >>> sam = Joueur(nom="Sam", age="Tu sauras pas", signe_particulier="Est parfaitement impartial") >>> sam.age 'Tu sauras pas' |
Petite coquille, dans le ème encadré de code :
À la place du NameError ;)
Arf, il manque des “2” un peu partout dans le comm’ précédent… :|
Ce qui me fait peur, c’est que pour voir ce genre de détail, ça veut dire qu’il y a des lecteurs qui run les codes lignes à lignes. Tous les codes. Y compris les codes qui font des erreurs.
Toutes mes erreurs sont vues.
La pression je vous dis pas !
Bon, merci en tout cas, c’est corrigé.
Non t’inquiète pas, c’est juste le NameError qui m’a sauté aux yeux !
Petite coquille sur le nom de la class : Joueur
(oui, oui, on surveille les moindres caractères !)
Met le lien que j’ai donné dans le post, ça peut intéresser quelques un
Et contrairement à un tuple normal, les valeurs sont modifiables :
sam._replace(signe_particulier="Est totalement partial")
Les namedtuples m’ont toujours fait penser aux beans java.
@fpp: un tuple modifiable, même named, je trouvais ça étrange alors j’ai regardé: _replace() ne modifie pas le tuple, mais renvoie une copie en changeant les valeurs passées en argument (comme string.replace()). Donc il faut faire :
sam = sam._replace(signe_particulier="Est totalement partial")
Les
namedtuple
s sont bien non modifiables !En effet ! Je m’étais fié à l’explication donnée par mon aide-mémoire préféré, le “Python Quick Reference”:
http://rgruet.free.fr/PQR27/PQR2.7.html#namedtuples
Mais la fin de l’exemple est au mieux trompeuse, sinon incorrecte…
@sam : mouarf … mais alors .. tu testes pas le code de tes articles ? *:o)
@fpp: Elle est fausse, si tu executes le code la dernière ligne lance une AssertionError. J’ai envoyé un mail au mec pour qu’il corrige ça.
bah y a pas d’image ? ^^
namedtuple fabrique dynamiquement une classe qui encapsule un tuple. Je trouve que c’est à cheval entre 2 technique:
1) J’utilise des classes pour avoir une couche d’abstraction propre
2) Je fou toutes mes données dans des tuples qui contiennent des dicts qui contiennent des tuples et je fais un:
voitures[ 'Md Michoue' ][5][3]['heure'][0]
Pour savoir à quelle heure Md Michoue a prit sa voiture pour aller à la plage.
étant (trop) souvent confronté a du legacy code de catégorie 2, je suis plutôt partisan de la 1er technique et je n’ai pas encore trouver le besoin d’utiliser les NamedTuple
Merci pour cette article. Les explications sont toujours top.
Hum, je ne connaissois point.
En faisant un
, j’ai vu apparaitre les attributs “nom”, “age” et “signe_particulier”. Bon bref jdg est devenue en fait une classe.
J’ai vu aussi d’autres attributs comme “count” et “index”. Et là, je me dis “hum, mais que se passera-donc-t-il-donc si j’écris
??? Je pense que les attributs “count” et “index” vont écraser ceux définis par défaut. En tout cas, j’ai pas eu d’erreur donc danger dans les noms qu’on met aux “tuples nommés”…
Sinon il y a moyen d’itérer les noms et leurs valeurs ? Un peu faire comme un
???
Nope. Tu peux taper dans le mapping des attributs, mais dans ce cas autant utiliser un dico.
merci pour l’image, pas trop grave pour la couleur des cheveux :p
Bonjour,
Merci pour cet article.
pour ceux qui cherche une structure de données mutable avec la même API que namedtuple sachez qu’il existe recordclass
http://stackoverflow.com/questions/29290359/existence-of-mutable-named-tuple-in-python
https://pypi.python.org/pypi/recordclass
http://nbviewer.ipython.org/urls/bitbucket.org/intellimath/recordclass/raw/default/examples/what_is_recordclass.ipynb
sympa ton article :)
quelqu’un a fait un timeit ou un @wraps pour comparer un tuple() avec un named tuple() ou une liste ?
(avec que je convertisse tout le dict de mon app temps réel ?)
Si tu le fais, poste le ici.