I have recently started to learn Python and have encountered something a little strange when playing with sets. The following code sample doesn't produce the expected results.
a_set = {True,2,3,4}
a_set.add(1)
I expected a_set to have the values {True, 1, 2, 3, 4}
but instead this code produced {True, 2, 3, 4}
.
Trying variations on this also produced the same results:
a_set = {1,2,3,4}
a_set.add(True)
Expected {True, 1, 2, 3, 4}
Actual {1, 2, 3, 4}
Trying this with False
and 0
obtained the same results:
a_set = {False,2,3,4}
a_set.add(0)
Expected {False, 0, 2, 3, 4}
Actual {False, 2, 3, 4}
a_set = {0,2,3,4}
a_set.add(False)
Expected {False, 0, 2, 3, 4}
Actual {0, 2, 3, 4}
I understand that the bool
type is inherited from int
and that True == 1
and False == 0
but was still a little surprised by the above results.
Does anybody know if this behaviour is by design? Also is it possible to have a set which contains both True
, False
, 0
, and 1
?
I did perform quite a bit of googling but was not able to find an answer to my questions.
Thanks in advance
In response to the comments below I agree that the following question partially answers my question.
Is False == 0 and True == 1 in Python an implementation detail or is it guaranteed by the language?
But I feel that it doesn't answer the query I have regarding the behaviour of sets and whether it is possible to have a set containing both True
and 1
. Even though bool
is inherited from int
, they are different types, so I found the fact that a set cannot distinguish between True
and 1
to be a little confusing. So really this is a question about the behaviour of sets in Python not just about True == 1
.
For historical (hysterical?) reasons Python's bool
type is a subclass of int
, and True
is equal to 1 and False
is equal to 0.
They hash to the same location as well:
>>> True == 1
True
>>> hash(True) == hash(1)
True
>>> False == 0
True
>>> hash(False) == hash(0)
True
Since both True
and 1
are considered equal and they hash to the same slot, both set
and dict
treat them as the same thing.
You'll see the same with a dictionary:
>>> True in {1: 'foo'}
True
>>> 1 in {True: 'foo'}
True
This behaviour extends to other numbers too; floating point values equal to integer values will show the same behaviour:
>>> {1.0, 1, 2.0, 2}
{1, 2}
but at least the reasons why that happens are a little more.. obvious.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With