Документация Python неофициальный перевод
Содержание страницы

8.7. sets – Неупорядоченные коллекции уникальных элементовsets – Unordered collections of unique elements

Новое в версии 2.3.

Устарело с версии 2.6: Встроенные типы set/frozenset заменяют этот модуль.

Модуль sets предоставляет классы для создания и работы с неупорядоченными коллекциями уникальных элементов. Обычно используется для проверки принадлежности, удаления дубликатов из последовательности и выполнения стандартных математических операций над множествами, таких как пересечение, объединение, разность и симметрическая разность.

Как и другие коллекции, множества поддерживают x in set, len(set) и for x in set. Будучи неупорядоченной коллекцией, множество не запоминает положение элементов или порядок вставки. Поэтому множества не поддерживают индексацию, срезы и другое поведение, свойственное последовательностям.

Большинство приложений, работающих с множествами, используют класс Set, который предоставляет все методы множества, кроме __hash__(). Для более сложных приложений, требующих хеш-функцию, класс ImmutableSet добавляет метод __hash__(), но опускает методы, изменяющие содержимое множества. Оба класса Set и ImmutableSet являются производными от BaseSet, абстрактного класса, полезного для определения, является ли объект множеством: isinstance(obj, BaseSet).

Классы множеств реализованы с использованием словарей. Соответственно, требования к элементам множеств такие же, как к ключам словарей: а именно, элемент должен определять как __eq__(), так и __hash__(). В результате множества не могут содержать изменяемые элементы, такие как списки или словари. Однако они могут содержать неизменяемые коллекции, например кортежи или экземпляры ImmutableSet. Для удобства реализации множеств из множеств внутренние множества автоматически преобразуются в неизменяемую форму, например, Set([Set(['dog'])]) преобразуется в Set([ImmutableSet(['dog'])]).

class sets.Set([iterable])

Создаёт новый пустой объект Set. Если указан необязательный параметр iterable, обновляет множество элементами, полученными при итерации. Все элементы в iterable должны быть неизменяемыми или преобразуемыми в неизменяемые с помощью протокола, описанного в разделе Протокол автоматического преобразования в неизменяемые.

class sets.ImmutableSet([iterable])

Создаёт новый пустой объект ImmutableSet. Если указан необязательный параметр iterable, обновляет множество элементами, полученными при итерации. Все элементы в iterable должны быть неизменяемыми или преобразуемыми в неизменяемые с помощью протокола, описанного в разделе Протокол автоматического преобразования в неизменяемые.

Поскольку объекты ImmutableSet предоставляют метод __hash__(), они могут использоваться как элементы множества или как ключи словаря. Объекты ImmutableSet не имеют методов для добавления или удаления элементов, поэтому все элементы должны быть известны на момент вызова конструктора.

8.7.1. Объекты множествSet Objects

Экземпляры Set и ImmutableSet предоставляют следующие операции:

Операция

Эквивалентно

Результат

len(s)

количество элементов в множестве s (мощность)

x in s

проверить принадлежность x множеству s

x not in s

проверить, что x не принадлежит множеству s

s.issubset(t)

s <= t

проверить, что каждый элемент s принадлежит t

s.issuperset(t)

s >= t

проверить, что каждый элемент t принадлежит s

s.union(t)

s | t

новое множество с элементами из обоих s и t

s.intersection(t)

s & t

новое множество с элементами, общими для s и t

s.difference(t)

s - t

новое множество с элементами из s, не входящими в t

s.symmetric_difference(t)

s ^ t

новое множество с элементами, входящими либо в s, либо в t, но не в оба

s.copy()

новое множество с поверхностной копией s

Обратите внимание: неоператорные версии union(), intersection(), difference() и symmetric_difference() принимают любой итерируемый объект в качестве аргумента. В отличие от них, операторные аналоги требуют, чтобы их аргументы были множествами. Это исключает подверженные ошибкам конструкции вроде Set('abc') & 'cbs' в пользу более читаемых Set('abc').intersection('cbs').

Изменено в версии 2.3.1: Ранее все аргументы должны были быть множествами.

Кроме того, оба типа Set и ImmutableSet поддерживают сравнение множеств. Два множества равны тогда и только тогда, когда каждый элемент одного множества содержится в другом (каждое является подмножеством другого). Множество меньше другого множества тогда и только тогда, когда первое множество является строгим подмножеством второго (является подмножеством, но не равным). Множество больше другого множества тогда и только тогда, когда первое множество является строгим надмножеством второго (является надмножеством, но не равным).

Сравнения на подмножество и равенство не обобщаются до функции полного упорядочения. Например, любые два непересекающихся множества не равны и не являются подмножествами друг друга, поэтому все следующие выражения возвращают False: a<b, a==b, или a>b. Соответственно, множества не реализуют метод __cmp__().

Поскольку множества определяют лишь частичное упорядочение (отношения подмножеств), результат метода list.sort() для списков множеств не определён.

В следующей таблице перечислены операции, доступные в ImmutableSet, но отсутствующие в Set:

Операция

Результат

hash(s)

возвращает хеш-значение для s

