2009-08-24 20 views
9

¿Hay alguna manera de generar una identificación tipo hash para los objetos en python que se basa únicamente en los valores de atributo de los objetos? Por ejemplo,Genera una ID única para el objeto python en función de sus atributos

class test: 
    def __init__(self, name): 
     self.name = name 

obj1 = test('a') 
obj2 = test('a') 

hash1 = magicHash(obj1) 
hash2 = magicHash(obj2) 

Lo que estoy buscando es algo donde hash1 == hash2. ¿Algo como esto existe en Python? Sé que puedo probar si obj1.name == obj2.name, pero estoy buscando algo general que pueda usar en cualquier objeto.

Respuesta

6

¿Quiere decir algo como esto? Utilizando el método especial __hash__

class test: 
    def __init__(self, name): 
     self.name = name 
    def __hash__(self): 
     return hash(self.name) 

>>> hash(test(10)) == hash(test(20)) 
False 
>>> hash(test(10)) == hash(test(10)) 
True 
+2

Sin embargo, no se garantiza que sea único. –

+0

@Bastien, tienes razón. Pero eso realmente depende de la aplicación. Para muchos casos, hash podría ser suficiente. –

+1

No se recomienda devolver nada de __hash __ (self) además de int (http://docs.python.org/reference/datamodel.html#object.__hash__) ya que esto hará que el objeto tenga una apariencia aparentemente incorrecta (como en utilizado en los dictados) – SingleNegationElimination

3

Para obtener una comparación único:

ser único que podría serializar los datos y luego comparar el valor serializado para asegurarse de que coincide exactamente.

Ejemplo:

import pickle 

class C: 
    i = 1 
    j = 2 

c1 = C() 
c2 = C() 
c3 = C() 
c1.i = 99 

unique_hash1 = pickle.dumps(c1) 
unique_hash2 = pickle.dumps(c2) 
unique_hash3 = pickle.dumps(c3) 

unique_hash1 == unique_hash2 #False 
unique_hash2 == unique_hash3 #True 

Si usted no necesita valores únicos para cada objeto, pero sobre todo único:

Nota el mismo valor siempre se reducirá al mismo hash, pero diferente 2 los valores pueden reducirse al mismo hash.

No se puede utilizar algo así como la función incorporada de hash() (a menos que anule __hash__)

hash(c1) == hash(c2) #False 
hash(c2) == hash(c3) #False <--- Wrong 

o algo así serializar los datos usando salmuera y luego usar zlib.crc32.

import zlib 
crc1 = zlib.crc32(pickle.dumps(c1)) 
crc2 = zlib.crc32(pickle.dumps(c2)) 
crc3 = zlib.crc32(pickle.dumps(c3)) 
crc1 == crc2 #False 
crc2 == crc3 #True 
+0

Para la comparación única también puede usar zlib.compress para hacer la representación un poco más pequeña si tus objetos son muy grandes –

+0

No, pickle no es bueno para hash. Los resultados pueden variar, según lo descrito por Robert Brewer: http://www.aminus.org/blogs/index.php/2007/11/03/pickle_dumps_not_suitable_for_hashing?blog=2 –

+0

No estoy seguro de por qué pero con CPython 2.5.1 I no puede reproducir su comportamiento Siempre tiene el mismo resultado para mí. –

2

supongo

def hash_attr(ins): 
return hash(tuple(ins.__dict__.items())) 

hashes instancia nada sobre la base de sus atributos.

+1

Siempre que todos los atributos sean aptos para el uso .. –

Cuestiones relacionadas