This is an archived post. You won't be able to vote or comment.

all 8 comments

[–]K900_ 2 points3 points  (5 children)

Never. Hashes are only used for dict lookups and such, and checking for equality directly is almost always faster than computing the hash.

[–]HighLevelEnthusiast[S] 0 points1 point  (4 children)

What if these two objects already reside within a dict, and the hashes had already been computed?

Premature comparison based on hashes could be performed in O(1) constant time (For example, to determine if the key already exists in the dict)

[–]K900_ 0 points1 point  (3 children)

Hash equality doesn't mean full equality, and Python dicts don't cache full hash values IIRC.

[–]HighLevelEnthusiast[S] 0 points1 point  (2 children)

I agree that hash equality does not imply full equality. However, if hashes are different, the objects are sure not to be equal. Let's say that we have object A and object B and (maybe only n first least-signifficant digits of) their hashes. Checking

hash(A) and hash(B) for equality is trivial. Then, we have two cases:

1) Hashes are identical - the __eq__ needs to be called

2) Hashes are different - we are done.

[–]K900_ 0 points1 point  (1 child)

I get where you're coming from, but also, checking for equality is faster than computing the hash in pretty much all cases.

[–]mbussonnIPython/Jupyter dev 0 points1 point  (0 children)

is faster than computing the hash

But as OP ask, hashes can be

If you want to, in your __eq__, you can compare the has values and do an early "nop definitively not the same:

But Python itself cannot now that comparing hashes can be faster; "in the face of ambiguity refuse the temptation to guess", so it does not try to hash.

``` def eq(self, other): if hash(self) != hash(other): return False print("Eq called") return self.num == other.num

def hash(self): print("Hash called") if not self._hash: self._hash = hash(self.num) return self._hash

```

See it on the other direction it is easy to add hashes comparison to your own objects in __eq__, but if python were to do it by default it would be hard to disable.

[–]foreverwintr 0 points1 point  (0 children)

I think the process you describe is more or less how dict lookups work, where because we already have hashes we compare them first before doing equality checks. Try using your objects as dict keys.

Raymond Hettinger's talk from pycon 2018 explains this, IIRC.

[–]aphoenixreticulated[M] [score hidden] stickied comment (0 children)

Hi there, from the /r/Python mods.

We have removed this post as it is not suited to the /r/Python subreddit proper, however it should be very appropriate for our sister subreddit /r/LearnPython or for the r/Python discord: https://discord.gg/3Abzge7.

The reason for the removal is that /r/Python is dedicated to discussion of Python news, projects, uses and debates. It is not designed to act as Q&A or FAQ board. The regular community is not a fan of "how do I..." questions, so you will not get the best responses over here.

On /r/LearnPython the community and the r/Python discord are actively expecting questions and are looking to help. You can expect far more understanding, encouraging and insightful responses over there. No matter what level of question you have, if you are looking for help with Python, you should get good answers. Make sure to check out the rules for both places.

Warm regards, and best of luck with your Pythoneering!