В следующей таблице перечислены операции, доступные в Set, но отсутствующие в ImmutableSet:

Операция

Эквивалентно

Результат

s.update(t)

s |= t

возвращает множество s с элементами, добавленными из t

s.intersection_update(t)

s &= t

возвращает множество s, сохраняя только eлементы, также найденные в t

s.difference_update(t)

s -= t

возвращает множество s после удаления eлементов, найденных в t

s.symmetric_difference_update(t)

s ^= t

возвращает множество s с элементами из s или t, но не из обоих

s.add(x)

добавляет элемент x в множество s

s.remove(x)

удаляет x из множества s; вызывает KeyError, если отсутствует

s.discard(x)

удаляет x из множества s, если присутствует

s.pop()

удаляет и возвращает произвольный element из s; вызывает KeyError, если пусто

s.clear()

удаляет все элементы из множества s

Примечание: неоператорные версии update(), intersection_update(), difference_update() и symmetric_difference_update() принимают любой итерируемый объект в качестве аргумента.

Изменено в версии 2.3.1: Ранее все аргументы должны были быть множествами.

Также обратите внимание: модуль также включает метод union_update(), который является псевдонимом для update(). Этот метод включён для обратной совместимости. Программистам следует предпочитать метод update(), поскольку он поддерживается встроенными типами set() и frozenset().

8.7.2. ПримерExample

>>> from sets import Set
>>> engineers = Set(['John', 'Jane', 'Jack', 'Janice'])
>>> programmers = Set(['Jack', 'Sam', 'Susan', 'Janice'])
>>> managers = Set(['Jane', 'Jack', 'Susan', 'Zack'])
>>> employees = engineers | programmers | managers           # объединение
>>> engineering_management = engineers & managers            # пересечение
>>> fulltime_management = managers - engineers - programmers # разность
>>> engineers.add('Marvin')                                  # добавляет элемент
>>> print engineers 
Set(['Jane', 'Marvin', 'Janice', 'John', 'Jack'])
>>> employees.issuperset(engineers)     # проверка надмножества
False
>>> employees.update(engineers)         # обновление из другого множества
>>> employees.issuperset(engineers)
True
>>> for group in [engineers, programmers, managers, employees]: 
...     group.discard('Susan')          # безусловное удаление элемента
...     print group
...
Set(['Jane', 'Marvin', 'Janice', 'John', 'Jack'])
Set(['Janice', 'Jack', 'Sam'])
Set(['Jane', 'Zack', 'Jack'])
Set(['Jack', 'Sam', 'Jane', 'Marvin', 'Janice', 'John', 'Zack'])

8.7.3. Протокол автоматического преобразования в неизменяемый типProtocol for automatic conversion to immutable

Множества могут содержать только неизменяемые элементы. Для удобства изменяемые объекты Set автоматически копируются в ImmutableSet перед добавлением в качестве элемента множества.

Механизм заключается в том, чтобы всегда добавлять хэшируемый элемент, или, если он не хэшируемый, элемент проверяется на наличие метода __as_immutable__(), который возвращает неизменяемый эквивалент.

Поскольку объекты Set имеют метод __as_immutable__(), возвращающий экземпляр ImmutableSet, можно создавать множества множеств.

Похожий механизм нужен методам __contains__() и remove(), которым требуется хэшировать элемент для проверки членства в множестве. Эти методы проверяют элемент на хэшируемость и, если она отсутствует, ищут метод __as_temporarily_immutable__(), который возвращает элемент, обёрнутый классом, предоставляющим временные методы для __hash__(), __eq__(), и __ne__().

Альтернативный механизм избавляет от необходимости создавать отдельную копию исходного изменяемого объекта.

Объекты Set реализуют метод __as_temporarily_immutable__(), который возвращает объект Set, обёрнутый новым классом _TemporarilyImmutableSet.

Два механизма добавления хэшируемости обычно невидимы для пользователя; однако может возникнуть конфликт в многопоточной среде, где один поток обновляет множество, а другой временно обернул его в _TemporarilyImmutableSet. Другими словами, множества изменяемых множеств не являются потокобезопасными.

8.7.4. Сравнение со встроенными типами setComparison to the built-in set types

Встроенные типы set и frozenset были разработаны на основе уроков, извлечённых из модуля sets. Ключевые отличия:

  • Set и ImmutableSet были переименованы в set и frozenset.

  • Нет эквивалента для BaseSet. Вместо этого используйте isinstance(x, (set, frozenset)).

  • Алгоритм хэширования для встроенных типов работает значительно лучше (меньше коллизий) для большинства наборов данных.

  • Встроенные версии создают более компактные pickle-объекты.

  • Встроенные версии не имеют метода union_update(). Вместо этого используйте метод update(), который является эквивалентным.

  • Встроенные версии не имеют метода _repr(sorted=True). Вместо этого используйте встроенные функции repr() и sorted(): repr(sorted(s)).

  • Встроенная версия не имеет протокола автоматического преобразования в неизменяемый тип. Многие находили эту функцию сбивающей с толку, и никто в сообществе не сообщал о её реальном применении.