Тип set в Python: от основ до продвинутых возможностей
Основные принципы работы с множествами в Python
Множество (set) - это неупорядоченная коллекция уникальных элементов. Тип поддерживает основные математические операции с множествами: объединение, пересечение, разность. Элементы множества должны быть хэшируемыми, то есть неизменяемыми (числа, строки, кортежи, frozenset).
Создание и базовые операции
Наиболее распространённый способ - литерал множества в фигурных скобках: {1, 2, 3}. Для создания пустого множества используют set(), а не пустые фигурные скобки (они создадут словарь).
# Создание множества
fruits = {'apple', 'banana', 'orange'}
print(fruits) # {'banana', 'apple', 'orange'}
# Добавление элемента
fruits.add('grape')
print(fruits) # {'banana', 'apple', 'orange', 'grape'}
# Удаление элемента
fruits.discard('banana')
print(fruits) # {'apple', 'orange', 'grape'}
# Проверка вхождения
if 'apple' in fruits:
print('Яблоко есть')
элемент множества python (элемент множества в python)
Как создать множество из списка, удалив дубликаты?
Передаём список в set().
numbers = [1, 2, 2, 3, 4, 3]
unique = set(numbers)
print(unique) # {1, 2, 3, 4}
тип множества python (тип множества (set) в python)
Типичная ошибка: попытка создать пустое множество через {} - будет создан пустой словарь.
empty_set = set()
empty_dict = {}
print(type(empty_set)) #
print(type(empty_dict)) #
Альтернативные способы создания и манипуляции
Как использовать генератор множества?
По аналогии со списковыми включениями, но с фигурными скобками.
squares = {x**2 for x in range(10)}
print(squares) # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
Как получить все уникальные символы строки?
Передать строку в set().
text = 'hello world'
chars = set(text)
print(chars) # {' ', 'd', 'e', 'h', 'l', 'o', 'r', 'w'}
Как выполнить математическое пересечение двух множеств?
Используйте оператор & или метод intersection().
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
intersection1 = A & B
intersection2 = A.intersection(B)
print(intersection1) # {3, 4}
print(intersection2) # {3, 4}
Как проверить, является ли одно множество подмножеством другого?
Метод issubset() или оператор <=.
small = {1, 2}
large = {1, 2, 3}
print(small.issubset(large)) # True
print(small <= large) # True
Проблема: Попытка добавить список в множество вызовет TypeError, так как списки изменяемы и не хэшируются.
try:
my_set = {1, 2, [3, 4]}
except TypeError as e:
print(e) # unhashable type: 'list'
Выход: использовать кортеж или frozenset.
Когда полезен frozenset?
Неизменяемое множество можно использовать как ключ словаря или элемент другого множества.
frozen = frozenset([1, 2, 3])
d = {frozen: 'value'}
print(d) # {frozenset({1, 2, 3}): 'value'}
Цели использования множеств
- Удаление дубликатов из коллекции.
- Быстрая проверка наличия элемента (O(1) в среднем).
- Математические операции над наборами данных (объединение, пересечение, разность).
- Определение уникальности объектов.
Расширенные примеры работы с множествами
1. Объединение и обновление множества
# union (|) и update (|=)
A = {1, 2, 3}
B = {3, 4, 5}
union_set = A | B
print('Union:', union_set) # {1, 2, 3, 4, 5}
# update изменяет исходное множество
A.update(B)
print('A after update:', A) # {1, 2, 3, 4, 5}
Union: {1, 2, 3, 4, 5}
A after update: {1, 2, 3, 4, 5}
2. Разность и симметричная разность
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
# difference (-)
diff = A - B
print('A - B:', diff) # {1, 2}
# symmetric_difference (^)
sym_diff = A ^ B
print('Symmetric diff:', sym_diff) # {1, 2, 5, 6}
# difference_update
A.difference_update(B)
print('A after diff_update:', A) # {1, 2}
A - B: {1, 2}
Symmetric diff: {1, 2, 5, 6}
A after diff_update: {1, 2}
3. Методы для проверки отношений
# isdisjoint – не имеют общих элементов
A = {1, 2}
B = {3, 4}
print('Disjoint:', A.isdisjoint(B)) # True
# issuperset (>=)
C = {1, 2, 3}
print('Superset:', C.issuperset(A)) # True
print('C >= A:', C >= A) # True
# проверка строгого подмножества
print('A < C:', A < C) # True (строгое подмножество)
print('C < C:', C < C) # False
Disjoint: True Superset: True C >= A: True A < C: True C < C: False
4. Удаление элементов: remove vs discard vs pop
s = {10, 20, 30}
# discard – не вызывает ошибку если элемент отсутствует
s.discard(40)
print('After discard 40:', s) # {10, 20, 30}
# remove – KeyError при отсутствии
try:
s.remove(40)
except KeyError as e:
print('Error:', e) # 40
# pop – удаляет и возвращает произвольный элемент
popped = s.pop()
print('Popped:', popped)
print('Set after pop:', s)
After discard 40: {10, 20, 30}
Error: 40
Popped: 10
Set after pop: {20, 30}
5. Генераторы множеств с условиями
# Чётные числа от 0 до 20
evens = {x for x in range(20) if x % 2 == 0}
print('Evens:', evens) # {0, 2, 4, 6, 8, 10, 12, 14, 16, 18}
# Квадраты чисел, кратных 3
squares_mult3 = {x**2 for x in range(15) if x % 3 == 0}
print('Squares of multiples of 3:', squares_mult3) # {0, 9, 36, 81, 144, 225}
Evens: {0, 2, 4, 6, 8, 10, 12, 14, 16, 18}
Squares of multiples of 3: {0, 9, 36, 81, 144, 225}
6. Frozenset как ключ словаря и элемент множества
# Создание frozenset
fs1 = frozenset([1, 2, 3])
fs2 = frozenset([4, 5])
# Множество из frozenset-ов
set_of_frozensets = {fs1, fs2}
print('Set of frozensets:', set_of_frozensets)
# Словарь с ключами-frozenset
d = {fs1: 'first', fs2: 'second'}
print('Dict:', d)
print('Value for fs1:', d[fs1])
Set of frozensets: {frozenset({1, 2, 3}), frozenset({4, 5})}
Dict: {frozenset({1, 2, 3}): 'first', frozenset({4, 5}): 'second'}
Value for fs1: first
7. Использование множеств для поиска дубликатов в последовательности
# Функция, возвращающая дубликаты
nums = [1, 2, 2, 3, 3, 3, 4]
seen = set()
duplicates = set()
for num in nums:
if num in seen:
duplicates.add(num)
seen.add(num)
print('Duplicates:', duplicates) # {2, 3}
Duplicates: {2, 3}
8. Сравнение производительности: in vs list
import time
# Создаём большой список и множество
size = 10**6
big_list = list(range(size))
big_set = set(big_list)
# Проверка наличия последнего элемента
t_start = time.perf_counter()
_ = (size-1) in big_list
print('List in:', time.perf_counter() - t_start)
t_start = time.perf_counter()
_ = (size-1) in big_set
print('Set in:', time.perf_counter() - t_start)
# Вывод покажет, что множество значительно быстрее
9. Операции с множествами без изменения исходных
# copy() – поверхностное копирование
original = {1, 2, 3}
clone = original.copy()
clone.add(4)
print('Original:', original) # {1, 2, 3}
print('Clone:', clone) # {1, 2, 3, 4}
# intersection, union, difference возвращают новые множества
A = {1, 2, 3}
B = {2, 3, 4}
new = A.intersection(B)
print('New set:', new) # {2, 3}
print('A unchanged:', A) # {1, 2, 3}