虽然标题可以解释为三个问题,但实际问题很容易描述。在Linux系统上我安装了python 2.7.3,并希望收到有关python 3不兼容性的警告。因此,我的代码段(tester.py
)如下所示:
#!/usr/bin/python -3
class MyClass(object):
def __eq__(self, other):
return False
当我执行此代码片段(被认为只是为了显示问题,而不是我在项目中使用的实际代码段)时
./tester.py
我收到以下弃用警告:
./tester.py:3: DeprecationWarning: Overriding __eq__ blocks inheritance of __hash__ in 3.x
class MyClass(object):
我的问题:如何更改此代码段以消除警告,即使其与版本3兼容?我想以正确的方式实现相等运算符,而不仅仅是抑制警告或类似的东西。
答案 0 :(得分:5)
从Python 3.4的documentation页面:
如果某个类没有定义
__eq__()
方法,则它也不应定义__hash__()
操作;如果它定义__eq__()
但不定义__hash__()
,则其实例将不能用作可散列集合中的项目。如果一个类定义了可变对象并实现了__eq__()
方法,那么它不应该实现__hash__()
,因为hashable集合的实现要求键的哈希值是不可变的(如果对象的哈希值发生变化,它将会在错误的哈希桶中。)
基本上,您需要定义__hash()__
函数。
问题是对于用户定义的类,会自动定义__eq()__
和__hash()__
函数。
x.__hash__()
返回x == y
暗示的适当值x is y
和hash(x) == hash(y)
。
如果仅定义__eq()__
,则__hash()__
设置为返回None
。所以你会碰壁。
如果你不想打扰实现__hash()__
并且你肯定知道你的对象永远不会被散列,那么更简单的方法就是你明确声明__hash__ = None
来处理警告。
答案 1 :(得分:0)
Alex:python' s选项警告你一个潜在的问题;它并不知道你没有在集合中使用MyClass的实例或者在映射中使用MyClass的实例,所以它会警告你可能依赖的某些东西是不可行的,如果你的话。如果您没有这样使用MyClass,请忽略该警告。这是一个帮助你发现潜在问题的愚蠢工具;最后,你有望成为具有实际情报的人,以确定哪些警告确实很重要。
如果你真的关心抑制警告 - 或者,确实,如果一个类是可变的,你想确保不是在集合中使用或作为任何映射中的键 - 类体中的简单赋值__hash__ = None
(正如Sudipta指出的那样)应该为你做。由于None不可调用,这使得实例不可清除。
class MyClass (object):
def __eq__(self, other): return self is other
__hash__ = None