Skip to main content
 首页 » 编程设计

python之哈希方法在 python 2 中是默认的,而不是 python 3

2025年05月04日20cyq1162

在将一些代码从 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) and x.__hash__() returns an appropriate value such that x == y implies both that x is y and hash(x) == hash(y).

A class that overrides __eq__() and does not define __hash__() will have its __hash__() implicitly set to None. When the __hash__() method of a class is None, 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 checking isinstance(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) and x.__hash__() returns a result derived from id(x).

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