在将一些代码从 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 == yimplies both thatx is yandhash(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 切换行为的原因。
