如何消除Python3中等号运算符的弃用警告?

7 投票
2 回答
2451 浏览
提问于 2025-04-17 19:28

虽然标题看起来像是三个问题,但实际问题很简单。我的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 个回答

2

Alex: Python中的-3选项是在提醒你可能会遇到的问题;它并不知道你是否在集合中使用MyClass的实例或者把它作为映射的键,所以它会警告你,如果你真的这样做的话,可能会出现你依赖的东西无法正常工作。如果你并没有这样使用MyClass,那就忽略这个警告吧。这只是一个笨工具,帮助你发现潜在的问题;最终,你需要自己判断哪些警告是重要的。

如果你真的想要消除这个警告——或者说,如果一个类是可变的,你想确保它不会被用在集合中或者作为任何映射的键——那么在类的主体中简单地写上__hash__ = None(正如Sudipta所指出的)就可以了。因为None是不可调用的,这样就会让这个类的实例变得不可哈希。

    class MyClass (object):
        def __eq__(self, other): return self is other
        __hash__ = None
7

来自Python 3.4的文档

如果一个类没有定义__eq__()这个方法,那么它也不应该定义__hash__()这个操作;如果它定义了__eq__()但没有定义__hash__(),那么这个类的实例就不能用作可哈希集合中的元素。如果一个类定义了可变对象并且实现了__eq__()方法,那么它就不应该实现__hash__(),因为可哈希集合的实现要求键的哈希值是不可变的(如果对象的哈希值改变了,它就会被放到错误的哈希桶里)。

简单来说,你需要定义一个__hash()__函数。

问题是,对于用户自定义的类,__eq()____hash()__函数是自动定义的。

x.__hash__()会返回一个合适的值,这样x == y就意味着x is yhash(x) == hash(y)同时成立。

如果你只定义了__eq()__,那么__hash()__会被设置为返回None。这样你就会遇到问题。

如果你不想麻烦地去实现__hash()__,而且你确定你的对象永远不会被哈希,那么你可以直接声明__hash__ = None,这样就可以避免警告了。

撰写回答