2009-06-12 16 views
7

¿Pickle siempre produce la misma salida para un cierto valor de entrada? Supongo que podría haber un error al elegir diccionarios que tienen los mismos contenidos pero diferentes historiales de inserción/eliminación. Mi objetivo es crear una "firma" de argumentos de función, usando Pickle y SHA1, para una implementación memoise.¿El proceso de decapado es determinista?

Respuesta

7

Supongo que podría haber un error al extraer diccionarios que tienen los mismos contenidos pero diferentes historiales de inserción/eliminación.

Derecha:

>>> pickle.dumps({1: 0, 9: 0}) == pickle.dumps({9: 0, 1: 0}) 
False 

Consulte también: pickle.dumps not suitable for hashing

Mi objetivo es crear una "firma" de los argumentos de la función, el uso de la salmuera y SHA1, para una aplicación memoize.

Hay una serie de problemas fundamentales con esto. Es imposible llegar a una transformación objeto-cadena que mapea la igualdad correctamente-pensar en el problema de la identidad del objeto:

>>> a = object() 
>>> b = object() 
>>> a == b 
False 
>>> pickle.dumps(b) == pickle.dumps(a) 
True 

Dependiendo de sus requisitos exactos, puede ser capaz de transformar las jerarquías de objetos en los que usted podría entonces hash:

def hashablize(obj): 
    """Convert a container hierarchy into one that can be hashed. 

    Don't use this with recursive structures! 
    Also, this won't be useful if you pass dictionaries with 
    keys that don't have a total order. 
    Actually, maybe you're best off not using this function at all.""" 
    try: 
     hash(obj) 
    except TypeError: 
     if isinstance(obj, dict): 
      return tuple((k, hashablize(v)) for (k, v) in sorted(obj.iteritems())) 
     elif hasattr(obj, '__iter__'): 
      return tuple(hashablize(o) for o in obj) 
     else: 
      raise TypeError("Can't hashablize object of type %r" % type(obj)) 
    else: 
     return obj 
0

¿Qué quiere decir con la misma salida? Normalmente siempre debe obtener el mismo resultado para un viaje de ida y vuelta (decapado -> desatornillado), pero no creo que el formato serializado en sí mismo garantice que es el mismo en todas las condiciones. Ciertamente, puede cambiar entre plataformas y todo eso.

Dentro de una ejecución de su programa, usar decapado para la memorización debería estar bien - He usado este esquema varias veces sin problemas, pero eso fue para problemas bastante simples. Un problema es que esto no cubre todos los casos útiles (la función viene a la mente: no se los puede encuadrar, de modo que si su función toma un argumento invocable, eso no funcionará).

Cuestiones relacionadas