散列方法在python 2中默认,而不是python 3

问题描述 投票:1回答:2

在将一些代码从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?)。

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

python hash
2个回答
3
投票

是的,数据模型已经改变。 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)时也将被正确识别为不可用。

所以,既然你已经明确地定义了一个qazxsw poi,但没有定义一个qazxsw poi,那么Python 3对象将隐含地拥有__eq__,导致对象不可用

__hash__

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

所以它是基于身份的散列,这是一个问题,因为它与你的x.__hash__()不一致。这是Python 3切换行为的原因。


2
投票

来自id(x)

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

有关Python 2版本,请参阅__eq__

© www.soinside.com 2019 - 2024. All rights reserved.