8

Pickle 是否总是为某个输入值产生相同的输出?我想在腌制具有相同内容但插入/删除历史不同的字典时可能会有一个问题。我的目标是使用 Pickle 和 SHA1 为 memoize 实现创建函数参数的“签名”。

4

2 回答 2

9

我想在腌制具有相同内容但插入/删除历史不同的字典时可能会有一个问题。

对:

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

另请参阅:pickle.dumps 不适合散列

我的目标是使用 Pickle 和 SHA1 为 memoize 实现创建函数参数的“签名”。

这存在许多基本问题。想出一个正确映射相等性的对象到字符串的转换是不可能的——想想对象身份的问题:

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

根据您的确切要求,您可以将对象层次结构转换为可以散列的对象层次结构:

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
于 2009-06-12T07:06:00.617 回答
0

相同的输出是什么意思?通常,您应该始终获得相同的往返输出(酸洗 -> 解酸),但我认为序列化格式本身并不能保证在每种情况下都是相同的。当然,它可能会在平台之间发生变化。

在你的程序的一次运行中,使用酸洗进行记忆应该没问题 - 我已经多次使用这个方案没有麻烦,但那是非常简单的问题。一个问题是这并没有涵盖所有有用的情况(想到函数:你不能腌制它们,所以如果你的函数接受一个可调用的参数,那将不起作用)。

于 2009-06-12T07:04:14.520 回答