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