在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()
识别存储桶是:
PersistentDict
,则无法使用答案 0 :(得分:0)
我使用hash
和zlib.adler32
的组合取得了成功。最直接的实现是:
def hashkey(obj, salt=0):
"""
Create a key suitable for use in hashmaps
:param obj: object for which to create a key
:type: str, bytes, :py:class:`datetime.datetime`, object
:param salt: an optional salt to add to the key value
:type salt: int
:return: numeric key to `obj`
:rtype: int
"""
if obj is None:
return 0
if isinstance(obj, str):
return zlib.adler32(obj.encode(), salt) & 0xffffffff
elif isinstance(obj, bytes):
return zlib.adler32(obj, salt) & 0xffffffff
elif isinstance(obj, datetime_type):
return zlib.adler32(str(obj).encode(), salt) & 0xffffffff
return hash(obj) & 0xffffffff
使用Python 3.4.3,这比调用普通hash
要慢得多,后者需要大约0.07 usec。对于常规对象,hashkey
需要~1.0 usec。 0.8 usec表示bytes
,0.7表示str
。
开销大致如下:
hash(obj)
vs def pyhash(obj): return hash(obj)
)isinstance
zlib.adler32
或zlib.crc32
vs hash
:~0.160 usec vs~0.75 usec(adler和crc为+/- 4 usec)obj.encode()
str
个"foobar"
个对象str(obj).encode()
的0.15 usec datetime.datetime
if
个对象最优化来自def hashkey_c(obj, salt=0):
if obj.__class__ in hashkey_c.types:
if obj is None:
return 0
if obj.__class__ is str:
return zlib.adler32(obj.encode(), salt) & 0xffffffff
elif obj.__class__ is bytes:
return zlib.adler32(obj, salt) & 0xffffffff
elif obj.__class__ is datetime_type:
return zlib.adler32(str(obj).encode(), salt) & 0xffffffff
return hash(obj) & 0xffffffff
hashkey_c.types = {str, bytes, datetime_type, type(None)}
语句的排序。如果一个人主要期望普通物体,以下是我能想到的最快的物品:
str
总时间:bytes
和datetime
约为0.7,dict
为极差,对象为int,等等为0.35。使用dict
将地图类型映射到如果一个人使用obj.__class__ in hashkey.dict_types
密钥(又称类型)分别使用显式检查(即不是obj.__class__ in hashkey.explicit_dict_types
而是hash
),则哈希值可比较。
一些补充说明:
__hash__
实施的任何对象,None
在解释器启动时不稳定,包括__hash__
(1, 2, 'three')