Множества в Python

В этой статье мы рассмотрим множества (set) в Python — коллекции уникальных элементов с особыми свойствами, которые делают их незаменимыми для определенных задач.

Что такое множество?

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

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

Основные характеристики множеств:

  • Изменяемость: можно добавлять и удалять элементы
  • Хеширование: элементы должны быть хешируемыми (неизменяемыми) объектами
  • Эффективность: оптимизированы для быстрой проверки вхождения элементов

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

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

С помощью фигурных скобок

Python 3.13
# Множество целых чисел
>>> numbers = {1, 2, 3, 4, 5}
>>> print(numbers)
{1, 2, 3, 4, 5}
# Автоматическое удаление дубликатов >>> duplicates = {1, 2, 2, 3, 3, 3, 4, 5, 5} >>> print(duplicates)
{1, 2, 3, 4, 5}
# Множество с разными типами данных >>> mixed = {1, "привет", (1, 2, 3)} >>> print(mixed)
{1, 'привет', (1, 2, 3)}

Важно: Нельзя создать пустое множество с помощью {}, так как это будет пустой словарь. Для создания пустого множества используйте set().

С помощью конструктора set()

Python 3.13
# Пустое множество
>>> empty_set = set()
>>> print(empty_set)
set()
# Создание множества из списка >>> numbers_set = set([1, 2, 2, 3, 4, 4, 5]) >>> print(numbers_set)
{1, 2, 3, 4, 5}
# Создание множества из строки >>> letters = set("hello") >>> print(letters) # 'l' встречается только один раз
{'h', 'e', 'l', 'o'}

С помощью генераторов множеств

