On Tue, Sep 14, 2021 at 11:30 PM
I think I implemented __eq__ but not __hash__ and it broke the golden rule of x == y => x is y i,.e. hash(x) == hash(y)
Not sure what you're referring to there. The rule regarding hashes is that if x == y, then hash(x) == hash(y). Identity doesn't come into it, other than in the trivial sense that, for most classes, hash(x) == hash(x) (in other words, the hash is stable), and x == x, which complies with the rule. But if x != x (eg with float("nan")), there's no problem. Incidentally, I don't think it's documented, but an object's hash should never change. Otherwise, you can get bizarre behaviours:
class X: ... def __init__(self, value): self.thing = value ... def __eq__(self, other): return self.thing == other.thing ... def __hash__(self): return hash(self.thing) ... stuff = {X(5): "hello", X(7): "world"} stuff[X(5)] 'hello'
Well and good. But if we mutate the key...
list(stuff)[0].thing = 2 for key in stuff: ... print(key, stuff[key]) ... Traceback (most recent call last): File "<stdin>", line 2, in <module> KeyError: <__main__.X object at 0x7f1420409180>
... we can iterate over the keys in the dictionary, use that exact object to subscript the dictionary, and it isn't found. That key/value pair has been placed in the bucket for 5, and won't be found in 2's bucket. If equality can change, __hash__ should be omitted. ChrisA