Введение в множества
Set' ы в Python реализованы так, что максимально напоминают математические множества. Давайте пройдемся по основным свойствам и возможностям множеств в Python, и разберемся, как их использовать. 
В математике множество -- это набор объектов произвольной природы. В Python множество тоже может содержать переменные разных типов, например: 
 
>>> A = {"My hovercraft is full of eels", 42, (3.14, 2.72)}
Но есть одно ограничение: элементы множества должны быть хэшируемыми: например, в множество можно добавить строки, числа и кортежи, но нельзя словари и списки:
 
>>> A.add([-1, 0])
TypeError: unhashable type: 'list'
При этом поскольку сами множества 
мутабельны, то множество множеств, как в известном парадоксе про брадобрея, сделать не получится. Но если очень хочется, можно использовать frozenset’ы: эти объекты в остальном ведут себя почти так же, но они иммутабельны и их можно добавить в множество. 
Инициализировать множество можно используя фигурные скобки или через конструктор класса 
set(). Эти инициализации эквивалентны:
 
>>> B = {1, 2, 3}
>>> B = set((1, 2, 3))
Только не запутайтесь: такая инструкция  
 
C = {}
создаст не множество, а словарь. 
В версиях интерпретатора 2.7 и выше работают set comprehensions: 
 
>>> C = {x for x in range(1, 5)} 
>>> C
{1, 2, 3, 4}
Элементы множества, как и в математике, должны быть уникальными. На практике этим пользуются для того, чтобы исключить повторяющиеся элементы:
 
>>> D = [1, 2, 3, 3]
>>> D = list(set(D))
>>> D
[1, 2, 3]
Кстати, множества не сохраняют порядок, поэтому если он нужен, то добро пожаловать в списки. Из-за того, что порядка нет, во множествах нет ни индексирования, ни слайсов. В то же время циклы по множеству можно делать обычным pythonic-способом: 
 
>>> for elem in C: 
...     print(elem)
 Над множествами в Python можно делать те же операции, что и в математике: находить объединение, пересечение, проверять принадлежность к множеству и так далее. Для этого можно пользоваться операторами, а можно методами множеств: 
 
A | B   A.union(B)
A & B   A.intersection(B)
A - B   A.difference(B)
A <= B  A.issubset(B)
A => B  A.issuperset(B)
…
Обратите внимание, что операторы принимают только set’ы, а методы -- любые iterable контейнеры. Есть мнение, что операторы менее читаемые, но оба подхода в целом равноправны. 
И еще у класса 
set есть методы, которые удобны для работы со множествами как с коллекциями: 
add() — добавить элемент, 
remove() — удалить элемент, 
pop() — извлечь с удалением, 
update() — объединить с другим множеством,
clear() — очистить множество. 
И напоследок: один раз я больно отстрелила себе ногу, когда хотела добавить составной элемент в множество с помощью неправильного инструмента. Например, если у нас есть множество строк и мы пытаемся добавить в него еще один элемент вот так:
 
>>> F = {"Seregia", "Vasia"}
>>> F.update("Alisa")
то получаем ожидаемый результат:
 
>>> F
{'l', 'a', 'Seregia', 'Vasia', 'A', 'i', 's'}
Это абсолютно валидный код и он отработает, поэтому такую ошибку по невнимательности можно искать довольно долго.  Так что не попадайте в ловушку методов 
add() и 
update(). 
В общем, Python set'ы сильно напоминают математические множества: могут содержать объекты разных типов,  требуют уникальности элементов, не сохраняют порядок и имеют методы, позволяющие их объединять, пересекать, etc... Кроме того, множества имеют интерфейс для работы с ними как с коллекциями. 
Как определиться в выборе коллекции?
🐙 Если важен порядок — используйте списки. 
🐙 Если нужно отображение ключ-значение — используйте словари.
🐙 Если нужен набор уникальных элементов — используйте множества. 
#основы #типы_данных #comprehensions #списки #селяви #коллекции