散列在python中的对象的总和

时间:2015-03-25 16:43:09

标签: python hash

在我的脚本中,我使用大而复杂的对象(包含自定义类型的字符串,字典和类对象的多维列表)。我需要复制,pickle(缓存)和unpickle,以及通过MPI接口在子进程之间发送。在某些方面,我怀疑数据传输没有错误,即最后我有相同的对象。

因此,我想计算其哈希值或其他类型的指纹。我知道有例如hashlib库;但是,它在对象类型方面受到限制:

>>> import hashlib
>>> a = "123"
>>> hashlib.sha224(a.encode()).hexdigest()
'78d8045d684abd2eece923758f3cd781489df3a48e1278982466017f'
>>> a = [1, 2, 3]
>>> hashlib.sha224(a).hexdigest()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object supporting the buffer API required

因此,问题是:是否有一些类似的函数可以处理任何类型的对象?

2 个答案:

答案 0 :(得分:1)

pickle.dumps(...)

返回一个字符串,它是一个可哈希的对象。您可以按照以下方式执行此操作

import pickle
a=[1,2,3,4]
h=pickle.dumps(a)
print hash(h)

# or like this

from hashlib import sha512
print sha512(h).hexdigest()

c=pickle.loads(h)
assert c==a

答案 1 :(得分:1)

一种选择是递归地将结构的所有元素转换为可混合的对应物,即列入元组,dicts和对象到frozensets,然后简单地将hash()应用于整个事物。举例说明:

def to_hashable(s):
    if isinstance(s, dict):
        return frozenset((x, to_hashable(y)) for x, y in s.items())
    if isinstance(s, list):
        return tuple(to_hashable(x) for x in s)
    if isinstance(s, set):
        return frozenset(s)
    if isinstance(s, MyObject):
        d = {'__class__': s.__class__.__name__}
        d.update(s.__dict__)
        return to_hashable(d)
    return s

class MyObject:
    pass

class X(MyObject):
    def __init__(self, zzz):
        self.zzz = zzz

my_list = [
    1,
    {'a': [1,2,3], 'b': [4,5,6]},
    {1,2,3,4,5},
    X({1:2,3:4}),
    X({5:6,7:8})
]

print hash(to_hashable(my_list))

my_list2 = [
    1,
    {'b': [4,5,6], 'a': [1,2,3]},
    {5,4,3,2,1},
    X({3:4,1:2}),
    X({7:8,5:6})
]

print hash(to_hashable(my_list2)) # the same as above