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