Союз из 2 наборов не содержит всех предметов

Как получилось, когда я изменяю порядок двух наборов в союзах ниже, я получаю разные результаты?

set1 = {1, 2, 3}
set2 = {True, False}

print(set1 | set2)
# {False, 1, 2, 3}

print(set2 | set1)
#{False, True, 2, 3}

Ответ 1

Почему union() не содержит всех элементов

1 и True эквивалентны и считаются дублирующими. Аналогично 0 и False также эквивалентны:

>>> 1 == True
True
>>> 0 == False
True

Какое эквивалентное значение используется

Когда встречается несколько эквивалентных значений, наборы сохраняют первый вид:

>>> {0, False}
{0}
>>> {False, 0}
{False}

Способы различения значений

Чтобы заставить их обрабатываться как разные, просто сохраните их в паре (value, type):

>>> set1 = {(1, int), (2, int), (3, int)}
>>> set2 = {(True, bool), (False, bool)}
>>> set1 | set2
{(3, <class 'int'>), (1, <class 'int'>), (2, <class 'int'>),
 (True, <class 'bool'>), (False, <class 'bool'>)}
>>> set1 & set2
set()

Другой способ сделать значения различными - хранить их как строки:

>>> set1 = {'1', '2', '3'}
>>> set2 = {'True', 'False'}
>>> set1 | set2
{'2', '3', 'False', 'True', '1'}
>>> set1 & set2
set()

Надеюсь, что это очистит тайну и покажет путь вперед: -)


Спасено из комментариев:

Это стандартная методика для разграничения межсимвольной эквивалентности (т.е. 0.0 == 0, True == 1 и Decimal(8.5) == 8.5)). Этот метод используется в модуле регулярного выражения Python 2.7, чтобы принудительно кэшировать регулярные выражения unicode из другого эквивалента str regexes. Этот метод также используется в Python 3 для functools.lru_cache(), когда типизированный параметр имеет значение true.

Если OP нуждается в чем-то отличном от отношения эквивалентности по умолчанию, тогда необходимо определить какое-то новое отношение. В зависимости от варианта использования, это может быть нечувствительность к регистру для строк, нормализация для юникода, внешний вид (вещи, которые выглядят по-разному, считаются разными), идентичность (без двух разных объектов считаются равными), пара значений/типа или некоторые другие функция, которая определяет отношение эквивалентности. Учитывая конкретный пример ОП, казалось бы, он ожидал либо различия по типу, либо визуальному различию.

Ответ 2

В Python False и 0 считаются эквивалентными, как и True и 1. Поскольку True и 1 считаются одинаковыми, только одно из них может присутствовать в наборе a в одно и то же время. Какой из них зависит от порядка, в который они добавляются в набор. В первой строке set1 используется как первый набор, поэтому мы получаем 1 в результирующем наборе. Во втором наборе True находится в первом наборе, поэтому True включен в результат.

Ответ 3

Если вы посмотрите https://docs.python.org/3/library/stdtypes.html#boolean-values раздел 4.12.10. Булевы значения:

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

Ответ 4

Оператор сравнения (==, !=) определяется для boolean True и False для соответствия 1 и 0.

Итак, в объединении set, когда он проверяет, есть ли True в новом наборе уже, он получает правдивый ответ:

>>> True in {1}
True
>>> 1 in {True}
True