Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deep Down, explain or remove example #301

Open
merriam opened this issue Nov 17, 2022 · 4 comments
Open

Deep Down, explain or remove example #301

merriam opened this issue Nov 17, 2022 · 4 comments

Comments

@merriam
Copy link

merriam commented Nov 17, 2022

This example:

    >>> hash(WTF()) == hash(WTF()) # hashes _should_ be different as well
    True
  1. Is not explained.
  2. Has result contrary to comment.
  3. May not be explainable.

It may not be explainable because the documentation of __hash__ is borked. It never discusses what a hash of an instance entails. It also adds the bizarre restriction to user defined hash and equality functions that "x==y implies ... x is y" so all custom hash functions and custom equality must incorporate id(self) and provide no more or less information than id(self) or cause issues as in "Disorder within Order".

The code snippet works simply because the WTF() on both sides of an equality are likely to have the same id (memory reuse). And that the hash happens to return the same value for the same instance type at the same location.

Consider this example showing that the contents are ignored:

    >>> hash(a)
    8768377079588
    >>> a.new_field = 42
    >>> hash(a)
    8768377079588

Therefore, I recommend removing this example and just relating to a later wtff. (f is for flying).

@merriam
Copy link
Author

merriam commented Nov 18, 2022

In retrospect, maybe the example could be expanded and explained.

>> class WTF(): pass
>> class More_WTF():
  ..    def __init__(i):
  ..         self.i = i
>> hash(WTF()) == hash(More_WTF(42))
True

The WTF() is created, used by hash(), then discarded. The memory location is then reused for More_WTF(). hash() on an instance hashes only its id().

@satwikkansal
Copy link
Owner

Thanks for starting the discussion, I think

  1. It's because of memory reuse, which is mentioned in the explanation.
  2. When you say the result is contrary, do you mean hash(WTF()) == hash(WTF()) returns False?
  3. I agree that the example set-up is contrived, and even overlaps with others, but it was done on purpose. If more people think that's not a constructive way, I can change that in the next revision. Otherwise, I do realise that the explanation can be improved so will do that anyway.
>> class WTF(): pass
>> class More_WTF():
  ..    def __init__(i):
  ..         self.i = i
>> hash(WTF()) == hash(More_WTF(42))
True

And yeah, I agree this is a simpler way to convey it, so I'll consider this too :)

@merriam
Copy link
Author

merriam commented Nov 25, 2022

Thank you for thinking about5 this.

The issues is 'equivalence'. By default, instances use is. To make them compare, you add an __eq__, which is supposed to implement a == b in such a way as:

  • a == a, a == b implies b == a, a ==b and b==c implies a == c. In Disorder within Order, you implement a "permissive equality" across types, where a ==b and b == c does NOT imply a == c. Once that rule breaks, sets and dictionaries fail to work.
  • I'm attaching a random file of examples I wrote while reading your great report. Share and enjoy!
    experiments1.py.zip

@satwikkansal
Copy link
Owner

a == a, a == b implies b == a, a ==b and b==c implies a == c. In Disorder within Order, you implement a "permissive equality" across types, where a ==b and b == c does NOT imply a == c. Once that rule breaks, sets and dictionaries fail to work.

I think thats's a good way to explain it.

Also, thanks for sharing your notes :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants