用于任意对象的 python 哈希函数的替代方案

2023-12-13

在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]。显然,不可能使用用于特定调用的固定盐。所以,我需要一个替代方案:

  • 跨解释器调用必须稳定
  • 可能需要在执行时提供参数,例如在通话中设置盐
  • 必须支持任意对象(任何支持的对象dict/set)

我已经尝试过使用哈希函数hashlib(慢!)和校验和zlib(显然对于散列来说不是理想的,但是嗯)它可以很好地处理字符串/字节。然而,他们工作only在类似字节的对象上,而hash()几乎适用于所有东西。


[1] 使用hash()识别存储桶的方法是:

  • 如果盐是随机的,则跨解释器调用不可靠
  • 防止应用程序使用随机加盐功能,盐是固定的
  • 如果有两个则无法使用PersistentDicts 是用不同的盐创建的

我已经成功地使用了以下组合hash and 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 us。对于一个规则的物体来说,hashkey需要 ~1.0 usc。 0.8 微秒bytes0.7 为str.

开销大致如下:

  • 函数调用需要 0.1 usec (hash(obj) vs def pyhash(obj): return hash(obj))
  • 0.2 usec 到 0.5 usec 用于选择哈希函数isinstance
  • 0.75 用于zlib.adler32 or zlib.crc32 vs hash:~0.160 usec vs ~ 0.75 usec(adler 和 crc 为 +/- 4 usec)
  • 0.15 微秒obj.encode() of str对象("foobar")
  • 1.5 微秒str(obj).encode() of datetime.datetime objects

最优化来自于排序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)}

总时间:~0.7 usstr and bytes, 糟糕透顶datetime, 0.35 usec 用于对象、整数等。dict将类型映射到可比较的散列,如果对dict键(又名类型)分别(即不obj.__class__ in hashkey.dict_types but obj.__class__ in hashkey.explicit_dict_types).


一些附加说明:

  • hash对于使用默认值的任何对象,跨解释器启动都不稳定__hash__实施,包括None
  • 它对于不可变容器(定义了__hash__) 含有盐分类型,例如(1, 2, 'three')
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用于任意对象的 python 哈希函数的替代方案 的相关文章

