【问题标题】:Is python's hash() portable?python 的 hash() 是可移植的吗?
【发布时间】:2015-07-01 20:13:26
【问题描述】:

python的hash函数可以移植吗?

我所说的“可移植”是指,它是否会跨 python 版本、平台和实现返回相同的结果(对于相同的数据)?

如果没有,是否有任何替代方案提供此类功能(同时仍能够散列常见数据结构)?


The documentation 不是特别有用。 This question 指的是一个似乎推出了自己的版本的库,但我不确定它的原因是不可移植性。

【问题讨论】:

  • hash 仅用于dict 类型,它被实现为哈希表。您可能需要标准库中 hashlib 模块中的函数。
  • @chepner 我正在寻找像hash 这样的任意数据结构散列的东西,我认为hashlib 不会这样做?
  • hash 也不能散列任意数据结构。 (尝试将dictset 传递给hash。)
  • @chepner 是的,我知道只支持简单且不可变的结构。这足以满足我的需求(尽管可能不是其他人的)

标签: python hash cross-platform portability


【解决方案1】:

不,hash() 不保证可移植。

Python 3.3 默认也使用 散列随机化,其中某些类型在启动时使用散列种子进行散列。然后,Python 解释器调用之间的哈希值会有所不同。

来自object.__hash__() documenation

默认情况下,str、bytes 和 datetime 对象的 __hash__() 值是用不可预测的随机值“加盐”的。尽管它们在单个 Python 进程中保持不变,但它们在 Python 的重复调用之间是不可预测的。

这是为了防止由精心选择的输入引起的拒绝服务,这些输入利用字典插入的最坏情况性能,O(n^2) 复杂度。详情请见http://www.ocert.org/advisories/ocert-2011-003.html

更改哈希值会影响 dicts、sets 和其他映射的迭代顺序。 Python 从未对这种顺序做出保证(它通常在 32 位和 64 位版本之间变化)。

另见PYTHONHASHSEED

Python 2.6.8 和 3.2.3 及更新版本支持相同的功能,但通常禁用它。

Python 3.2 引入了sys.hash_info named tuple,它为您提供了有关当前解释器的哈希实现的详细信息。

如果你需要一个可移植的哈希,有很多实现。标准库包括一个名为hashlib 的加密哈希库;这些实现绝对是可移植的。另一种选择是mm3 package,它提供Murmur3 non-cryptographic hash function implementations

普通数据结构需要先转换为字节;您可以为此使用序列化,例如 jsonpickle 模块。

【讨论】:

  • 这是对主要问题的出色回答。至于替代方案,我有dug a bit more,看起来序列化为 json 是一个合理的替代方案。如果您不介意我编辑您的答案,我可以包含该信息
  • @goncalopp:序列化为 JSON 不会给你一个紧凑的散列;你仍然必须通过某种散列算法来运行它。我添加了指向hashlib 的指针。
  • 是的,然后您可以通过 hashlib 运行它,如 this answer。注意我已经编辑了这个问题以澄清我正在寻找像hash那样散列数据结构的东西,而不仅仅是字符串
  • @goncalopp:然后将这些数据结构转换为字节; JSON 可以做到这一点,但 pickle 模块也可以。
  • pickle 在不同的 python 版本上生成不同的输出,因此它不会是“便携式哈希”。 JSON序列化为easy enough to control,以便得到reasonably canonical
猜你喜欢
  • 2020-01-30
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
  • 2013-04-27
  • 2020-02-08
  • 2016-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多