【问题标题】:Is there any reason *not* to cache an object's hash?是否有任何理由*不*缓存对象的哈希?
【发布时间】:2011-04-16 18:56:13
【问题描述】:

我编写了一个类,它的.__hash__() 实现需要很长时间才能执行。我一直在考虑缓存它的哈希,并将其存储在像._hash 这样的变量中,所以.__hash__() 方法将简单地返回._hash。 (这将在 .__init__() 的末尾或第一次调用 .__hash__() 时计算。)

我的理由是:“这个对象是不可变的 -> 它的哈希永远不会改变 -> 我可以缓存这个哈希。”

但现在这让我想到:你可以对 any 可哈希对象说同样的话。 (除了以哈希为 id 的对象。)

那么有没有理由缓存对象的哈希,除了哈希计算非常快的小对象?

【问题讨论】:

    标签: python caching hash


    【解决方案1】:

    当然,可以缓存散列值。事实上,Python 对字符串本身就是这样做的。权衡是在哈希计算的速度和保存哈希值所需的空间之间。这种权衡就是为什么元组不缓存它们的哈希值,但字符串会缓存(参见request for enhancement #1462796)。

    【讨论】:

      【解决方案2】:

      通常的原因是 Python 中的大多数对象都是可变的,所以如果散列依赖于属性,那么只要你改变一个属性,它就会改变。如果您的类确实是不可变的并且(进入散列的所有属性也是不可变的!),那么您可以缓存散列。

      【讨论】:

      • 当然,如果一个对象是可变的,那么实现__hash__ 通常是个坏主意。 __hash__ 的唯一内置用法要求哈希是稳定的。
      • 不,__hash__ 的默认实现不会在您更改对象的属性时返回任何不同的内容。因为默认情况下这对任何对象都是正确的:hash(obj) == id(obj) == hash(id(obj))——这意味着对象只是将它们的 id 作为它们的哈希值。 id 是静态的,所以你可以说对象默认“缓存”它们的哈希值。
      【解决方案3】:

      hash(obj) == id(obj) 一般不成立:

          >>> class A(object): pass
          ... 
          >>> a = A()
          >>> hash(a), id(a)
          (8762051845337, 140192829525392)
      

      【讨论】:

      • 这不是答案。似乎是对上述答案中的cmets的回应。
      • 而且它不应该 id 对于任何唯一对象都是唯一的,hash 是用于值的。
      猜你喜欢
      • 1970-01-01
      • 2017-12-04
      • 2013-10-20
      • 2011-11-28
      • 2011-05-19
      • 1970-01-01
      • 1970-01-01
      • 2015-10-18
      • 2010-12-27
      相关资源
      最近更新 更多