Python 3.13
# Множество квадратов чисел от 0 до 9
>>> squares = {x**2 for x in range(10)}
>>> print(squares)
{0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
# Множество четных чисел от 0 до 9 >>> even_numbers = {x for x in range(10) if x % 2 == 0} >>> print(even_numbers)
{0, 2, 4, 6, 8}

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

Проверка наличия элемента

Python 3.13
>>> fruits = {"яблоко", "банан", "вишня"}

>>> print("яблоко" in fruits)
True
>>> print("груша" in fruits)
False

Добавление и удаление элементов

Python 3.13
>>> fruits = {"яблоко", "банан"}

# Добавление одного элемента
>>> fruits.add("вишня")
>>> print(fruits)
{'яблоко', 'вишня', 'банан'}
# Добавление нескольких элементов >>> fruits.update(["груша", "апельсин"]) >>> print(fruits)
{'яблоко', 'вишня', 'банан', 'груша', 'апельсин'}
# Удаление элемента >>> fruits.remove("банан") # вызывает KeyError, если элемента нет >>> print(fruits)
{'яблоко', 'вишня', 'груша', 'апельсин'}
# Безопасное удаление элемента >>> fruits.discard("вишня") # не вызывает ошибку, если элемента нет >>> print(fruits)
{'яблоко', 'груша', 'апельсин'}
# Извлечение произвольного элемента >>> random_fruit = fruits.pop() >>> print(random_fruit)
яблоко
>>> print(fruits)
{'груша', 'апельсин'}
# Очистка множества >>> fruits.clear() >>> print(fruits)
set()

Итерация по множеству

Python 3.13
>>> colors = {"красный", "синий", "зеленый"}

>>> for color in colors:
...     print(color)
красный
синий
зеленый
# Порядок элементов не гарантирован!

Математические операции над множествами

Объединение (Union)

Python 3.13
>>> a = {1, 2, 3}
>>> b = {3, 4, 5}

# С оператором |
>>> union_set = a | b
>>> print(union_set)
{1, 2, 3, 4, 5}
# С методом union() >>> union_set = a.union(b) >>> print(union_set)
{1, 2, 3, 4, 5}

Пересечение (Intersection)

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

# С оператором &
>>> intersection_set = a & b
>>> print(intersection_set)
{3, 4}
# С методом intersection() >>> intersection_set = a.intersection(b) >>> print(intersection_set)
{3, 4}

Разность (Difference)

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

# С оператором -
>>> difference_set = a - b
>>> print(difference_set)
{1, 2}
# С методом difference() >>> difference_set = a.difference(b) >>> print(difference_set)
{1, 2}

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

Python 3.13
>>> a = {1, 2, 3}
>>> b = {1, 2, 3, 4, 5}
>>> c = {1, 2, 3}

# Равенство множеств
>>> print(a == c)  # Содержат одинаковые элементы
True
# Подмножества >>> print(a.issubset(b)) # Все элементы a есть в b
True
>>> print(a < b) # a является строгим подмножеством b
True
# Надмножества >>> print(b.issuperset(a)) # b содержит все элементы a
True
>>> print(b > a) # b является строгим надмножеством a
True
# Проверка на отсутствие общих элементов >>> d = {6, 7, 8} >>> print(a.isdisjoint(d)) # Нет общих элементов
True

Неизменяемые множества (frozenset)

Если нужен неизменяемый вариант множества, используйте frozenset:

Python 3.13
# Создание frozenset
>>> immutable_set = frozenset([1, 2, 3, 4])
>>> print(immutable_set)
frozenset({1, 2, 3, 4})
# Попытка изменить frozenset вызывает ошибку >>> try: ... immutable_set.add(5) ... except AttributeError as e: ... print(f"Ошибка: {e}")
Ошибка: 'frozenset' object has no attribute 'add'
# frozenset можно использовать как ключ словаря или элемент другого множества >>> normal_set = {frozenset([1, 2]), frozenset([3, 4])} >>> print(normal_set)
{frozenset({1, 2}), frozenset({3, 4})}

Практические примеры использования множеств

1. Удаление дубликатов из списка

Python 3.13
>>> numbers = [1, 2, 2, 3, 3, 3, 4, 5, 5]
>>> unique_numbers = list(set(numbers))
>>> print(unique_numbers)
[1, 2, 3, 4, 5]

2. Нахождение общих элементов

Python 3.13
>>> users_group1 = ["Анна", "Иван", "Мария", "Петр", "Елена"]
>>> users_group2 = ["Иван", "Ольга", "Елена", "Алексей"]

# Общие элементы (пересечение)
>>> common_users = set(users_group1) & set(users_group2)
>>> print(f"Пользователи в обеих группах: {common_users}")
Пользователи в обеих группах: {'Елена', 'Иван'}
# Элементы только из первой группы (разность) >>> only_group1 = set(users_group1) - set(users_group2) >>> print(f"Только в группе 1: {only_group1}")
Только в группе 1: {'Мария', 'Анна', 'Петр'}
# Все уникальные элементы (объединение) >>> all_users = set(users_group1) | set(users_group2) >>> print(f"Все уникальные пользователи: {all_users}")
Все уникальные пользователи: {'Елена', 'Иван', 'Мария', 'Анна', 'Ольга', 'Алексей', 'Петр'}

3. Проверка уникальности элементов

Python 3.13
>>> def are_all_unique(items):
...     """Проверяет, все ли элементы в последовательности уникальны."""
...     return len(set(items)) == len(items)

>>> print(are_all_unique([1, 2, 3, 4, 5]))
True
>>> print(are_all_unique([1, 2, 3, 3, 4]))
False

Ограничения и производительность

Ограничения

Элементы множества должны быть хешируемыми (неизменяемыми):

Python 3.13
# Работает с неизменяемыми типами данных
>>> valid_set = {1, "hello", (1, 2, 3)}
>>> print(valid_set)
{1, 'hello', (1, 2, 3)}
# Ошибка с изменяемыми типами данных >>> try: ... invalid_set = {1, [2, 3], {"a": 1}} ... except TypeError as e: ... print(f"Ошибка: {e}")
Ошибка: unhashable type: 'list'

Можно добавлять:

  • Числа (int, float, complex)
  • Строки (str)
  • Кортежи (tuple) с хешируемыми элементами
  • Frozenset

Нельзя добавлять:

  • Списки (list)
  • Словари (dict)
  • Множества (set)

Производительность

Множества оптимизированы для быстрых операций:

Python 3.13
>>> import time

# Сравнение скорости поиска (демонстрация)
>>> data = list(range(10000))
>>> data_set = set(data)

# Поиск в списке vs. поиск в множестве
>>> start = time.time()
>>> 9999 in data  # Медленно: O(n)
>>> list_time = time.time() - start

>>> start = time.time()
>>> 9999 in data_set  # Быстро: O(1)
>>> set_time = time.time() - start

>>> print(f"Поиск в списке: {list_time:.6f} сек")
>>> print(f"Поиск в множестве: {set_time:.6f} сек")
>>> print(f"Множество быстрее в {list_time/set_time:.1f} раз")
Поиск в списке: 0.000248 сек
Поиск в множестве: 0.000003 сек
Множество быстрее в 82.7 раз

Операции со сложностью O(1) (константное время):

  • Проверка наличия элемента: x in set
  • Добавление элемента: set.add(x)
  • Удаление элемента: set.remove(x), set.discard(x)

Проверка понимания

Какой из следующих кодов правильно находит элементы, присутствующие в списке list1, но отсутствующие в списке list2?


Мы с вами на связи
Русский