Por Favor Ayuda
Alexis Roda
alexis.roda.villalonga en gmail.com
Mar Jun 27 23:13:26 CEST 2006
En/na Chema Cortes ha escrit:
> Es algo lioso de explicar, pero el problema está en que 'd' no debe
> verse como la clave. Una vez creada la instancia de MiDiccionario, ya
> no hay relación con 'd'.
Creo que me va a explotar la cabeza :-)
> En este código habría que haber comprobado
> que todavía existe la clave:
>
>>>> r.has_key(d)
> False
>>>> print r.keys()
> {2: 'otra clave', 'clave1': 'Esta es la clave 1'}
A mi me da otro resultado:
Python 2.3.5 (#2, Sep 4 2005, 22:01:42)
[GCC 3.3.5 (Debian 1:3.3.5-13)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class MiDiccionario(dict):
... def __hash__(self):
... return tuple(self.items()).__hash__()
...
>>> d=MiDiccionario( {'clave1':"Esta es la clave 1", 2:"otra clave"} )
>>> r = {d:d}
>>> r.keys()
[{2: 'otra clave', 'clave1': 'Esta es la clave 1'}]
>>> r.keys()[0] is d
True
>>> d['otra clave'] = 12345
>>> r.keys()
[{'otra clave': 12345, 2: 'otra clave', 'clave1': 'Esta es la clave 1'}]
>>> r.has_key(d)
False
>>> r.keys()[0] is d
True
>>>
Imagino que el problema aparece como consecuencia del funcionamiento de
las tablas asociativas.
Al hacer r[d] = 'foo' python utiliza el "bucket" B1 para almacenar
'foo'. B1 se determina a partir del valor H1 = d.__hash__()
Al modificar d tenemos H2 = d.__hash__(), muy posiblemente H2 != H1.
El bucket correspondiente al nuevo valor de d será B2, determinado a
partir de H2. Muy probablemente B1 != B2.
Si ahora accedemos a r[d] estaremos buscando en el sitio equivocado
(B2), motivo del KeyError.
Es pura especulación, pero suena convincente (suficiente para mi nivel
de curiosidad actual :-) ). Para el que quiera buscarla, supongo que la
respuesta buena estará en Objects/dictobject.c.
Saludos
Más información sobre la lista de distribución Python-es