Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #197793 > unrolled thread

Python __hash__ return value - what use is it?

Started byVeek M <veekjunk@foobar.com>
First post2026-05-31 08:28 +0000
Last post2026-05-31 13:06 +0000
Articles 5 — 4 participants

Back to article view | Back to comp.lang.python


Contents

  Python __hash__ return value - what use is it? Veek M <veekjunk@foobar.com> - 2026-05-31 08:28 +0000
    Re: Python __hash__ return value - what use is it? Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-05-31 09:25 +0000
      Re: Python __hash__ return value - what use is it? Veek M <veekjunk@foobar.com> - 2026-05-31 10:13 +0000
    Re: Python __hash__ return value - what use is it? ram@zedat.fu-berlin.de (Stefan Ram) - 2026-05-31 09:40 +0000
    Re: Python __hash__ return value - what use is it? Jon Ribbens <jon+usenet@unequivocal.eu> - 2026-05-31 13:06 +0000

#197793 — Python __hash__ return value - what use is it?

FromVeek M <veekjunk@foobar.com>
Date2026-05-31 08:28 +0000
SubjectPython __hash__ return value - what use is it?
Message-ID<10vgrfu$1dchl$1@dont-email.me>
1. So I am returning 1 for every instance of MyClass and then inserting 
the instances into a set. However when I print the set I see individual 
instances though I want the instances to be the treated the same .ie there 
should be just one instance in the set because the return value from 
__hash__ is always 1.

