2011-12-26 7 views
5

¿Cómo convertirías un anidamiento de objetos Python frozenset en un entero único que fuera el mismo en todas las sesiones y plataformas de Python?Hashing persistente de Python Frozen Sets

p. Ej. Consigo valores diferentes de almohadilla() en diferentes plataformas

32 bits

Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) 
[GCC 4.4.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> a=frozenset([frozenset([1,2,3]),frozenset(['a','b','c'])]); 
>>> hash(a) 
1555175235 

64-bits

Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> a=frozenset([frozenset([1,2,3]),frozenset(['a','b','c'])]); 
>>> hash(a) 
-6076998737938213053 

Respuesta

7

¿Cómo convertir un anidamiento de Python frozenset objetos en un único entero que era el mismo en todas las sesiones y plataformas de Python?

Los hashes de AFAIK no son garantía de ser únicos. De hecho, donde se usan para las tablas de búsqueda (como en los diccionarios), los conflictos hash son bastante comunes.

Dicho eso. Si desea una plataforma cruzada consistente y no única, intentaré usar la biblioteca estándar hashlib. No tengo la posibilidad de probarlo en una plataforma diferente, pero creo que la mayoría de los algoritmos implementados allí (como por ejemplo el MD5) son independientes de la plataforma.

Me gustaría alimentar los algoritmos de hash con la versión encurtida del conjunto ordenado, a fin de asegurarse de que la cadena utilizada para el hash sea siempre la misma.


EDIT: pensado agregar un ejemplo básico:

>>> import cPickle as pkl 
>>> import hashlib as hl 
>>> s = frozenset([1,2,3]) 
>>> p = pkl.dumps(sorted(s)) #make sure you use the same pickle protocol on all platform! 
'(lp1\nI1\naI2\naI3\na.' 
>>> h = hl.md5(p) 
<md5 HASH object @ 0xb76fb110> 
>>> h.digest() 
"\x89\xaeG\x1d'\x83\xa5\xbd\xac\xa7\x1c\xd9\x1d/2t" #this should be consistent 
+0

Por lo que vale la pena, he comprobado que la suma de md5 del congelado en escabeche es la misma en las plataformas de 32 y 64 bits. – jcollado

+0

@jcollado - ¡Gracias! :) – mac

+1

¿Es un encurtido de tipo desordenado, garantizado para encurtir lo mismo en todas las plataformas? Soy reacio a confiar en que así será. Probablemente sacaré los elementos de los conjuntos en listas, y los clasificaré antes del decapado. – dstromberg

0

También puede crear su propia función hash:

def hash(fs): 
    res = 1 
    for v in fs: 
     res = (res*31 + v) % 2**30 
    return res 

Esto no será necesariamente único, pero es tan bueno como la compilación en conjunto hash, y tiene un control total sobre su resultado en todas las plataformas.