让我们定义一个非常简单的Test
类,它继承自int
:
TEST_DICT = {1: 'a', 2: 'b'}
class Test(int):
def __str__(self):
return TEST_DICT[self]
def __repr__(self):
return str(self)
if __name__ == '__main__':
print(Test(1))
这将按预期打印a
,即1
类Test
的代表。
现在,让我们重新定义__eq__
方法:
TEST_DICT = {1: 'a', 2: 'b'}
class Test(int):
def __str__(self):
return TEST_DICT[self]
def __repr__(self):
return str(self)
def __eq__(self, other):
if isinstance(other, int):
return self == other
if isinstance(other, str):
return str(self) == other
return False
if __name__ == '__main__':
print(Test(1))
然而,这导致以下追溯:
Traceback (most recent call last):
File "test.py", line 14, in <module>
print(Test(1))
File "test.py", line 4, in __str__
return TEST_DICT[self]
TypeError: unhashable type: 'Test'
有人可以解释为什么会发生这种情况,我怎么能避免这个错误,同时还能重新定义__eq__
方法?
答案 0 :(得分:3)
来自https://docs.python.org/2/reference/datamodel.html:
这里没有比较运算符之间的隐含关系。 x == y的真实性并不意味着x!= y是假的。因此,在定义 eq ()时,还应该定义 ne (),以便运算符按预期运行。有关创建支持自定义比较操作的可哈希对象的一些重要说明,请参阅哈希()上的段落。
和
如果某个类未定义 cmp ()或 eq ()方法,则不应定义哈希()操作; 如果它定义__cmp __()或__eq __()但不定义__hash __(),则它的实例将无法在散列集合中使用。如果类定义了可变对象并实现了 cmp ()或 eq ()方法,它不应该实现哈希(),因为hashable collection实现要求对象的哈希值是不可变的(如果对象的哈希值发生变化,它将在错误的哈希桶中。)
默认情况下,用户定义的类具有 cmp ()和哈希()方法;使用它们,所有对象都比较不相等(除了它们自己)和x。哈希()返回从id(x)派生的结果。
答案 1 :(得分:0)
感谢@DeepSpace提供有关数据模型文档的链接。
可能的实施,供参考:
TEST_DICT = {1: 'a', 2: 'b'}
class Test(int):
def __str__(self):
return TEST_DICT[int(self)]
def __repr__(self):
return str(self)
def __eq__(self, other):
if isinstance(other, int):
return int(self) == other
if isinstance(other, str):
return str(self) == other
return False
def __hash__(self):
return hash(int(self))
if __name__ == '__main__':
print(Test(1))
请注意int(self)
和__eq__()
中的转化__hash__()
,以避免无限递归。