types acceptés comme key d'un dict [résolu]

types acceptés comme key d'un dict [résolu] - Python - Programmation

Marsh Posté le 03-10-2005 à 19:59:51    

Bonsoir !
 
Je lis dans la doc python (http://python.org/doc/2.4.1/tut/no [...] 0000000000) que :
 

... dictionaries are indexed by keys, which can be any immutable type; strings and numbers can always be keys. Tuples can be used as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object either directly or indirectly, it cannot be used as a key. You can't use lists as keys, since lists can be modified in place using their append() and extend() methods, as well as slice and indexed assignments.


Donc je n'ai pas le droit d'écrire :

d = { [1,2] : "mon machin pour 1,2" }


et effectivement Python me l'interdit (list object are unhashable)
 
Bon. De même il va de soi que ceci m'est interdit (et en effet, même message d'erreur)

class myclass(list):
____pass
d = { myclass() : "mon machin pour myclass()" }


Mais alors pourquoi Python me laisse-t-il écrire ceci ??? (pas d'erreur signalée) :

class myclass(object):
____myclass_o = []
d = { myclass() : "mon machin pour myclass()" }


myclass_o est bien un type mutable, non ? Est-ce Python qui ne voit pas le problème ou moi qui n'est pas compris la doc ?
 
 
edit : typos


Message édité par suizokukan le 03-10-2005 à 22:52:22

---------------
rule #1 : trust the python
Reply

Marsh Posté le 03-10-2005 à 19:59:51   

Reply

Marsh Posté le 03-10-2005 à 20:21:49    

Ptin mais arrête d'utiliser des underscores bordel, c'est incompréhensible [:mlc]
 
Et dériver MyClass (CamelCase stp) de list, ça veut dire qu'un objet de type MyClass est mutable. Ton objet Python n'est pas mutable, puisque ton "myclass_o" fait partie de la classe et non de l'objet.
 
Dernière question: quel intérêt ça a de se poser ces questions [:petrus dei]


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 03-10-2005 à 20:38:53    

ben c'est hashable ou ça l'est pas.

Reply

Marsh Posté le 03-10-2005 à 22:51:41    

> Masklinn (et Taz  :)) Merci du coup de main et désolé pour les ____, c'est vrai que ce n'est pas clair...
 
Pourquoi je me triture les méninges là-dessus ? Bah... par curiosité et parce ce que j'en ai marre de réécrire mon code. Ca m'arrive à chaque fois que j'utilise des techniques que je maîtrise mal : en l'occurence, ce qui hashable et ce qui ne l'est pas.


---------------
rule #1 : trust the python
Reply

Marsh Posté le 03-10-2005 à 22:56:09    

Ben si tu veux savoir ce qui est hashable et ce qui l'est pas, tu utilises la fonction "hash" dessus
 

>>> hash(tuple())
3527539
>>> hash(2)
2
>>> hash("test" )
1308370872
>>> hash(object())
14664760
>>> hash(dict())
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: dict objects are unhashable
>>> hash(list())
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: list objects are unhashable
>>>


 
Accessoirement, je te recommande quelques petits trucs à faire:

  • Lire le tutoriel python en entier
  • Lire Dive Into Python en entier (bouquin gratuit sur Py)
  • dir(__builtins__) puis utiliser la fonction "help" sur chaque objet que tu vois (genre "help(map)", "help(callable)", ...)


En option, http://wiki.python.org/moin/ et http://the.taoofmac.com/space/Python/Grimoire


Message édité par masklinn le 03-10-2005 à 23:02:40

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 03-10-2005 à 22:58:10    

En effet c'est l'existence d'une méthode __hash__ valide (qui retourne un entier) qui détermine si l'objet sera utilisable comme clé dans un dictionnaire.
Mais rien ne t'empêche de foutre le bordel:


>>> class L(list):
        def __hash__(self):
            return hash(tuple(self))
 
>>> l = L((1,2,3))
>>> d = {l:None}
>>> L((1,2,3)) in d
True            # jusqu'ici tout va bien
>>> l[1]=4
>>> d
{[1, 4, 3]: None}
>>> L((1,2,3)) in d
False           # on s'y attendait
>>> L((1,4,3)) in d
False           # arg! le hash de l a changé mais le dictionnaire ne le sait pas !
>>> l in d
False           # même ainsi ça ne va pas

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed