【问题标题】:Hash method is defaulted in python 2, not python 3哈希方法在 python 2 中默认,而不是 python 3
【发布时间】:2023-03-26 13:14:01
【问题描述】:

在将某些代码从 python 2 转换到 python 3 时,我遇到了一个奇怪的行为示例。下面是它的最小 (?) 示例:


class Bar(object):
    def __init__(self, x):
        self.x = x
    def __eq__(self, other):
        return self.x == other.x

b = Bar(1)
print(hash(b))

当使用python2 运行时,此代码会产生一些输出(Bar(1) 的哈希),而python3 会产生TypeError: unhashable type: 'Bar'

这意味着 __hash__ 在 python 2 中以某种方式继承(从 object ?)。

所以,我的问题是:Bar(1) 在 python 2 中的哈希是什么?为什么行为不同?

【问题讨论】:

    标签: python hash


    【解决方案1】:

    是的,数据模型已更改。 In Python 3:

    用户定义的类有 __eq__()__hash__() 方法 默认;与它们相比,所有对象都比较不平等(除了 他们自己)和x.__hash__() 返回一个适当的值,使得 x == y 暗示 x is yhash(x) == hash(y)

    覆盖__eq__() 且未定义__hash__() 的类将其__hash__() 隐式设置为None。当。。。的时候 __hash__() 类的方法是None,当程序尝试检索时,类的实例将引发适当的 TypeError 它们的哈希值,也将被正确识别为不可哈希 检查isinstance(obj, collections.abc.Hashable)时。

    因此,由于您明确定义了__eq__,但没有定义__hash__,P​​ython 3 对象将隐含__hash__ = None,导致对象不可散列

    Python 2:

    用户定义的类有__cmp__()__hash__()方法 默认;与它们相比,所有对象都比较不平等(除了 他们自己)和x.__hash__()返回从id(x)派生的结果。

    所以它是基于身份的哈希,这是一个问题,因为它与您的__eq__ 不一致。这是 Python 3 切换行为的原因。

    【讨论】:

      【解决方案2】:

      来自https://docs.python.org/3/reference/datamodel.html#object.hash

      重写 eq() 且未定义 hash() 的类将 将其 hash() 隐式设置为 None。当 hash() 方法 一个类的值为无,该类的实例将引发一个适当的 TypeError 当程序尝试检索其哈希值时,以及 检查时也将被正确识别为不可散列 isinstance(obj, collections.abc.Hashable)。

      请参阅https://docs.python.org/2/reference/datamodel.html#object.hash 了解 Python 2 版本。

      【讨论】:

      • 第二个链接只说“x.__hash__() 返回从 id(x) 派生的结果。”。如何查看结果是如何得出的?
      • 您可以在此处查看有关 cmets 中不同版本 Python 的一些讨论:stackoverflow.com/questions/11324271/…
      猜你喜欢
      • 1970-01-01
      • 2019-06-12
      • 1970-01-01
      • 2015-04-11
      • 1970-01-01
      • 2016-12-27
      • 2018-01-15
      • 1970-01-01
      • 2017-12-18
      相关资源
      最近更新 更多