Sam & Max » tuple http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Le namedtuple, la structure mal aimée 17 http://sametmax.com/le-namedtuple-la-structure-mal-aimee/ http://sametmax.com/le-namedtuple-la-structure-mal-aimee/#comments Thu, 13 Feb 2014 16:29:32 +0000 http://sametmax.com/?p=9137 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'
]]>
http://sametmax.com/le-namedtuple-la-structure-mal-aimee/feed/ 17
De l’intérêt des tuples comme clé de dictionnaire 8 http://sametmax.com/de-linteret-des-tuples-comme-cle-de-dictionnaire/ http://sametmax.com/de-linteret-des-tuples-comme-cle-de-dictionnaire/#comments Sat, 21 Dec 2013 08:18:02 +0000 http://sametmax.com/?p=8392 On peut utiliser n’importe quel objet hashable comme clé de dictionnaire en Python, pas uniquement des strings. Donc des entiers bien entendu, mais également, et c’est rarement utilisé, des tuples.

Imaginez que vous ayez une structures de données ainsi initialisée :

from random import choice, randint
 
tags = ('personne', 'animal', 'objet')
depart = {}
 
depart = {'%s_%s' % (choice(tags), randint(0, 10)): None for x in range(10)}

Cela donne quelque chose comme ça :

{u'personne_6': None,
 u'personne_5': None,
 u'objet_9': None,
 u'objet_6': None,
 u'objet_4': None,
 u'personne_8': None,
 u'objet_2': None,
 u'objet_0': None,
 u'animal_8': None}

On voit que les clés ont ici une valeur sémantique importante : elles sont porteuses de sens.

Si vous voulez la liste des nombres utilisés, il va vous falloir changer votre structure de données : en avoir plusieurs séparées, probablement. Ou alors faire de la manipulation de chaîne à base de split() et de casting.

Par contre, si vous utilisez un tuple comme clé, vous avez le même format pour votre dictionnaire depart, avec les mêmes possibilités, mais en plus un accès aux clés plus complet.

Déjà le code de génération est plus simple :

depart = {(choice(tags), randint(0, 10)): None for x in range(10)}

Ce qui donne :

{(u'animal', 2): None,
 (u'personne', 5): None,
 (u'personne', 4): None,
 (u'objet', 6): None,
 (u'objet', 10): None,
 (u'animal', 7): None,
 (u'animal', 1): None,
 (u'animal', 10): None,
 (u'personne', 8): None}

Mais en prime, on peut faire ça :

for (tag, number), value in depart.items():
    print tag, number, value
 
## animal 2 None
## personne 5 None
## personne 4 None
## objet 6 None
## objet 10 None
## animal 7 None
## animal 1 None
## animal 10 None
## personne 8 None

Bref, quand vos clés ont une valeur sémantique importante, pensez à utiliser des tuples, voir carrément, un namedtuple, qui est une structure de données trop souvent ignorée alors qu’elle est très puissante, et peut remplacer bien des classes conteneurs.

]]>
http://sametmax.com/de-linteret-des-tuples-comme-cle-de-dictionnaire/feed/ 8