wtfpython icon indicating copy to clipboard operation
wtfpython copied to clipboard

Deep Down, explain or remove example

Open merriam opened this issue 2 years ago • 4 comments

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 avatar Nov 17 '22 21:11 merriam

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().

merriam avatar Nov 18 '22 20:11 merriam

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 :)

satwikkansal avatar Nov 19 '22 11:11 satwikkansal

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

merriam avatar Nov 25 '22 20:11 merriam

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 :)

satwikkansal avatar Nov 27 '22 11:11 satwikkansal