Множества в Python
Множества Python: создание, добавление и удаление элементов, объединение, пересечение, разность, симметричная разность, подмножества и frozenset.
Множество (set) в Python — это неупорядоченная коллекция уникальных хешируемых элементов. Поскольку множества автоматически обеспечивают уникальность и поддерживают быструю проверку членства, они идеально подходят для дедупликации, математических операций над множествами и проверки пересечений коллекций.
В этой главе рассматривается:
- Как создавать множества (литеральный синтаксис и
set()) - Добавление и удаление элементов — и когда каждый метод вызывает ошибку
- Четыре операции над множествами: объединение, пересечение, разность, симметричная разность
- Сокращённые операторы (
|,&,-,^) - Проверки подмножества и надмножества
- Генераторы множеств
- Неизменяемые множества (
frozenset) для хешируемых фиксированных наборов
Создание множеств
Использование фигурных скобок
Самый быстрый способ создать непустое множество — использовать литерал в фигурных скобках. Каждое значение встречается только один раз, сколько бы раз вы его ни записали.
Создание множества в Python
Использование конструктора set()
Передайте любой итерируемый объект — список, кортеж, строку или диапазон — в set(), чтобы создать из него множество. Дублирующиеся значения молча отбрасываются.
Преобразование списка в множество в Python
Важно: пустое множество
Для создания пустого множества необходимо использовать set(). Запись {} создаёт пустой словарь, а не множество.
empty_set = set() # correct
empty_dict = {} # this is a dict!
print(type(empty_set)) # <class 'set'>
print(type(empty_dict)) # <class 'dict'>Что может быть элементом множества?
Элемент множества должен быть хешируемым — неизменяемые типы, такие как int, float, str, bool и tuple, подходят. Списки и другие множества не могут быть элементами, так как они изменяемы и потому не хешируемы.
valid = {1, "hello", (2, 3), True} # OK
# invalid = {[1, 2]} # TypeError: unhashable type: 'list'
print(valid)Доступ к элементам множества
Множества неупорядочены, поэтому элементы не имеют индексов и получить отдельный элемент по позиции невозможно. Стандартный способ перебрать все элементы — цикл for.
colors = {"red", "green", "blue"}
for color in colors:
print(color)
# Output order may vary — sets are unorderedЧтобы проверить наличие конкретного значения, используйте оператор in:
colors = {"red", "green", "blue"}
print("red" in colors) # True
print("yellow" in colors) # FalseПроверка членства в множестве выполняется за O(1) в среднем — намного быстрее, чем поиск по списку при больших коллекциях.
Подробнее см. в главе Доступ к элементам множества.
Добавление элементов
Используйте add(), чтобы вставить один элемент, или update(), чтобы добавить несколько элементов из любого итерируемого объекта.
Добавление элемента в множество в Python
update() принимает любой итерируемый объект и добавляет все его элементы:
my_set = {1, 2, 3}
my_set.update([4, 5], {6, 7})
print(my_set) # {1, 2, 3, 4, 5, 6, 7}Подробнее см. в главе Добавление элементов множества.
Удаление элементов
Python предоставляет несколько методов удаления элементов, каждый из которых ведёт себя по-разному при отсутствии элемента.
| Метод | Поведение при отсутствии элемента |
|---|---|
remove(x) | Вызывает KeyError |
discard(x) | Ничего не делает (безопасно) |
pop() | Удаляет и возвращает произвольный элемент; вызывает KeyError, если множество пусто |
clear() | Удаляет все элементы |
Удаление элемента из множества в Python
Когда выбирать remove вместо discard: используйте remove(), когда элемент должен присутствовать и его отсутствие означает ошибку. Используйте discard(), когда элемент может быть или не быть, и вам просто нужно его убрать.
Подробнее обо всех способах удаления см. в главе Удаление элементов множества.
Операции над множествами
Множества Python реализуют четыре классические операции теории множеств. Каждая операция доступна как в виде метода, так и в виде оператора — выбирайте то, что нагляднее в контексте.
Операции над множествами в Python
set1 = {1, 2, 3}
set2 = {2, 3, 4}
# Union — all elements from both sets
print(set1.union(set2)) # {1, 2, 3, 4}
print(set1 | set2) # {1, 2, 3, 4}
# Intersection — only elements present in both
print(set1.intersection(set2)) # {2, 3}
print(set1 & set2) # {2, 3}
# Difference — elements in set1 but not set2
print(set1.difference(set2)) # {1}
print(set1 - set2) # {1}
# Symmetric difference — elements in either set, but not both
print(set1.symmetric_difference(set2)) # {1, 4}
print(set1 ^ set2) # {1, 4}Проверки подмножества и надмножества
Используйте issubset(), issuperset() или операторы сравнения <= / >= для проверки отношений включения.
a = {1, 2}
b = {1, 2, 3, 4}
print(a.issubset(b)) # True — every element of a is in b
print(a <= b) # True
print(b.issuperset(a)) # True — b contains all elements of a
print(b >= a) # True
print(a < b) # True — proper subset (a != b)
print(a == b) # Falseisdisjoint() возвращает True, если два множества не имеют ни одного общего элемента:
x = {1, 2, 3}
y = {4, 5, 6}
print(x.isdisjoint(y)) # TrueПодробнее о вариантах обновления на месте (|=, &=, -=, ^=) см. в главе Объединение множеств.
Генераторы множеств
Как и генераторы списков, множества можно создавать с помощью компактного выражения в фигурных скобках с предложением for.
squares = {x ** 2 for x in range(1, 6)}
print(squares) # {1, 4, 9, 16, 25}
# With a filter condition
even_squares = {x ** 2 for x in range(1, 11) if x % 2 == 0}
print(even_squares) # {4, 16, 36, 64, 100}Поскольку результат является множеством, дублирующиеся значения автоматически убираются:
words = ["apple", "banana", "avocado", "blueberry"]
first_letters = {w[0] for w in words}
print(first_letters) # {'a', 'b'}Неизменяемые множества (frozenset)
frozenset — это неизменяемая версия множества. После создания элементы нельзя добавлять или удалять. Объекты frozenset хешируемы, поэтому их можно использовать в качестве ключей словаря или элементов другого множества.
fs = frozenset([1, 2, 3])
print(fs) # frozenset({1, 2, 3})
# All read-only operations work
print(2 in fs) # True
print(fs | {4, 5}) # frozenset({1, 2, 3, 4, 5})
# fs.add(4) # AttributeError — frozenset has no add()
# Use as a dictionary key
permissions = {
frozenset(["read", "write"]): "editor",
frozenset(["read"]): "viewer",
}
user_perms = frozenset(["read", "write"])
print(permissions[user_perms]) # editorКогда использовать frozenset: всякий раз, когда нужен объект наподобие множества, который не должен изменяться — как постоянная конфигурация, безопасный ключ словаря или при совместном использовании множества между потоками без блокировки.
Практические примеры
Удаление дубликатов из списка
Преобразование в множество и обратно — простейший способ удалить дубликаты из списка. Обратите внимание, что исходный порядок не сохраняется; если порядок важен, используйте dict.fromkeys().
Удаление дубликатов из списка с помощью множества в Python
Проверка наличия общих элементов в двух списках
Проверка наличия общих элементов в двух списках в Python с помощью множеств
isdisjoint() — более прямая альтернатива для этой проверки:
list1 = [1, 2, 3]
list2 = [4, 5, 6]
print(not set(list1).isdisjoint(set(list2))) # False — no common elementsПоиск уникальных тегов статей
article_a_tags = {"python", "tutorial", "beginner"}
article_b_tags = {"python", "advanced", "data-science"}
all_tags = article_a_tags | article_b_tags
shared_tags = article_a_tags & article_b_tags
only_in_a = article_a_tags - article_b_tags
print("All tags: ", all_tags)
print("Shared tags: ", shared_tags)
print("Only in A: ", only_in_a)Итоги
| Операция | Метод | Оператор |
|---|---|---|
| Объединение | a.union(b) | a | b |
| Пересечение | a.intersection(b) | a & b |
| Разность | a.difference(b) | a - b |
| Симметричная разность | a.symmetric_difference(b) | a ^ b |
| Проверка подмножества | a.issubset(b) | a <= b |
| Проверка надмножества | a.issuperset(b) | a >= b |
| Проверка непересечения | a.isdisjoint(b) | — |
Связанные главы: Добавление элементов множества · Удаление элементов множества · Доступ к элементам множества · Перебор элементов множества · Объединение множеств · Методы множеств