如何消除Python3中等号运算符的弃用警告?
虽然标题看起来像是三个问题,但实际问题很简单。我的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):
我的问题是:我该如何修改这个代码片段,以消除警告,也就是让它兼容python 3?我想正确地实现相等运算符,而不是仅仅压制警告或类似的做法。
2 个回答
Alex: Python中的-3选项是在提醒你可能会遇到的问题;它并不知道你是否在集合中使用MyClass的实例或者把它作为映射的键,所以它会警告你,如果你真的这样做的话,可能会出现你依赖的东西无法正常工作。如果你并没有这样使用MyClass,那就忽略这个警告吧。这只是一个笨工具,帮助你发现潜在的问题;最终,你需要自己判断哪些警告是重要的。
如果你真的想要消除这个警告——或者说,如果一个类是可变的,你想确保它不会被用在集合中或者作为任何映射的键——那么在类的主体中简单地写上__hash__ = None
(正如Sudipta所指出的)就可以了。因为None是不可调用的,这样就会让这个类的实例变得不可哈希。
class MyClass (object):
def __eq__(self, other): return self is other
__hash__ = None
来自Python 3.4的文档:
如果一个类没有定义
__eq__()
这个方法,那么它也不应该定义__hash__()
这个操作;如果它定义了__eq__()
但没有定义__hash__()
,那么这个类的实例就不能用作可哈希集合中的元素。如果一个类定义了可变对象并且实现了__eq__()
方法,那么它就不应该实现__hash__()
,因为可哈希集合的实现要求键的哈希值是不可变的(如果对象的哈希值改变了,它就会被放到错误的哈希桶里)。
简单来说,你需要定义一个__hash()__
函数。
问题是,对于用户自定义的类,__eq()__
和__hash()__
函数是自动定义的。
x.__hash__()
会返回一个合适的值,这样x == y
就意味着x is y
和hash(x) == hash(y)
同时成立。
如果你只定义了__eq()__
,那么__hash()__
会被设置为返回None
。这样你就会遇到问题。
如果你不想麻烦地去实现__hash()__
,而且你确定你的对象永远不会被哈希,那么你可以直接声明__hash__ = None
,这样就可以避免警告了。