2010-04-22 8 views
9

que define una clase:Python hash() no puede manejar un entero largo?

 
class A: 
    ''' hash test class 
    >>> a = A(9, 1196833379, 1, 1773396906) 
    >>> hash(a) 
    -340004569 

    This is weird, 12544897317L expected. 
    ''' 
    def __init__(self, a, b, c, d): 
     self.a = a 
     self.b = b 
     self.c = c 
     self.d = d 

    def __hash__(self): 
     return self.a * self.b + self.c * self.d 

¿Por qué, en el doctest, función hash() da un entero negativo?

Respuesta

10

Parece estar limitado a 32 bits. Al leer this question, parece que su código podría haber producido el resultado esperado en una máquina de 64 bits (con esos valores particulares, ya que el resultado cabe en 64 bits).

Los resultados de la función incorporada hash dependen de la plataforma y están limitados al tamaño de la palabra nativa. Si necesita un hash determinístico multiplataforma, considere usar el módulo hashlib.

4

Dado que el propósito de una función hash es tomar un conjunto de entradas y distribuirlas a través de un rango de claves, no hay ninguna razón para que esas claves tengan que ser enteros positivos.

El hecho de que la función hash de pitones devuelva números enteros negativos es solo un detalle de implementación y está necesariamente limitado a entradas largas. Por ejemplo, hash ('abc') es negativo en mi sistema.

7

Ver object.__hash__

en cuenta que

cambiado en la versión 2.5: __hash__() puede ahora también devolver un objeto entero largo; el entero de 32 bits se deriva del hash de ese objeto.

En su caso, que se espera 12544897317L es un objeto entero largo,

Python deriva el entero de 32 bits -340,004,569 por (12544897317 & 0xFFFFFFFF) - (1<<32)

Python deriva el entero de 32 bits por almohadilla (12544897317L), lo que se traduce -340004569

El algoritmo es algo como esto:

def s32(x): 
    x = x & ((1<<32)-1) 
    if x & (1<<31): 
     return x - (1<<32) 
    else: 
     return x 

def hash(x): 
    h = 0 
    while x: 
     h += s32(x) 
     x >>= 32 
    return h 
+2

Nitpick: (12544897317 & 0xFFFFFFFF) - (1 << 32) no es -340004569; es -340004571. Python realmente llega al número de 32 bits mediante * re-hashing *; es decir, cálculo hash (12544897317). Esto es mejor porque no solo descarta los bits de orden superior del valor hash original, sino que los mezcla en el valor hash final. –

+0

@Mark Dickinson, uh-huh, gracias – inv

Cuestiones relacionadas