Set Python. Множества в Python
В языке Python есть тип данных, который может быть очень полезен для работы с множествами – это set. В данном уроке будет рассказано о том, как работать с множествами (set python) и об операциях над ними.
Что это
Set в Python — это тип данных, встроенный в язык и предназначенный для работы с последовательностями, которые имеют свойства математических множеств. В качестве элементов набора данных выступают различные неизменяемые объекты. В python множество может состоять из не ограниченного количества элементов и они могут быть любых неизменяемых типов, таких как кортежи, числа, строки и т. д. Однако, множество не поддерживает mutable элементы, к примеру списки, словари, и прочие. Python множества — это изменяемые коллекции элементов, обладающие некоторыми особенностями:
— их элементы не упорядочены;
— их элементы не повторяются.
Таким образом, множеством в языке Python является неупорядоченная совокупность элементов, при том уникальных. Порядок расстановки элементов не учитывается при работе с его содержимым. Над одним или несколькими множествами можно выполнять разные операции, используя функции, содержащиеся в стандартной библиотеке Python.
Как создать множество python
Перед тем как выполнять операции с множеством, необходимо его создать. Существует несколько способов создавать множества в Python. Можно это сделать, присвоив любой переменной коллекцию значений, окружив их фигурными скобками <>, а так же разделить все элементы запятыми.
Создание множества в Python выглядит следующим образом:
Множества в Python (set, frozenset)
Множество — интуитивно понятный математический термин, который часто используется в обыденной речи и означает набор или совокупность неких элементов, что обладают каким-то общим свойством.
Не слишком строгое определение множества, однако, с ним возникали проблемы даже у великих математиков.
В широком смысле, элементами множеств могут быть даже нематериальные вещи: чётные числа, несданные задачи по термодинамике, алгоритмы сортировки, любимые фильмы Юлии и Алексея и даже мысли об эклерах.
🐱 Возьмите в руки кота. Взяли? Хорошо. Теперь множество котов в ваших руках насчитывает ровно один мурлыкающий элемент. Если же пушистику вдруг не понравится, что вы его тискаете, и он выскочит из рук, то элементов внутри множества не останется. Множество, в котором нет ни одного элемента, называется пустым. Но что же там в Python?
Назначение в Python
Множества (set) в питоне появились не сразу, и здесь они представлены как неупорядоченные коллекции уникальных и неизменяемых объектов. Коллекции, которые не являются ни последовательностями (как списки), ни отображениями (как словари). Хотя с последними у множеств много общего.
Можно сказать, что set напоминает словарь, в котором ключи не имеют соответствующих им значений
Пример set-ов в Python:
# множество натуральных чисел от 1 до 10 natural_num_set = <1, 2, 3, 4, 5, 6, 7, 8, 9, 10># множество персонажей Братства Кольца the_fellowship_of_the_ring_set = <'Гэндальф', 'Арагорн', 'Фродо', 'Сэм', 'Боромир', 'Леголас', 'Гимли', 'Мерри', 'Пиппин'># множество приближений math.sqrt(2) sqrt_approximation_set = <1.4142135623, 1.414213562, 1.41421356, 1.4142135, 1.414213># множество результатов какого-то голосования vote_result_set =
Особенности set
Одно из основных свойств множеств заключается в уникальности каждого из их элементов. Посмотрим, что получится, если сформировать set из строчки с заведомо повторяющимися символами:
strange_app = set(‘TikTok’) print(strange_app) >
Из результата были удалены дублирующиеся в слове ‘TikTok’ символы. Так множества в очередной раз доказали, что содержат в себе только уникальные элементы.
👉 Немаловажным является и тот факт, что при литеральном объявлении, итерируемые объекты сохраняют свою структуру.
pangram_second = set(‘съешь же ещё этих мягких французских булок, да выпей чаю’) print(pangram_ second) # попить чаю с функцией set(), к сожалению, не выйдет >
Отдельное python множество может включать в себя объекты разных типов:
Здесь нет никакого противоречия с математической дефиницией, так как все составляющие we_are_the_py_objects имеют вполне конкретное общее свойство, являясь объектами языка Питон.
Но не стоит забывать и внутреннее определение set-ов. Важно помнить, что list-ы и dict-ы не подходят на роль элементов множества, из-за своей изменяемой природы.
glados = <['Great cake']>print(glados) > Traceback (most recent call last): glados = <['Great cake']>TypeError: unhashable type: ‘list’
# словарь будет преобразован во множество его ключей, значения отбрасываются some_dict = <'key_one': 'val_one', 'key_two': 'val_two'>some_set = set(some_dict) print(some_set) > <'key_one', 'key_two'># элементы списка преобразуются в элементы множества, дубликаты удаляются card_suit = [‘heart’, ‘diamond’, ‘club’, ‘spade’, ‘spade’] suit_set = set(card_suit) print(suit_set) >
Однако в списках не должно быть вложенных изменяемых элементов.
tricky_list = [<'jocker': 'black'>, <'jocker': 'red'>] sad_set = set(tricky_list) print(sad_set) > Traceback (most recent call last): sad_set = set(tricky_list) TypeError: unhashable type: ‘dict’
Работа с set-ами
Создание
Чтобы получить аналогичный результат, необходимо передать итерируемый объект (список, строку или кортеж) в качестве аргумента:
# объявим список L L = [‘1’, ‘2’, ‘3’] # и предоставим его в set() S_2 = set(L) print(S_2) # так как set — коллекция неупорядоченная, то результат вывода может отличаться > <'1', '2', '3'>print(type(S_2)) >
👉 Замечание: пустое множество создаётся исключительно через set()
empty_set = set() print(empty_set) > set() print(type(empty_set)) >
Если же сделать так:
another_empty_set = <> print(another_empty_set) > <> print(type(another_empty_set)) >
То получим пустой словарь. А если внутри фигурных скобок поместить пустую строку:
maybe_empty_set = <''>print(maybe_empty_set) > <''>print(type(maybe_empty_set)) >
То на выходе увидим множество, состоящее из одного элемента — этой самой пустой строки.
# количество элементов множества print(len(maybe_empty_set)) > 1
Вполне естественно, что пустое множество, при приведении его к логическому типу, тождественно ложно:
true_or_false = set() print(bool(true_or_false)) > False
Пересечение
Добавление элемента
stats = <1.65, 2.33, 5.0>stats.add(14.7) print(stats) >
Если среди исходных объектов, составляющих set, «x» уже был, то ничего не произойдёт, и начальное множество не изменится.
big_cats = <'tiger', 'liger', 'lion', 'cheetah', 'leopard', 'cougar'>big_cats.add(‘cheetah’) # это жестоко, но второго гепарда не появится print(big_cats) >
Удаление и очистка
Очистить и свести уже существующий сет к пустому не составит никаких проблем благодаря методу сlear() :
set_with_elements = <'i am element', 'me too'>print(set_with_elements) > <'i am element', 'me too'>set_with_elements.clear() print(set_with_elements) > set()
Для удаления одного единственного компонента из набора в Питоне определены аж три способа.
triangle_coord = <(0, 4), (3, 0), (-3, 0)>print(triangle_coord) > <(3, 0), (-3, 0), (0, 4)>triangle_coord.discard((0, 4)) print(triangle_coord) > <(3, 0), (-3, 0)>triangle_coord.discard((54, 55)) print(triangle_coord) >
Удаляет и возвращает случайный элемент множества:
Перебор элементов
Множество, как и любую другую коллекцию, итерируем циклом for :
iterate_me = <1.1, 1.2, 1.3, 1.4, 1.5>for num in iterate_me: print(num) > 1.1 1.4 1.3 1.2 1.5
Принадлежность объекта set-у
Оператор in даёт возможность проверить наличие элемента в наборе:
berry_club = <'Tomato', 'Currant', 'Sea buckthorn', 'Grape', 'Barberry'>print(‘Tomato’ in berry_club) > True print(‘Strawberry’ in berry_club) > False
Сортировка множеств
Длина множества
Операции на множествах
Самое важное в этой теме. Математические теоретико-множественные операции, что не доступны никаким другим коллекциям языка. Поехали.
Объединение
Объединением двух множеств «X» и «Y» является такое третье множество «Z», каждый элемент которого принадлежит либо множеству «X», либо «Y».
lang_X = <'C++', 'Perl', 'PHP'>lang_Y = <'Java', 'C#', 'PHP', 'Python'>lang_Z = lang_X.union(lang_Y) # или так lang_Z = lang_X | lang_Y print(lang_Z) >
Пересечение
Пересечением двух множеств «A» и «B» является такое третье множество «C», каждый элемент которого принадлежит и множеству «A», и множеству «B».
bats_enemies = <'Darkside', 'Jocker', 'Bane'>sups_enemies = <'General Zod', 'Darkside', 'Lobo'>JL_enemies = bats_enemies.intersection(sups_enemies) # или так JL_enemies = bats_enemies & sups_enemies print(JL_enemies) >
Разность множеств
Разностью двух множеств «O» и «P» является такое третье множество «S», каждый элемент которого принадлежит множеству «O» и не принадлежит множеству «P».
Симметрическая разность
Симметрической разностью двух множеств «M» и «N» является такое третье множество «L», каждый элемент которого принадлежит либо множеству «M», либо «N», но не их пересечению.
f_set = <11, 'a', 18, 'v', 65, 'g'>s_set = <11, 'z', 32, 'v', 0, 'g'>t_set = f_set.symmetric_difference(s_set) # или так t_set = f_set ^ s_set print(t_set) >
Помимо теоретико-множественных операций, в питоне существуют и сугубо утилитарные производные методы.
isdisjoint()
Метод определяет, есть ли у двух set-ов общие элементы:
it = <'green', 'white', 'red'>ru = <'white', 'blue', 'red'>ukr = <'blue', 'yellow'># вернет False, если множества пересекаются print(ukr.isdisjoint(it)) > True # и True, в противном случае print(ru.isdisjoint(it)) > False
В Python нет оператора, который бы соответствовал этому методу.
issubset()
Показывает, является ли «I» подмножеством «J» (Метод вернет True, если все элементы «I» принадлежат «J»):
solar_system = <'Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune'>first_three_planets = <'Mercury', 'Venus', 'Earth'>poor_small_guy = <'Pluto'>emptyness = set() print(first_three_planets.issubset(solar_system)) # или так first_three_planets True print(poor_small_guy.issubset(solar_system)) # poor_small_guy False # как и в математике, пустое множество есть подмножество любого множества print(emptyness.issubset(solar_system)) # emptyness True # также любое множество является подмножеством самого себя print(poor_small_guy.issubset(poor_small_guy)) # poor_small_guy True
print(poor_small_guy.issubset(poor_small_guy)) # poor_small_guy False
issuperset()
Показывает, является ли «F» надмножеством «G»:
print(solar_system.issuperset(first_three_planets)) # solar_system >= first_three_planets > True print(poor_small_guy.issuperset(solar_system)) # poor_small_guy >= solar_system > False # в сердечке Плутона лишь пустота… print(poor_small_guy.issuperset(emptyness)) # poor_small_guy >= emptyness > True
print(poor_small_guy > poor_small_guy) > False
И для него в языке Python тоже не существует соответствующего метода.
update()
Изменяет исходное множество по объединению:
dogs_in_first_harness = <'Lessie', 'Bork', 'Spark'>dogs_in_second_harness = <'Lucky'>dogs_in_second_harness.update(dogs_in_first_harness) # или так dogs_in_second_harness |= dogs_in_first_harness print(dogs_in_second_harness) >
intersection_update()
difference_update()
symmetric_difference_update()
И, наконец, по симметрической разности:
his_bag = <'croissant', 'tea', 'cookies'>her_bag = <'tea', 'cookies', 'chocolate', 'waffles'>her_bag.symmetric_difference_update(his_bag) print(her_bag) # или так her_bag ^= his_bag >
Свойства методов и операторов
list_of_years = [2019, 2018, 2017] set_of_years = <2009, 2010, 2011>print(set_of_years.union(list_of_years)) > <2017, 2018, 2019, 2009, 2010, 2011>print(set_of_years | list_of_years) > Traceback (most recent call last):> print(set_of_years | list_of_years) TypeError: unsupported operand type(s) for |: ‘set’ and ‘list’
Но есть и сходства. Например, важным является то, что некоторые операторы и методы позволяют совершать операции над несколькими сетами сразу:
Тем интереснее, что оператор ^ симметрической разности позволяет использовать несколько наборов, а метод symmetric_difference() — нет.
tc1 = <10.1, 20.2, 30.3, 40.4, 50.5>tc2 = <10.1, 20.2, 30.3, 40.4, 500>tc3 = <1, 50.1, 1000>print(tc1 ^ tc2 ^ tc3) # вы же помните про порядок операций (слева-направо)? > <1, 1000, 50.1, 50.5, 500>print(tc1.symmetric_difference(tc2, tc3)) > Traceback (most recent call last): print(tc1.symmetric_difference(tc2, tc3)) TypeError: symmetric_difference() takes exactly one argument (2 given)
Преобразования
Конвертация строки во множество
Чтобы перевести строку во множество, достаточно представить её в виде литерала этого множества.
my_string = ‘Lorem ipsum dolor sit amet’ sting_to_set =
Конвертация списка во множество
Со списком подобный трюк не пройдет, но здесь на помощь спешит функция set() :
my_list = [2, 4, 8, 16, 32] list_to_set = set(my_list) print(list_to_set) >
Frozenset
Python и теория множеств
В Python есть очень полезный тип данных для работы с множествами – это set. Об этом типе данных, примерах использования, и небольшой выдержке из теории множеств пойдёт речь далее.
Следует сразу сделать оговорку, что эта статья ни в коем случае не претендует на какую-либо математическую строгость и полноту, скорее это попытка доступно продемонстрировать примеры использования множеств в языке программирования Python.
Множество
Множество – это математический объект, являющийся набором, совокупностью, собранием каких-либо объектов, которые называются элементами этого множества. Или другими словами:
Множество – это не более чем неупорядоченная коллекция уникальных элементов.
Что значит неупорядоченная? Это значит, что два множества эквивалентны, если содержат одинаковые элементы.
Элементы множества должны быть уникальными, множество не может содержать одинаковых элементов. Добавление элементов, которые уже есть в множестве, не изменяет это множество.
Множества, состоящие из конечного числа элементов, называются конечными, а остальные множества – бесконечными. Конечное множество, как следует из названия, можно задать перечислением его элементов. Так как темой этой статьи является практическое использование множеств в Python, то я предлагаю сосредоточиться на конечных множествах.
Множества в Python
Множество в Python можно создать несколькими способами. Самый простой – это задать множество перечислением его элементов в фигурных скобках:
Единственное ограничение, что таким образом нельзя создать пустое множество. Вместо этого будет создан пустой словарь:
Для создания пустого множества нужно непосредственно использовать set() :
Также в set() можно передать какой-либо объект, по которому можно проитерироваться (Iterable):
Ещё одна возможность создания множества – это использование set comprehension. Это специальная синтаксическая конструкция языка, которую иногда называют абстракцией множества по аналогии с list comprehension (Списковое включение).
Хешируемые объекты
Существует ограничение, что элементами множества (как и ключами словарей) в Python могут быть только так называемые хешируемые (Hashable) объекты. Это обусловлено тем фактом, что внутренняя реализация set основана на хеш-таблицах. Например, списки и словари – это изменяемые объекты, которые не могут быть элементами множеств. Большинство неизменяемых типов в Python (int, float, str, bool, и т.д.) – хешируемые. Неизменяемые коллекции, например tuple, являются хешируемыми, если хешируемы все их элементы.
Объекты пользовательских классов являются хешируемыми по умолчанию. Но практического смысла чаще всего в этом мало из-за того, что сравнение таких объектов выполняется по их адресу в памяти, т.е. невозможно создать два «равных» объекта.
Скорее всего мы предполагаем, что объекты City(«Moscow») должны быть равными, и следовательно в множестве cities должен находиться один объект.
Этого можно добиться, если определить семантику равенства для объектов класса City :
Чтобы протокол хеширования работал без явных и неявных логических ошибок, должны выполняться следующие условия:
Свойства множеств
Тип set в Python является подтипом Collection (про коллекции), из данного факта есть три важных следствия:
Принадлежность множеству
Мощность множества
Мощность множества – это характеристика множества, которая для конечных множеств просто означает количество элементов в данном множестве. Для бесконечных множеств всё несколько сложнее.
Перебор элементов множества
Как уже было отмечено выше, множества поддерживают протокол итераторов, таким образом любое множество можно использовать там, где ожидается iterable-объект.
Отношения между множествами
Между множествами существуют несколько видов отношений, или другими словами взаимосвязей. Давайте рассмотрим возможные отношения между множествами в этом разделе.
Равные множества
Тут всё довольно просто – два множества называются равными, если они состоят из одних и тех же элементов. Как следует из определения множества, порядок этих элементов не важен.
Непересекающиеся множества
Если два множества не имеют общих элементов, то говорят, что эти множества не пересекаются. Или другими словами, пересечение этих множеств является пустым множеством.
Подмножество и надмножество
Подмножество множества S – это такое множество, каждый элемент которого является также и элементом множества S. Множество S в свою очередь является надмножеством исходного множества.
Пустое множество является подмножеством абсолютно любого множества.
Само множество является подмножеством самого себя.
Операции над множествами
Рассмотрим основные операции, опредяляемые над множествами.
Объединение множеств
Объединение множеств – это множество, которое содержит все элементы исходных множеств. В Python есть несколько способов объединить множества, давайте рассмотрим их на примерах.
Добавление элементов в множество
Пересечение множеств
Пересечение множеств – это множество, в котором находятся только те элементы, которые принадлежат исходным множествам одновременно.
Разность множеств
Разность двух множеств – это множество, в которое входят все элементы первого множества, не входящие во второе множество.
Удаление элементов из множества
Симметрическая разность множеств
Симметрическая разность множеств – это множество, включающее все элементы исходных множеств, не принадлежащие одновременно обоим исходным множествам. Также симметрическую разность можно рассматривать как разность между объединением и пересечением исходных множеств.
Заключение
Я надеюсь, мне удалось показать, что Python имеет очень удобные встроенные средства для работы с множествами. На практике это часто позволяет сократить количество кода, сделать его выразительнее и легче для восприятия, а следовательно и более поддерживаемым. Я буду рад, если у вас есть какие-либо конструктивные замечания и дополнения.
Множества в Python
Множество (англ. «set«) – неупорядоченная коллекция из уникальных (неповторяющихся) элементов. Элементы множества в Python должны быть немутабельны (неизменяемы), хотя само содержимое множества может меняться: можно добавлять и удалять элементы из множества.
О неизменяемых множествах написано в конце этой статьи.
CPython: внутри множества реализованы как хэш-таблицы, в которых есть только ключи без значений и добавлены некоторые оптимизации, которые используют отсутствие значений. Проверка членства выполняется за время O(1), так как поиск элементов в хэш-таблицы тоже выполняется за О(1). Если интересно, как это реализовано на С: вот ссылка.
Создание множества
Сформировать множество можно несколькими способами. Самый простой – перечислить элементы через запятую внутри фигурных скобок <>. Множество может содержать элементы разных типов, главное, чтобы они были неизменяемы. Поэтому кортеж можно поместить в множество, а список – нельзя.
Можно также воспользоваться встроенной функцией set, чтобы создать множество из другой коллекции: списка, кортежа или словаря. Если это будет словарь – то новое множество будет составлено только из ключей этого словаря. Можно создать множество даже из строки: будет добавлена каждая буква (но только один раз):
Как создать пустое множество? <> – вернет нам пустой словарик, а не множество. Поэтому, нужно использовать set() без аргументов.
Изменение множеств
Множества можно менять, добавляя или удаляя элементы. Так как они не упорядочены, то индексирование не имеет смысла и не поддерживается: мы не может получать доступ к элементам множества по индексу, как мы это делаем для списков и кортежей.
Добавление одного элемента выполняется методом add(). Нескольких элементов из коллекции или нескольких коллекций – методом update():
Естественно, что при добавлении элементов дубликаты игнорируются.
Удаление элементов из множества
Для удаления элемента существуют методы discard() и remove(). Делают они одно и тоже, но если удаляемого элемента нет во множестве, то discard() оставит множество неизменным молча, а remove() – бросит исключение:
Также есть метод pop(), который берет какой-нибудь (первый попавшийся) элемент множества, удаляет его и возвращает как результат:
Наконец, очистить множество (т.е. удалить все его элементы) можно методом clear():
Проверка членства
Узнать есть ли элемент в множестве очень легко оператором in (или not in, если хотим убедиться в отсутствии элемента):
Таким образом проверяется членства одного элемента, если нужно узнать является ли одно множество подмножеством другого, то оператор in тут не подойдет:
Итерация множеств
Пробежаться по элементам множества также легко, как и по элементам других коллекций оператором for-in (порядок обхода не определен точно):
Операции над множествами
Самое интересное – проводить математические операции над множествами.
Рассмотрим два множества A и B:
Объединение
Объединение множеств – множество, в котором есть все элементы одного и другого множеств. Это коммуникативная операция (от перемены мест ничего не меняется).
В Python используется либо метод union(), либо оператор вертикальная черта «|»:
Пересечение множеств
Пересечение множеств – множество, в которое входят только общие элементы, то есть которые есть и в первом, и во втором множестве. Также коммуникативная операция.
Пересечение вычисляют методом intersection() или оператором амперсандом «&»:
Разность множеств
Разность множеств A и В – множество элементов из A, которых нет в B. Не коммуникативная операция!
Выполняется знаком минус «-» или оператором difference():
Как видно есть разница, в каком порядке идут операнды.
Симметричная разность
Симметричная разность – это объединение множеств за исключеним их пересечения. По другому, это сумма разностей. Это коммуникативный оператор.
Используется метод symmetric_difference() или оператор крышка «^»:
Обратите внимание на эквивалентность операции определениям, которые я привел в начале этого раздела:
Прочее
Ко множествам можно применять стандартные функции all(), any(), enumerate(), len(), max(), min(), sorted(), sum(). Описания их ищите тут.
Прочие методы класса set:
| copy() | Возвращает копию множества |
| difference_update(other_set) | Удаляет из этого множества все элементы, которые есть во множестве, переданным в аргументе |
| intersection_update(other_set) | Обновляет это множество элементами из пересечения множеств |
| isdisjoint(other_set) | Возвращает True, если множества не пересекаются |
| issubset(other_set) | Возвращает True, если это множество является подмножеством другого |
| issuperset(other_set) | Возвращает True, если это множество является надмножеством другого |
| symmetric_difference_update(other_set) | Добавляет в это множество симметричную разность этого и другого множеств |
Замороженное множество
Замороженное множество (frozen set) также является встроенной коллекцией в Python. Обладая характеристиками обычного множества, замороженное множество не может быть изменено после создания (подобно тому, как кортеж является неизменяемой версией списка).
Будучи изменяемыми, обычные множества являются нехешируемыми (unhashable type), а значит не могут применятся как ключи словаря или элементы других множеств.
Замороженные множества являются хэшируемыми, а значит могут быть ключами словаря и элементами других множеств.
Создаются замороженные множества функцией frozenset(), где аргументом будет другая коллекция. Примеры:
Над замороженными множествами можно производить все вышеописанные операции, кроме тех, что изменяют содержимое этого множества. Причем результатом логических операций будут тоже замороженные множества:
Теперь вы знаете много о множествах в Python.
Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈







