Тип set – это разновидность коллекций, которая поддерживает оператор
проверки на вхождение in, функцию len() и относится к разряду
итерируемых объектов. Кроме того, множества предоставляют метод
set.isdisjoint() и поддерживают операторы сравнения и битовые
операторы (которые в контексте множеств используются для получения
объединения, пересечения и т. д.). В языке Python имеется два
встроенных типа множеств: изменяемый тип set и неизменяемый
frozenset. При переборе элементов множества элементы могут следовать
в произвольном порядке.
В состав множеств могут включаться только хешируемые
объекты. Хешируемые объекты – это объекты, имеющие специальный метод
__hash__(), на протяжении всего жизненного цикла объекта всегда
возвращающий одно и то же значение, которые могут участвовать в
операциях сравнения на равенство посредством специального метода
__eq__(). (Специальные методы – это методы, имена которых начинаются
и оканчиваются двумя символами подчеркивания).
Все встроенные неизменяемые типы данных, такие как float,
frozenset, int, str и tuple, являются хешируемыми объектами и
могут добавляться во множества. Встроенные изменяемые типы данных,
такие как dict, list и set, не являются хешируемыми объектами,
так как значение хеша в каждом конкретном случае зависит от
содержащихся в объекте элементов, поэтому они не могут добавляться в
множества.
Множества могут сравниваться между собой с использованием стандартных
операторов сравнения (<, <=, ==, !=, >=, >). Обратите
внимание: операторы == и != имеют обычный смысл, и сравнение
выполняется путем поэлементного сравнения (или рекурсивно при наличии
таких вложенных элементов, как кортежи и фиксированные множества
(frozenset)), но остальные операторы сравнения выполняют сравнение
подмножеств и надмножеств, как вскоре будет показано.
set
Тип set – это неупорядоченная коллекция из нуля или более ссылок на
объекты, указывающих на хешируемые объекты. Множества относятся к
категории изменяемых типов, поэтому легко можно добавлять и удалять их
элементы, но, так как они являются неупорядоченными коллекциями, к ним
не применимо понятие индекса и не применима операция извлечения
среза. На рис. 3 иллюстрируется множество,
созданное следующим фрагментом программного кода:
S = {7, "veil", 0, -29, ("x", 11), "sun", frozenset({8, 4, 7}), 913}
Рисунок 3: Множество – это неупорядоченная коллекция уникальных элементов

Тип данных set может вызываться как функция set() –
без аргументов она возвращает пустое множество; с аргументом типа
set возвращает поверхностную копию аргумента; в случае, если
аргумент имеет другой тип, выполняется попытка преобразовать его в
объект типа set. Эта функция принимает не более одного
аргумента. Кроме того, непустые множества могут создаваться без
использования функции set(), а пустые множества могут создаваться
только с помощью функции set() – их нельзя создать с помощью пары
пустых скобок. Множество, состоящее из одного или более элементов,
может быть создано с помощью последовательности элементов, разделенных
запятыми, заключенной в фигурные скобки. Другой способ создания
множеств заключается в использовании генераторов множеств. Множества
всегда содержат уникальные элементы – добавление повторяющихся
элементов возможно, но не имеет смысла. Например, следующие три
множества являются эквивалентными: set("apple"), set("aple") и
{'e', 'p', 'a', 'l'}. Благодаря этой их особенности множества часто
используются для устранения повторяющихся значений. Например, если
предположить, что x – это список строк, то после выполнения
инструкции x = list(set(x)) в списке останутся только уникальные
строки, причем располагаться они могут в произвольном порядке.
Рисунок 4: Стандартные операторы множеств

Множества поддерживают встроенную функцию len() и быструю проверку
на вхождение с помощью операторов in и not in. Они также предоставляют
типичный набор операторов, как показано на рис. .
Полный перечень методов и операторов, применимых к множествам,
приводится в табл. collections:sets:tbl:1. Все методы семейства
«update» (set.update(), set.intersection_update() и т. д.) могут принимать в качестве
аргумента любые итерируемые объекты, но эквивалентные им
комбинированные операторы присваивания (|=, &= и т. д.) требуют, чтобы
оба операнда были множествами.
Таблица 2. Методы и операторы множеств
| Синтаксис | Описание |
s.add(x) | Добавляет элементы x во множество s, если они отсутствуют в s |
s.clear() | Удаляет все элементы из множества s |
s.difference(t)или s-t | Возвращает новое множество включающее элементы множества s, которые отсутствуют в множестве t |
s.difference_update(t) или s-=t | Удаляет из множества s все элементы, присутствующие в множестве t |
s.discard(x) | Удаляет элемент x из множества s, если он присутствует в множестве s |
s.intersection(t) или s & t | Возвращает новое множество, включающее элементы, присутствующие одновременно в множествах s и t |
s.intersection_update(t) или s &= t | Оставляет во множестве s пересечение множеств s и t |
s.isdisjoint(t) | Возвращает True, если множества s и t не имеют общих элементов |
s.issubset(t) или s <= t | Возвращает True, если множество s эквивалентно множеству t или является его подмножеством; чтобы проверить, является ли множество s только подмножеством множества t, следует использовать проверку s < t |
s.issuperset(t) или s >= t | Возвращает True, если множество s эквивалентно множеству t или является его надмножеством; чтобы проверить, является ли множество s только надмножеством множества t, следует использовать проверку s > t |
s.pop() | Возвращает и удаляет случайный элемент множества s или возбуждает исключение KeyError, если s – это пустое множество |
s.remove(x) | Удаляет элемент x из множества s или возбуждает исключение KeyError, если элемент x отсутствует в множестве s |
s.symmetric_difference(t) или s ^ t | Возвращает новое множество, включающее все элементы, присутствующие в множествах s и t, за исключением элементов, присутствующих в обоих множествах одновременно |
s.symmetric_difference_update(t) или s ^= t | Возвращает в множестве s результат строгой дизъюнкции множеств s и t |
s.union(t) или s | t | Возвращает новое множество, включающее все элементы множества s и все элементы множества t, отсутствующие в множестве s |
s.update(t) или s |= t | Добавляет во множество s все элементы множества t, отсутствующие в множестве s |
В дополнение к возможности создавать множества с помощью функции
set() или литералов, существует возможность создавать множества с
помощью генераторов множеств. Генератор множества – это выражение и
цикл с необязательным условием, заключенные в фигурные скобки. Подобно
генераторам списков, генераторы множеств поддерживают две формы
записи:
{expression for item in iterable}
{expression for item in iterable if condition}
Мы могли бы использовать генераторы множеств для фильтрации нежелательных элементов (когда порядок следования элементов не имеет значения), как показано ниже:
html = {x for x in files if x.lower().endswith((".htm", ".html"))}
Если предположить, что files – это список имен файлов, то данный
генератор множества создает множество html, в котором хранятся
только имена файлов с расширениями .htm и .html, независимо от
регистра символов.
Как и в случае с генераторами списков, в генераторах множеств используются итерируемые объеты, которые в свою очередь могут быть генераторами множеств (или генераторами любого другого типа), что позволяет создавать весьма замысловатые генераторы множеств.
frozenset
Фиксированное множество (frozenset) – это множество, которое после
создания невозможно изменить. Хотя при этом мы, конечно, можем
повторно связать переменную, которая ссылалась на фиксированное
множество, с чем-то другим. Фиксированные множества могут создаваться
только в результате обращения к имени типа frozenset как к
функции. При вызове frozenset() без аргументов возвращается пустое
фиксированное множество; с аргументом типа frozenset возвращается
поверхностная копия аргумента; если аргумент имеет другой тип,
выполняется попытка преобразовать его в объект типа frozenset. Эта
функция принимает не более одного аргумента.
Поскольку фиксированные множества относятся к категории неизменяемых объектов, они поддерживают только те методы и операторы, которые воспроизводят результат, не оказывая воздействия на фиксированное множество или на множества, к которым они применяются.
Поскольку фиксированные множества относятся к категории неизменяемых
объектов, они поддерживают только те методы и операторы, которые
воспроизводят результат, не оказывая воздействия на фиксированное
множество или на множества, к которым они применяются.
В табл. collections:sets:tbl:1 перечислены все методы множеств из
которых фиксированными множествами поддерживаются: frozenset.copy(),
frozenset.difference() (-), frozenset.intersection() (&),
frozenset.isdis-joint(), frozenset.issubset() (<= и < для
выявления подмножеств), frozenset.issuperset() (>= и > для
выявления надмножеств), frozenset.union() (|) и
frozenset.symmetric_difference() (^).
Если двухместный оператор применяется ко множеству и фиксированному
множеству, тип результата будет совпадать с типом операнда, стоящего
слева от оператора. То есть если предположить, что f – это
фиксированное множество, а s – это обычное множество, то выражение
f & s вернет объект типа frozenset, а выражение s & f – объект
типа set. В случае операторов == и != порядок операндов не имеет
значения, и выражение f == s вернет True, только если оба
множества содержат одни и те же элементы.
Другое следствие неизменности фиксированных множеств заключается в том, что они соответствуют критерию хеширования, предъявляемому к элементам множеств, и потому множества и фиксированные множества могут содержать другие фиксированные множества.