python 2中默认使用哈希方法,而不是python 3中默认 [英] Hash method is defaulted in python 2, not python 3

查看:117
本文介绍了python 2中默认使用哈希方法,而不是python 3中默认的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将某些代码从python 2转换为python 3时,我遇到了一个奇怪的行为示例.以下是它的一个最小(?)示例:

I've come across an example of weird behavior when transitioning some code from python 2 to python 3. Below's a minimal (?) example of it:


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'

when run with python2, this code produces some output (a hash of Bar(1)), while python3 causes a TypeError: unhashable type: 'Bar'

这意味着__hash__是在python 2中以某种方式继承的(从object吗?).

this means that __hash__ is somehow inherited (from object ?) in python 2.

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

So, my questions are: what is the hash of Bar(1) in python 2? And why is the behaviour different?

推荐答案

是的,数据模型已更改. 在Python 3中:

Yes, the data model has changed. In Python 3:

用户定义的类具有__eq__()__hash__()方法 默认;与他们,所有对象比较不相等(除了与 本身)和x.__hash__()返回适当的值,使得 x == y表示x is yhash(x) == hash(y).

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).

覆盖__eq__()并且未定义__hash__()的类将其__hash__()隐式设置为None .当...的时候 类的__hash__()方法是None,当程序尝试检索时,该类的实例将引发适当的TypeError. 它们的哈希值,也将正确地标识为不可哈希 检查isinstance(obj, collections.abc.Hashable)时.

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,从而导致这些对象不可散列

So, since you've defined a __eq__ explicitely, but did not define a __hash__, Python 3 objects will implicitely have __hash__ = None, causing the objects to be unhashable

Python 2 中:

用户定义的类具有__cmp__()__hash__()方法 默认;与他们,所有对象比较不相等(除了与 本身)和x.__hash__()返回从id(x)派生的结果.

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切换行为的原因.

So it is hashing based on identity, which is a problem, because it isn't consistent with your __eq__. This is a reason that Python 3 switched behaviors.

这篇关于python 2中默认使用哈希方法,而不是python 3中默认的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