Урок 26 Множества

set(), операции над множествами

⏱ ~10 мин чтения· 📘 Базовый

Создание множества

Множество — неупорядоченная коллекция уникальных элементов:

# Через фигурные скобки
fruits = {"яблоко", "банан", "вишня"}

# Через функцию set() — можно передать любой итерируемый объект (например, список)
numbers = set([1, 2, 2, 3, 3, 3])  # {1, 2, 3}

# Пустое множество (не {} — это словарь!)
empty = set()

Операции над множествами

Математические операции:

a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

print(a | b)   # {1, 2, 3, 4, 5, 6} — объединение
print(a & b)   # {3, 4} — пересечение
print(a - b)   # {1, 2} — разность
print(a ^ b)   # {1, 2, 5, 6} — симметрическая разность

Наглядно увидеть, какие элементы попадают в результат каждой операции, можно на диаграмме Эйлера. Нажмите кнопку под диаграммой — нужные числа подсветятся:

Методы множеств

Основные методы. Код выполняется последовательно — комментарии показывают множество после каждой строки:

s = {1, 2, 3}

print(3 in s)      # True — оператор in проверяет вхождение
print(10 not in s) # True — not in: элемента нет во множестве

s.add(4)          # {1, 2, 3, 4} — добавить элемент
s.remove(2)       # {1, 3, 4} — KeyError, если элемента нет
s.discard(10)     # {1, 3, 4} — ошибки не будет, даже если элемента нет
s.pop()           # удаляет и возвращает произвольный элемент
s.clear()         # set() — очищает множество

Метод .remove(x) вызывает ошибку KeyError, если элемента x нет во множестве:

s = {1, 2, 3}
s.remove(10)  # KeyError: 10

Почему элементы должны быть хешируемыми

Перед добавлением элемента Python вычисляет его хеш — число, которое возвращает встроенная функция hash():

print(hash(42))       # 42 — у чисел хеш совпадает с самим числом
print(hash("hello"))  # некоторое число — при каждом запуске своё!

Хеш определяет ячейку таблицы, в которую попадёт элемент. Отсюда три следствия:

  • Проверка x in s не перебирает элементы по очереди, а сразу смотрит в нужную ячейку по хешу — поэтому работает быстро даже на больших множествах.
  • Порядок элементов определяется их хешами, а не порядком добавления — поэтому множество «неупорядочено».
  • Изменяемые объекты (списки, словари) добавить нельзя: при изменении объекта изменился бы и его хеш, и элемент «потерялся» бы в таблице. Неизменяемые — числа, строки и кортежи — подходят:
data = {1, "hello", (2, 3)}
data.add([4, 5])  # TypeError: unhashable type: 'list'