In the dictionary when I print it I see the instances as individual keys 
though I want to see a single key - what gives?? Why is the return value 
of __hash__ being ignored?? (I can see it's being called)

2. When is __eq__ used? If I have two instances and want to make them 
equal - what's the use case?

#!/usr/bin/python

class MyClass:
    def __bool__(self):
        print('in __bool__')
        return True

    def __hash__(self):
        # hash value is not a key
        print('in __hash__')
        return 1

    def __eq__(self, val):
        print('in __eq__', val)
        return True

c = MyClass()
d = MyClass()

if c:
    print("true")

print('-----')
s = set()
s.add(c)
s.add(d)
print(s)

print('-----')
d = { c : "10", d : "20"  }
print(d)

[toc] | [next] | [standalone]


#197794

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-05-31 09:25 +0000
Message-ID<10vguqb$1ecdn$1@dont-email.me>
In reply to#197793
On Sun, 31 May 2026 08:28:46 -0000 (UTC), Veek M wrote:

> However when I print the set I see individual instances though I
> want the instances to be the treated the same .ie there should be
> just one instance in the set because the return value from __hash__
> is always 1.
>
> In the dictionary when I print it I see the instances as individual
> keys though I want to see a single key - what gives??

Just tried your code in a Jupyter notebook under Python 3.13.12, and
this was the output:

    in __bool__
    true
    -----
    in __hash__
    in __hash__
    in __eq__ <__main__.MyClass object at 0x7f68a86a4410>
    {<__main__.MyClass object at 0x7f68a8691400>}
    -----
    in __hash__
    in __hash__
    in __eq__ <__main__.MyClass object at 0x7f68a86a4410>
    {<__main__.MyClass object at 0x7f68a8691400>: '20'}

As you expected, only a single element in the set, and only a single
entry in the dict.

[toc] | [prev] | [next] | [standalone]


#197796

FromVeek M <veekjunk@foobar.com>
Date2026-05-31 10:13 +0000
Message-ID<10vh1kq$1f26j$1@dont-email.me>
In reply to#197794
On Sun, 31 May 2026 09:25:32 -0000 (UTC), Lawrence D’Oliveiro wrote:

> On Sun, 31 May 2026 08:28:46 -0000 (UTC), Veek M wrote:
> 
>> However when I print the set I see individual instances though I want
>> the instances to be the treated the same .ie there should be just one
>> instance in the set because the return value from __hash__
>> is always 1.
>>
>> In the dictionary when I print it I see the instances as individual
>> keys though I want to see a single key - what gives??
> 
> Just tried your code in a Jupyter notebook under Python 3.13.12, and
> this was the output:
> 
>     in __bool__
>     true -----
>     in __hash__
>     in __hash__
>     in __eq__ <__main__.MyClass object at 0x7f68a86a4410>
>     {<__main__.MyClass object at 0x7f68a8691400>}
>     -----
>     in __hash__
>     in __hash__
>     in __eq__ <__main__.MyClass object at 0x7f68a86a4410>
>     {<__main__.MyClass object at 0x7f68a8691400>: '20'}
> 
> As you expected, only a single element in the set, and only a single
> entry in the dict.

Oh. hmm - sorry - I guess I misread the output - I was under the 
impression there were two instances. Should have used len to check though.

[toc] | [prev] | [next] | [standalone]


#197795

Fromram@zedat.fu-berlin.de (Stefan Ram)
Date2026-05-31 09:40 +0000
Message-ID<hash-20260531103449@ram.dialup.fu-berlin.de>
In reply to#197793
Veek M <veekjunk@foobar.com> wrote or quoted:
>the instances into a set. However when I print the set I see individual 
>instances though I want the instances to be the treated the same .ie there 
>should be just one instance in the set because the return value from 
>__hash__ is always 1.

  I used the code below, where I added statements to print lengths,
  and all lengths printed are always "1" for me.

  Python Code

#!/usr/bin/python

class MyClass:
    def __bool__(self):
        print('in __bool__')
        return True

    def __hash__(self):
        # hash value is not a key
        print('in __hash__')
        return 1

    def __eq__(self, val):
        print('in __eq__', val)
        return True

c = MyClass()
d = MyClass()

if c:
    print("true")

print('-----')
s = set()
s.add(c); print( "len( s )= ", len( s ))
s.add(d); print( "len( s )= ", len( s ))
print(s)

print('-----')
d = { c : "10", d : "20"  }
print( "len( d )= ", len( d ))
print(d)

  Python Output (abbreviated at "...")

in __bool__
true
-----
in __hash__
len( s )=  1
in __hash__
in __eq__ <__main__.MyClass object at ...>
len( s )=  1
{<__main__.MyClass object at ...>}
-----
in __hash__
in __hash__
in __eq__ <__main__.MyClass object at ...>
len( d )=  1
{<__main__.MyClass object at ...>: '20'}

[toc] | [prev] | [next] | [standalone]


#197797

FromJon Ribbens <jon+usenet@unequivocal.eu>
Date2026-05-31 13:06 +0000
Message-ID<slrn111ocj0.4cm2.jon+usenet@raven.unequivocal.eu>
In reply to#197793
On 2026-05-31, Veek M <veekjunk@foobar.com> wrote:
> 1. So I am returning 1 for every instance of MyClass and then inserting 
> the instances into a set. However when I print the set I see individual 
> instances though I want the instances to be the treated the same .ie there 
> should be just one instance in the set because the return value from 
> __hash__ is always 1.

That doesn't follow. As others have already said, you do indeed
have only one item in the set. But that's not becuase __hash__
is returning the same value every time - or at least, not only
because of that. If __eq__ was not returning True, then you would
get 2 items in the set, regardless of what __hash__ was returning.

If two items are "equal" then their hashes must be the same. If they
are not equal then their hashes do not need to be different. The hash
is just for efficiency. Imagine you had a set of 1MB strings - you
wouldn't want to have to compare each 1MB string with every other
1MB string when deciding whether a new string is different or not.
So you compare the hashes, and then only if the hashes are the same
do you compare the strings themselves.

In short: if you make a class which returns the same __hash__ for
every object, you won't change its behaviour, you will just make it
(much) slower when used in things like sets and dictionaries.

> 2. When is __eq__ used? If I have two instances and want to make them 
> equal - what's the use case?

So "x == y" returns the result you want it to?

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web