【发布时间】:2016-06-24 09:15:12
【问题描述】:
在 python2.7 中,我成功地使用hash() 将对象放入持久存储在磁盘上的存储桶中。样机代码如下所示:
class PersistentDict(object):
def __setitem__(self, key, value):
bucket_index = (hash(key)&0xffffffff) % self.bucket_count
self._store_to_bucket(bucket_index, key, value)
def __getitem__(self, key):
bucket_index = (hash(key)&0xffffffff) % self.bucket_count
return self._fetch_from_bucket(bucket_index)[key]
在 python3 中,hash() 使用随机或固定的盐,这使得它无法用于此 [1]。显然,不可能使用fixed salt for specific invocations。所以,我需要一个替代方案:
- 必须在解释器调用中保持稳定
- 可能需要在执行时提供参数,例如在通话中设置盐
- 必须支持任意对象(
dict/set支持的任何对象)
我已经尝试过使用来自hashlib 的哈希函数(慢!)和来自zlib 的校验和(显然不适合散列,但是meh)可以很好地处理字符串/字节。但是,它们仅适用于字节类对象,而 hash() 几乎适用于所有对象。
[1] 使用hash() 识别存储桶是:
- 如果盐是随机的,则在解释器调用中不可靠
- 防止应用程序使用随机加盐功能(如果盐是固定的)
- 如果使用不同的盐创建两个
PersistentDicts,则无法使用
【问题讨论】:
-
随机哈希仅适用于
str、bytes和datetime对象。您只需要这些类型的替代品。 -
@MartijnPieters 谢谢!我猜 str 和 bytes 可以被 zlib/hashlib 覆盖。我看看能不能快速找到日期时间的东西。
-
如果涉及时区,我仍然会彻底测试并寻找替代方案;我怀疑时区的细微差别可能会导致其他不同时区对象的 ISO8601 表示形式相同,这可能很重要。
-
对于
None,__hash__的实现继承自type,它产生对象内存地址的哈希值,因为这因解释器进程而异,该值可能出现随机.这意味着设置PYTHONHASHSEED不会影响None的哈希值,就像它适用于种子的类型一样。 -
所以我想我必须修改我的第一条评论以包括类型对象(自定义类和内置)和
None。
标签: python python-3.x python-2.x