Тип данных set
в Python поддерживает все операции, которые проводятся над множествами в математике:
- пересечение;
- объединение;
- дополнение;
- разность;
- симметрическую разность.
Множества set
обладают рядом особенностей, которые значительно отличают их от других типов данных.
Особенности множеств в Python
1. В Python два вида множеств – обычное, изменяемое set
и замороженное, неизменяемое frozenset
. Замороженные множества нельзя изменить после создания, но все операции по объединению, пересечению и разности они поддерживают: результатом этих операций тоже будут frozenset
.
2. Множество может включать в себя только неизменяемые типы данных – строки, числа, кортежи (в любой комбинации). Попытка добавить в множество список, словарь или изменяемое множество приведет к ошибке:
>>> a_set = {[2, 3], [4, 7]}
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: unhashable type: 'list'
Неизменяемое множество frozenset
, в отличие от set
, может входить в изменяемое множество:
>>> set_a = {1, 2, 3}
>>> set_b = frozenset({4, 5, 6})
>>> set_c = {7, 8, 9, set_a}
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> set_c = {7, 8, 9, set_b}
>>> print(set_c)
{8, 9, frozenset({4, 5, 6}), 7}
3. Элементы во множествах хранятся в неупорядоченном виде, и к ним нельзя обратиться по индексу:
>>> set_a = set('123')
>>> print(set_a)
{'3', '2', '1'}
>>> print(set[1])
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: 'type' object is not subscriptable
4. Поскольку элементы множества не имеют индексов, срезы при работе с set
тоже использовать нельзя:
>>> set_a = {1, 3, 4, 5, 2, 9, 7}
>>> print(set_a[2:5])
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: 'set' object is not subscriptable
5. Все элементы множества – уникальны, повторяющиеся данные в set
игнорируются; это свойство множеств может пригодиться для решения практических задач:
>>> my_set = {2, 2, 2}
>>> print(my_set)
{2}
6. Множества не поддерживают конкатенацию и повторение:
>>> set_a = {1, 3, 5}
>>> set_b = {9, 4, 8}
>>> print(set_a + set_b)
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'set' and 'set'
>>> print(set_a * 2)
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'set' and 'int'
7. Множества занимают значительно больший объем памяти, нежели списки и кортежи. По этой причине лучше не использовать множества для решения задач с лимитом на объем памяти:
>>> from sys import getsizeof
>>> number = 100500
>>> my_list = list(range(number))
>>> my_tuple = tuple(range(number))
>>> my_set = set(range(number))
>>> my_list_size = getsizeof(my_list)
>>> my_tuple_size = getsizeof(my_tuple)
>>> my_set_size = getsizeof(my_set)
>>> print(f'Размер списка: {round(my_list_size / 1024 / 1024, 3)} Мб')
Размер списка: 0.431 Мб
>>> print(f'Размер кортежа: {round(my_tuple_size / 1024 / 1024, 3)} Мб')
Размер кортежа: 0.383 Мб
>>> print(f'Размер множества: {round(my_set_size / 1024 / 1024, 3)} Мб')
Размер множества: 2.0 Мб
8. Хотя множества занимают гораздо больший объем памяти, чем списки и кортежи, работают они гораздо быстрее. Этот код сравнивает время, затраченное на проведение операции над списком, кортежем и множеством с одинаковым количеством элементов:
from time import time
number = 15000
my_set = set(range(number))
my_list = list(range(number))
my_tuple = tuple(range(number))
t = time()
for i in range(number):
if i in my_list:
pass
print(f"Операция со списком: {time() - t} секунд")
my_list.clear()
t = time()
for i in range(number):
if i in my_tuple:
pass
print(f"Операция с кортежeм: {time() - t} секунд")
t = time()
for i in range(number):
if i in my_set:
pass
print(f"Операция со множеством: {time() - t} секунд")
my_set.clear()
Результат:
Операция со списком: 1.810847282409668 секунд
Операция с кортежeм: 1.6490623950958252 секунд
Операция со множеством: 0.0013110637664794922 секунд
Создание множеств в Python
Пустое множество можно создать только одним способом, с помощью set()
:
>>> my_set = set()
>>> print(type(my_set))
<class 'set'>
Попытка создать пустое множество с помощью фигурных скобок {}
обречена на провал – вместо set
будет создан словарь dict
:
>>> my_set = {}
>>> print(type(my_set))
<class 'dict'>
Множество с данными можно создать несколькими способами.
Способ 1: Перечисление элементов
Для создания множества нужные элементы перечисляют через запятую в фигурных скобках:
>>> set_a = {3, 7, 9, 0, 2, 1}
>>> set_b = {'а', 'б', 'в', 'г'}
>>> set_c = {'Мастер и Маргарита', 450, 1250, 'переплет'}
>>> set_d = {2, 4, 5, (2, 9, 0)}
Способ 2: Преобразование других типов данных
Множество можно создать на основе символов либо слов строки:
>>> print(set('абырвалг'))
{'р', 'в', 'л', 'г', 'б', 'а', 'ы'}
>>> print(set('Множества в Python'.split()))
{'Множества', 'в', 'Python'}
Множество из списка:
>>> print(set([3, 6, 4, 5, 5]))
{3, 4, 5, 6}
Множество на основе кортежа:
>>> print(set(('красный', 'синий', 'зеленый')))
{'зеленый', 'красный', 'синий'}
При создании множества из dict
от словаря останутся только ключи:
>>> print(set({'артикул': 'А123', 'цвет': 'черный'}))
{'артикул', 'цвет'}
В отличие от символов строк, число нельзя автоматически разбить на отдельные цифры и преобразовать во множество напрямую:
>>> print(set(123))
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: 'int' object is not iterable
Но с применением str
преобразование проходит без ошибок:
>>> print(set(str(1812)))
{'8', '2', '1'}
Способ 3: Генераторы множеств
Как и в случае со списками и словарями, для создания множеств удобно использовать генераторы:
>>> print({i ** 2 for i in range(15)})
{0, 1, 64, 121, 4, 36, 100, 196, 9, 169, 16, 49, 81, 144, 25}
В генераторах можно использовать любые условия:
>>> print({int(i) for i in '3в2о7ыр3р74ртрчфрежр4рфф23468795323' if i.isdigit() and int(i) < 7})
{2, 3, 4, 5, 6}
В генератор можно включить любые дополнительные функции, например, ввод input()
и функцию ord()
для возвращения числового кода символа из таблицы Unicode:
>>> print({ord(i) for i in input() if i.isalpha()})
ewr73694yrhf897349ugg05fhshcvnaWQXXldoaxsd
{81, 87, 88, 97, 99, 100, 101, 102, 103, 104, 108, 110, 111, 114, 115, 117, 118, 119, 120, 121}
Помимо условия if
, в генератор можно добавить обработку else
:
>>> set_a = {i ** 2 if i % 2 == 0 else i ** 3 for i in (map(int, input().split()))}
2 5 12 13 4 56 71 33 9 10
>>> print(set_a)
{3136, 35937, 4, 100, 144, 16, 2197, 357911, 729, 125}
Стандартные методы множеств в Python
Множества поддерживают ряд стандартных методов, общих для большинства коллекций Python, и имеют несколько собственных, уникальных для типа set
. Начнем с общих методов.
Длина, сумма, min и max элементы
Эти методы работают со множествами точно так же, как и со списками и кортежами:
>>> set_a = {2, 4, 5, 6, 1, 9, 7, 12}
>>> print(f'Количество элементов: {len(set_a)}, сумма элементов: {sum(set_a)}')
Количество элементов: 8, сумма элементов: 46
>>> print(f'Минимальный элемент: {min(set_a)}, максимальный элемент: {max(set_a)}')
Минимальный элемент: 1, максимальный элемент: 12
Принадлежность элемента множеству
>>> my_set = {'математика', 'физика', 'химия'}
>>> print('математика' in my_set)
True
>>> print('биология' not in my_set)
True
Сортировка
Как и в случае с кортежами, результатом сортировки множества будет список:
>>> numbers = {25, 15, 7, 8, 19, 34, 52, 0, 12, 59, 91, 4}
>>> print(sorted(numbers))
[0, 4, 7, 8, 12, 15, 19, 25, 34, 52, 59, 91]
>>> print(sorted(numbers, reverse=True))
[91, 59, 52, 34, 25, 19, 15, 12, 8, 7, 4, 0]
Сравнение множеств
Множества можно сравнивать с помощью операторов ==
и !=
:
>>> set_a = {5, 1, 4, 8, 6, 9}
>>> set_b = {6, 2, 5, 9, 7, 10}
>>> print(set_b != set_a)
True
Другие операторы сравнения, например >
и <
, дают неожиданный на первый взгляд результат:
>>> set_a = {1, 2, 3}
>>> set_b = {4, 5, 6, 7}
>>> print(set_b > set_a)
False
Это связано с тем, что при сравнении множеств Python определяет, является ли одно из них под- или надмножеством другого (подробнее об этом – ниже):
>>> set_a = {1, 2, 3}
>>> set_b = {1, 2, 3, 4}
>>> print(set_b > set_a)
True
Добавление элемента
Метод add()
добавляет во множество новый элемент:
>>> letters = {'а', 'б', 'в'}
>>> letters.add('г')
>>> print(letters)
{'г', 'в', 'а', 'б'}
Несколько элементов можно добавить с помощью цикла for
(мы рассмотрим его в следующей статье) или с помощью генератора:
>>> set_a = set()
>>> gen = {set_a.add(i) for i in range(12)}
>>> print(set_a)
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
Удаление элемента
Для удаления элемента нужно воспользоваться одним из поддерживаемых методов:
1. remove()
– возвращает сообщение об ошибке, если элемент не будет найден:
>>> my_set = {1, 2, 3}
>>> my_set.remove(2)
>>> print(my_set)
{1, 3}
2. discard()
– безопасный метод, не приводит к ошибке в случае отсутствия элемента:
>>> my_set = {'красный', 'черный', 'синий'}
>>> my_set.discard('синий')
>>> print(my_set)
{'красный', 'черный'}
>>> my_set.discard('розовый')
>>>
3. pop()
– в отличие от аналогичного списочного метода, удаляет случайный элемент и возвращает его значение:
>>> my_set = {2, 4, 6, 1, 12}
>>> print(my_set.pop())
1
4. Метод clear() удаляет все элементы множества сразу – так можно освободить оперативную память после завершения операции с объемным set
:
>>> my_set = {6, 2, 9, 0}
>>> my_set.clear()
>>> print(my_set)
set()
Отлично! Вы освоили основы работы с множествами.
Вы знаете их уникальные свойства, умеете их создавать и выполнять все стандартные операции: добавлять, удалять и сортировать элементы.
Но вся мощь множеств раскрывается, когда вы начинаете работать с несколькими наборами данных одновременно. Для этого в Python встроены сверхбыстрые математические операции. В полной версии урока вы освоите специальные методы множеств и научитесь:
- В одну строку находить общие элементы (пересечение), объединять коллекции и находить уникальные различия между ними.
- Мгновенно проверять, входит ли один набор данных в другой с помощью методов
issubset
иissuperset
. - Применять эти мощные инструменты для решения 10 практических задач по анализу данных, поиску дубликатов и сравнениям.
Комментарии
описание и примеры методов issubset() и issuperset() ПОМЕНЯНЫ МЕСТАМИ !!!