在将一些代码从 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 类型: 'Bar'
这意味着 __hash__
在 python 2 中以某种方式继承(从 object
?)。
所以,我的问题是:python 2 中 Bar(1)
的散列是什么?为什么行为不同?
最佳答案
是的,数据模型已经改变了。 In Python 3 :
User-defined classes have
__eq__()
and__hash__()
methods by default; with them, all objects compare unequal (except with themselves) andx.__hash__()
returns an appropriate value such thatx == y
implies both thatx is y
andhash(x) == hash(y)
.A class that overrides
__eq__()
and does not define__hash__()
will have its__hash__()
implicitly set toNone
. When the__hash__()
method of a class isNone
, instances of the class will raise an appropriate TypeError when a program attempts to retrieve their hash value, and will also be correctly identified as unhashable when checkingisinstance(obj, collections.abc.Hashable)
.
因此,由于您明确定义了 __eq__
,但没有定义 __hash__
,因此 Python 3 对象将隐含地具有 __hash__ = None
,导致对象不可散列
在Python 2 :
User-defined classes have
__cmp__()
and__hash__()
methods by default; with them, all objects compare unequal (except with themselves) andx.__hash__()
returns a result derived fromid(x)
.
所以它是基于身份的散列,这是一个问题,因为它与你的 __eq__
不一致。这是 Python 3 切换行为的原因。
关于python - 哈希方法在 python 2 中是默认的,而不是 python 3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55753498/