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

标签 python hash

在将一些代码从 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 切换行为的原因。

关于python - 哈希方法在 python 2 中是默认的,而不是 python 3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55753498/

相关文章:

php - 确定以前在实现随机盐时是否使用过密码

python - 值错误: invalid literal for int() with base 16: 'Interstitial'

javascript - 如何将csrf_token传递给jqgrid的editurl的post参数?

python - 如何使用 Django 发送 iCalendar 电子邮件附件?

perl - 如何在 Perl 中将这些字符串转换为哈希?

memory - Redis内存优化建议

node.js - 在 nodejs scrypt 包中使用 Firebase SCrypt 参数

python - 适用于 Python 的 Twilio RequestValidator 始终返回 false

python - 屏幕命令和python

python - 使用 flask-bcrypt 生成和验证密码哈希