Hashability в Python: почему set.add(set(...)) вызывает TypeError
@python_quizРазберем этот квиз
Кратко: в Python элементы множества (set) должны быть хешируемыми (immutable с реализованным __hash__). frozenset и кортеж — хешируемы, обычный set — нет. Попытка добавить изменяемый set вызовет TypeError, при этом ранее добавленные элементы останутся в множестве.
Условие (фрагмент кода)

По шагам — что происходит
s = set() — создаём пустое множество.- s.add(frozenset([1,2])) — frozenset неизменяем и хешируем, добавляется успешно.
- s.add((3,4)) — кортеж неизменяем и хешируем, добавляется успешно.
- s.add(set([3,4])) — попытка добавить обычный set, который изменяем и не хешируется; Python выбросит
TypeError: unhashable type: 'set'. Исключение прервёт выполнение на этой строке.
Важно: исключение не откатывает предыдущие успешные добавления — s будет содержать два первых элемента.
Демонстрация (поведение в Python)

Проверка хешируемости:

Альтернативы и обходные пути
- Если нужно хранить множество как элемент множества — используйте frozenset:
`python
s.add(frozenset([3,4]))
`
- Можно конвертировать в кортеж, если порядок не критичен:
`python
s.add(tuple([3,4]))
`
- Если хочется хранить изменяемые коллекции в качестве элементов — можно использовать список словарей/списков, но не в set; вместо этого применять структуры данных, которые допускают такие элементы (например список элементов, где элементы могут быть любыми).
Анализ вариантов (коротко)
- Вариант, утверждающий, что frozenset и кортеж добавятся, а всё выполнится без ошибок — неверен, потому что третья операция вызывает исключение.
- Вариант с
TypeError: unhashable type: 'set' при попытке добавить изменяемый set — описывает реальное поведение. - Утверждение, что после исключения множество останется пустым — неверно: первые два добавления уже произошли.
- Утверждение про
TypeErrorна frozenset — неверно, потому что frozenset хешируем.
Вывод
В множества Python можно добавлять только хешируемые (обычно неизменяемые) объекты: frozenset и tuple — подходят, обычный set — нет. При попытке добавить изменяемый set возникнет TypeError, но ранее добавленные элементы сохранятся. Чтобы хранить "множество внутри множества", либо используйте frozenset, либо конвертируйте во что-то хешируемое.