Почему я могу добавить логическое значение 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 == True
(и hash(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 уже в нем.