问题
Although the title can be interpreted as three questions, the actual problem is simple to describe. On a Linux system I have python 2.7.3 installed, and want to be warned about python 3 incompatibilities. Therefore, my code snippet (tester.py
) looks like:
#!/usr/bin/python -3
class MyClass(object):
def __eq__(self, other):
return False
When I execute this code snippet (thought to be only to show the problem, not an actual piece of code I am using in my project) as
./tester.py
I get the following deprecation warning:
./tester.py:3: DeprecationWarning: Overriding __eq__ blocks inheritance of __hash__ in 3.x
class MyClass(object):
My question: How do I change this code snippet to get rid of the warning, i.e. to make it compatible to version 3? I want to implement the equality operator in the correct way, not just suppressing the warning or something similar.
回答1:
From the documentation page for Python 3.4:
If a class does not define an
__eq__()
method it should not define a__hash__()
operation either; if it defines__eq__()
but not__hash__()
, its instances will not be usable as items in hashable collections. If a class defines mutable objects and implements an__eq__()
method, it should not implement__hash__()
, since the implementation of hashable collections requires that a key’s hash value is immutable (if the object’s hash value changes, it will be in the wrong hash bucket).
Basically, you need to define a __hash()__
function.
The problem is that for user-defined classes, the __eq()__
and __hash()__
functions are automatically defined.
x.__hash__()
returns an appropriate value such thatx == y
implies both thatx is y
andhash(x) == hash(y)
.
If you define just the __eq()__
, then __hash()__
is set to return None
. So you will hit the wall.
The simpler way out if you don't want to bother about implementing the __hash()__
and you know for certain that your object will never be hashed, you just explicitly declare __hash__ = None
which takes care of the warning.
回答2:
Alex: python's -3 option is warning you about a potential problem; it doesn't know that you aren't using instances of MyClass in sets or as keys in mappings, so it warns that something that you might have been relying on wouldn't work, if you were. If you aren't using MyClass that way, just ignore the warning. It's a dumb tool to help you catch potential problems; in the end, you're expected to be the one with the actual intelligence to work out which warnings actually matter.
If you really care about suppressing the warning - or, indeed, if a class is mutable and you want to make sure it isn't used in sets or as the key in any mapping - the simple assignment __hash__ = None
(as Sudipta pointed out) in the class body shall do that for you. Since None isn't callable, this makes instances non-hashable.
class MyClass (object):
def __eq__(self, other): return self is other
__hash__ = None
来源:https://stackoverflow.com/questions/15471333/how-to-eliminate-a-python3-deprecation-warning-for-the-equality-operator