随机推荐

  • C#调用WinApi?

    我正在尝试调用 WinAPI 函数DeviceIoControl在 C 中使用代码IOCTL DISK SET DISK ATTRIBUTES并传递结构SET DISK ATTRIBUTES 我正在尝试用这段代码来做到这一点 const u
  • 如何将 setup.py 替换为 pyproject.toml 以获取本机 C 构建依赖项?

    我碰到this用于创建 C 编译版本的小项目布莱克 斯科尔斯python 中要使用的函数 虽然示例代码似乎是今年7月发布的 但似乎使用setup py旧版构建之外的构建类型已被弃用 任何编译失败 先抱怨缺失MS C 14编译器 这不是真的
  • NSString 反斜杠转义

    我正在开发一个 iPhone OS 应用程序 该应用程序向 Web 服务发送 xml 请求 为了发送请求 xml 被添加到 NSString 中 这样做时我遇到了一些引号问题 和反斜杠 在 xml 文件中 需要转义 是否有需要转义的字符的完
  • R 中的 Bootstrap 置信区间

    我是 R 新用户 在使用启动包时遇到问题 我想要做的就是使用 bootstrapping 来生成围绕数字向量均值的置信区间 例如 x lt rnorm 100 1 5 有小费吗 以下还不够吗 library boot x lt rnorm
  • 了解 rowwise() 和 c_across()

    您好 任何人都可以提供外行人的解释 为什么这两种尝试计算分数的行平均值的方法效果不同 谢谢 library tidyverse var1 lt rnorm 100 var2 lt rnorm 100 var3 lt rnorm 100 df
  • 如果 URL 包含特定字符串,则 htaccess 重定向

    我该如何写一个 htaccess如果 URL 包含某个单词 则重定向规则 例如如果它包含foobar然后重定向到index php RewriteCond REQUEST URI foobar RewriteRule index php o
  • 如何写入 Python 子进程的标准输入?

    我正在尝试编写一个启动子进程并写入子进程标准输入的Python 脚本 我还希望能够确定子进程崩溃时要采取的操作 我试图启动的进程是一个名为nuke它有自己的内置 Python 版本 我希望能够向其提交命令 然后在命令执行后告诉它退出 到目前
  • 如何在 Java 中创建唯一 ID? [复制]

    这个问题在这里已经有答案了 我正在寻找在 Java 中创建唯一 ID 作为字符串的最佳方法 任何指导表示赞赏 谢谢 我应该提到我正在使用 Java 5 创建一个UUID String uniqueID UUID randomUUID toS
  • Chrome 调试器 Api 附加扩展错误

    Task 使用调试其他扩展Chrome 调试器 API 预期输出 其他已安装扩展发出的 http 请求日志 Method 在 python 设置标志中使用 selenium 运行 chrome webdriverchromeopts add
  • 如何使用 VBScript 从驱动器号获取硬盘号

    如何使用 VBScript 从驱动器号获取硬盘号 先感谢您 Remou 关于 WMI 的看法是正确的 只是需要让它变得更混乱一点 如果有更简单 更好的方法来执行此操作 一点也不会感到惊讶 但此脚本至少应该为您提供一个良好的起点来完成您需要的
  • 使用安全登录进行 PHP 网站抓取

    我正在尝试减少我的一位经销商的每种产品的库存数量 他们不知道如何导出这些数据 所以我想知道是否有人可以帮助我指明如何使用 PHP 抓取必须登录才能获取数据的网站的正确方向 它不是一个使用 SSL 的安全站点 感谢您的任何提示 克里斯 爱德华
  • C 中是否有 strtoull() 函数的替代方案?

    我需要转换char to unsigned long long int有一个函数叫做strtoull in the C标准库 但需要很多时间 我需要在之间快速转换char to unsigned long long int 如何编写比标准转
  • 日期列中的 Kendo 网格格式时间问题[重复]

    这个问题在这里已经有答案了 我有一个剑道网格 它有一个日期列 我想在那里显示日期和时间 我在列定义中使用以下格式 format 0 dd MMM yyyy hh mm ss tt 在模态中我使用了日期类型Updated Date type
  • UnsupportedAudioFileException 的解决方法?

    我正处于用 Java 编写小型音乐 节奏游戏的早期阶段 通过 Slick 框架 该框架又使用 OpenAL 但这可能与这里无关 游戏需要读取 并播放 多个 WAV 格式的声音文件 但某些文件抛出 javax sound sampled Un
  • 在 cookie 中存储数组

    我需要在 cookie 中存储一些数组数据 我一直在研究最好的方法来做到这一点 很多人似乎说使用serialize是要走的路 但在这个线程中 PHP如何字符串化数组并存储在cookie中 有人建议不要使用它 因为 序列化将调用序列化类的构造
  • 在函数中使用 dplyr group_by

    我试图在本地函数中使用 dplyr 的 group by 例如 testFunction lt function df x df gt group by x gt summarize mean Petal Width mean Petal
  • 使用 Bootstrap Datepicker 时如何获取选定的日期值?

    使用 jquery 和 Bootstrap Datepicker 如何获取我使用 Bootstrap Datepicker 选择的新日期值 仅供参考 我正在使用 Rails 3 和 Coffescript 我使用以下方法设置日期选择器
  • 具有多对多关系的 MVC4 控制器

    我有两个实体 Arena 和 Regulator 它们之间具有多对多的关系 我已经实现了 EF 代码首先接受的解决方案 见下文 我现在一直致力于实现控制器视图 以便当用户创建调节器时 他可以选择一个或多个竞技场 可能使用复选框或多选列表 并
  • 通过 xpath Selenium java 选择具有动态生成的 id 的 WebElements

    我需要在下拉窗口中选择一个元素 每次我在正在测试的网站中打开下拉窗口时 网站都会随机生成该下拉窗口的 ID 下拉窗口的先前实例可见 使用 Firebug 但不可选择 有一个静态路径 但仅当我使用 ChromeDriver 测试它时才有效 而
  • 用于任意对象的 python 哈希函数的替代方案

    在python2 7中 我成功使用hash 将对象放入持久存储在磁盘上的存储桶中 样机代码如下所示 class PersistentDict object def setitem self key value bucket index ha