问题描述
在将某些代码从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__()
的类将其__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 中:
因此它是基于身份的哈希,这是一个问题,因为它与您的__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中默认的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!