Почему я могу добавить логическое значение False, но не True в наборе в Python?

Я только начал исследовать заданный тип данных в Python. По какой-то причине всякий раз, когда я добавляю логическое значение True в набор, он не появляется. Однако, если я добавлю False в набор, он станет элементом набора. Я был потрясен, когда я задал этот вопрос, что ничего не вышло.

example1 = {1, 2, 7, False}
example2 = {7, 2, 4, 1, True}

print(example1)
print(example2)

Выход:

{False, 1, 2, 7}
{1, 2, 4, 7}

Ответ 1

Потому что в Python 1 == Truehash(1) == hash(True)), и у вас уже есть 1 в вашем наборе.

Представьте себе этот пример:

example1 = {0, False, None}
example2 = {1, True}

print(example1)
print(example2)

Вывод:

{0, None}
{1}

Первый набор имеет 0 и None потому что 0 == False но 0 != None. При втором наборе 1 == True поэтому True не добавляется в набор.

Ответ 2

Причина, по которой вы теряете логические значения из set если они уже содержат 0 или 1 состоит в следующем:

>>> hash(1) == hash(True)
True
>>> hash(0) == hash(False)
True
>>> 1 == True
>>> True
>>> 0 == False
>>> True

... гарантируется в Python 3.x.

Это означает, что вы не можете иметь оба в наборе:

>>> set([True, 1])
{True}
>>> set([False, 0])
{False}

Хэши, равные, так же важны, как и объекты, поскольку объекты, которые являются "равными", могут создавать разные хэши и наоборот:

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>}

Вы также можете иметь set, содержащий элементы с теми же хэшами, если эти элементы не равны:

>>> hash('a')
-904409032991049157
>>> hash(-904409032991049157)
-904409032991049157
>>> hash('a') == hash(-904409032991049157)
True
>>> set(['a', -904409032991049157])
{-904409032991049157, 'a'}

Такое поведение не гарантируется в Python 2.x по той простой причине, что True и False не являются зарезервированными ключевыми словами (это изменение было введено в 3.x). Вы можете переназначить их (хотя лучше не делать этого), поэтому нет оснований полагать, что такое же поведение должно выполняться в Python 2.x:

>>> True = 5
>>> hash(True) == hash(1)
False
>>> set([1, True])
set([1, 5])

Но не позволяйте факту, что True заменили на 5 препятствуйте вам! Мы можем злоупотреблять представлением класса, чтобы оно выглядело так, как будто True действительно находится в наборе:

class Foo(object):
    def __repr__(self):
        return('True')

>>> True = Foo()
>>> set([1, True])
set([1, True])

Очевидно, что последние пара фрагментов кода - это плохая практика, и они предназначены только для демонстрации. Основной вывод заключается в том, что равные объекты с одним и тем же хешем не могут содержаться в одном set, а в Python 3.x, 1 и True, 0 и False всегда будут иметь одинаковый хеш и всегда будут равны.

Ответ 3

False и True равны 0 и 1 соответственно. Они представляют собой разные объекты, но два равных значения не могут быть оба в наборе. Это явно нежелательное поведение, но не совсем ясно, что он может быть исправлен и по-прежнему позволяет умножать логическое значение на работу, как описано.

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}

Обратите внимание, что в зависимости от порядка размещения их в наборе 1 не будет в наборе, если True уже в нем, и True не будет в наборе, если 1 уже в нем.