Python, sum de comprobación de un dict.

Estoy pensando en crear una sum de comprobación de un dictado para saber si se modificó o no. Por el momento tengo eso:

>>> import hashlib >>> import pickle >>> d = {'k': 'v', 'k2': 'v2'} >>> z = pickle.dumps(d) >>> hashlib.md5(z).hexdigest() '8521955ed8c63c554744058c9888dc30' 

Tal vez exista una mejor solución?

Nota: quiero crear un ID único de un dict para crear un buen Etag.

EDITAR: Puedo tener datos abstractos en el dict.

    Algo como esto:

     reduce(lambda x,y : x^y, [hash(item) for item in d.items()]) 

    Tome el hash de cada tupla (clave, valor) en el dict y XOR todas juntas.

    @katrielalex Si el dict contiene elementos inestables, puede hacer esto:

     hash(str(d)) 

    o tal vez incluso mejor

     hash(repr(d)) 

    No sé si pickle garantiza que el hash se serializa de la misma manera cada vez.

    Si solo tiene diccionarios, me gustaría ir a una combinación de llamadas a keys() , sorted() , crear una cadena basada en los pares de clave / valor ordenados y calcular la sum de comprobación en esa

    Como dijiste, querías generar un Etag basado en el contenido del diccionario, OrderedDict que preserva el orden del diccionario puede ser mejor candidato aquí. Solo iterador a través de la clave, los pares de valores y construya su cadena Etag.

    Creo que es posible que no te des cuenta de algunas de las sutilezas que intervienen en esto. El primer problema es que el orden en que aparecen los elementos en un dict no está definido por la implementación. Esto significa que el simple hecho de pedir un dictado no funciona, porque podría haber

     str(d1) == "{'a':1, 'b':2}" str(d2) == "{'b':2, 'a':1}" 

    y estos tendrán hash a diferentes valores. Si solo tienes elementos hashables en el dict, puedes agruparlos y luego unirlos, como @Bart o simplemente

     hash(tuple(sorted(hash(x) for x in d.items()))) 

    Tenga en cuenta lo sorted , ya que debe asegurarse de que la tupla de hash salga en el mismo orden, independientemente del orden en que aparezcan los elementos en el dict. Si tiene dictados en el dictado, puede repetir esto, pero será complicado.

    PERO sería fácil romper cualquier implementación como esta si permitiera datos arbitrarios en el diccionario, ya que simplemente puede escribir un objeto con una implementación __hash__ rota y usarla. Y no puedes usar id , porque entonces podrías tener elementos iguales que comparen diferentes.

    La moraleja de la historia es que los dictados de hash no se admiten en Python por una razón.

    En Python 3, la función hash se inicializa con un número aleatorio, que es diferente para cada sesión de python. Si eso no es aceptable para la aplicación deseada, use, por ejemplo, zlib.adler32 para generar la sum de comprobación para un dict:

     import zlib d={'key1':'value1','key2':'value2'} checksum=0 for item in d.items(): c1 = 1 for t in item: c1 = zlib.adler32(bytes(repr(t),'utf-8'), c1) checksum=checksum ^ c1 print(checksum)