7

虽然标题可以理解为三个问题,但实际问题描述起来很简单。在 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 兼容?我想以正确的方式实现相等运算符,而不仅仅是抑制警告或类似的东西。

4

2 回答 2

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()__设置为 return None。所以你会碰壁。

如果您不想费心实现__hash()__并且您确定您的对象永远不会被散列,那么更简单的方法是,您只需明确声明__hash__ = None哪个负责警告。

于 2013-03-18T07:09:41.740 回答
2

Alex:python 的 -3 选项警告你一个潜在的问题;它不知道您没有在集合中使用 MyClass 的实例或作为映射中的键,因此它会警告您可能一直依赖的东西不会起作用,如果您是的话。如果您没有以这种方式使用 MyClass,请忽略该警告。这是一个帮助您发现潜在问题的愚蠢工具;最后,您应该是具有实际智慧的人来确定哪些警告实际上很重要。

如果你真的关心抑制警告——或者,事实上,如果一个类是可变的,并且你想确保它没有在集合中使用或作为任何映射中的键——简单的赋值__hash__ = None(如 Sudipta 指出的)在班级机构将为您做到这一点。由于 None 不可调用,这使得实例不可散列。

    class MyClass (object):
        def __eq__(self, other): return self is other
        __hash__ = None
于 2014-12-14T20:55:12.350 回答