Clash Royale CLAN TAG#URR8PPP
How come I can add the boolean value False but not True in a set in Python?
I just started investigating the set data type in Python. For some reason, whenever I add the Boolean value of True to a set it doesn't appear. However, if I add False to a set it will become an element of the set. I was shocked when I googled this question that nothing came up.
example1 = {1, 2, 7, False}
example2 = {7, 2, 4, 1, True}
print(example1)
print(example2)
The output is:
{False, 1, 2, 7}
{1, 2, 4, 7}
true
false
print({0, False})
{True, 2, 4, 7}
__future__
id(1) == id(True)
False
True
bool
1
int
bool
==
bool
int
3 Answers
3
Because in Python 1 == True
and you have 1 in your set already.
1 == True
Imagine this example:
example1 = {0, False, None}
example2 = {1, True}
print(example1)
print(example2)
Will output:
{0, None}
{1}
First set has 0
and None
because 0 == False
but 0 != None
. With second set 1 == True
so True
isn't added to the set.
0
None
0 == False
0 != None
1 == True
True
1 == True
1 is not True
hash(1) == hash(True)
{1, True}
1
True
{True, 1}
True
True
False and True are equal to 0 and 1, respectively. They are distinct entities, yet the two equal values cannot both be in a set. This is clearly undesired behavior, yet it is not clear it can be fixed and still allow multiplying by a boolean value to work as documented.
IPython 6.2.1 -- An enhanced Interactive Python.
1 is True
Out[1]: False
{1,True}
Out[2]: {1}
{0,False}
Out[3]: {0}
{False, 0}
Out[4]: {False}
{True, 1}
Out[5]: {True}
Notice that depending on the order of putting them into the set, 1 will not be in the set if True is already in it, and True will not be in the set if 1 is already in it.
The reason that you are losing boolean values from a set
if they already contain 0
or 1
is because the following behavior...
set
0
1
>>> hash(1) == hash(True)
True
>>> hash(0) == hash(False)
True
>>> 1 == True
>>> True
>>> 0 == False
>>> True
...is guaranteed in Python 3.x.
Which means that you cannot have both in a set:
>>> set([True, 1])
{True}
>>> set([False, 0])
{False}
The hashes being equal is just as important as the objects being equal, because objects that are "equal" can produce different hashes and vice versa:
class Foo:
def __init__(self, x):
self.x = x
def __hash__(self):
return 1
def __eq__(self, other):
return self.x == other.x
class Bar:
def __init__(self, x):
self.x = x
def __hash__(self):
return 2
def __eq__(self, other):
return self.x == other.x
>>> x = Foo(3)
>>> y = Bar(3)
>>> x == y
True
>>> hash(x) == hash(y)
False
>>> set([x, y])
{<__main__.Bar at 0x56ed278>, <__main__.Foo at 0x5707390>}
You can also have a set
that contains items with the same hashes, if those items are not equal:
set
>>> hash('a')
-904409032991049157
>>> hash(-904409032991049157)
-904409032991049157
>>> hash('a') == hash(-904409032991049157)
True
>>> set(['a', -904409032991049157])
{-904409032991049157, 'a'}
This behavior is not guaranteed in Python 2.x, for the simple reason that True
and False
are not reserved keywords (this change was introduced in 3.x). You may reassign them (although better not to), so there is no reason that the same behavior must hold in Python 2.x:
True
False
>>> True = 5
>>> hash(True) == hash(1)
False
>>> set([1, True])
set([1, 5])
But don't let the fact that True
was replaced with 5
discourage you! We can abuse the representation of a class to make it appear as though True
really is in the set.
True
5
True
class Foo(object):
def __repr__(self):
return('True')
>>> True = Foo()
>>> set([1, True])
set([1, True])
Obviously the last couple code snippets are bad practice, and are only for demonstration. The main takeaway is that equal objects with the same hash cannot be contained in the same set
, and in Python 3.x, 1
and True
, and 0
and False
, will always have the same hash, and will always be equal.
set
1
True
0
False
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
If
true
is 1 andfalse
is 0, true is already in the set so it won't be added again.– daniu
yesterday