Наборы в Python

Наборы в Python

Возможно, вы помните, что когда-то в своем математическом образовании вы узнали оsets иset theory. Может быть, вы даже помните диаграммы Венна:

Venn diagram

Если это не звонок, не волнуйтесь! Это руководство должно быть легко доступным для вас.

В математике строгое определение множества может быть абстрактным и трудным для понимания. Однако на практике набор можно рассматривать просто как четко определенный набор отдельных объектов, обычно называемыхelements илиmembers.

Группировка объектов в набор также может быть полезна при программировании, и Python предоставляет для этого встроенный тип набора. Наборы отличаются от других типов объектов уникальными операциями, которые могут быть выполнены над ними.

Here’s what you’ll learn in this tutorial: Вы увидите, как определять объектыset в Python, и узнаете, какие операции они поддерживают. Как и в предыдущих уроках по спискам и словарям, когда вы закончите работу с этим уроком, вы должны хорошо понимать, когда набор является подходящим выбором. Вы также узнаете оfrozen sets, которые похожи на наборы, за исключением одной важной детали.

__ Take the Quiz: Проверьте свои знания с помощью нашей интерактивной викторины «Наборы Python». По окончании вы получите оценку, чтобы вы могли отслеживать прогресс в обучении с течением времени:

Определение набора

Встроенный в Python типset имеет следующие характеристики:

  • Наборы неупорядочены.

  • Элементы набора являются уникальными. Повторяющиеся элементы не допускаются.

  • Сам набор может быть изменен, но элементы, содержащиеся в наборе, должны быть неизменного типа.

Давайте посмотрим, что все это значит, и как вы можете работать с наборами в Python.

Набор может быть создан двумя способами. Во-первых, вы можете определить набор с помощью встроенной функцииset():

x = set()

В этом случае аргумент<iter> является итерируемым - опять же, на данный момент, списком размышлений или кортежем - который генерирует список объектов, которые должны быть включены в набор. Это аналогично аргументу<iter>, передаваемому методу списка.extend():

>>>

>>> x = set(['foo', 'bar', 'baz', 'foo', 'qux'])
>>> x
{'qux', 'foo', 'bar', 'baz'}

>>> x = set(('foo', 'bar', 'baz', 'foo', 'qux'))
>>> x
{'qux', 'foo', 'bar', 'baz'}

Строки также являются итерируемыми, поэтому строку также можно передать вset(). Вы уже видели, чтоlist(s) генерирует список символов в строкеs. Точно так жеset(s) генерирует набор символов вs:

>>>

>>> s = 'quux'

>>> list(s)
['q', 'u', 'u', 'x']
>>> set(s)
{'x', 'u', 'q'}

Вы можете видеть, что результирующие наборы неупорядочены: исходный порядок, указанный в определении, не обязательно сохраняется. Кроме того, повторяющиеся значения представлены в наборе только один раз, как, например, строка'foo' в первых двух примерах и буква'u' в третьем.

В качестве альтернативы набор можно определить с помощью фигурных скобок ({}):

x = {, , ..., }

Когда набор определяется таким образом, каждый<obj> становится отдельным элементом набора, даже если он является итеративным. Это поведение похоже на поведение метода списка.append().

Таким образом, наборы, показанные выше, также могут быть определены следующим образом:

>>>

>>> x = {'foo', 'bar', 'baz', 'foo', 'qux'}
>>> x
{'qux', 'foo', 'bar', 'baz'}

>>> x = {'q', 'u', 'u', 'x'}
>>> x
{'x', 'q', 'u'}

Подведем итог:

  • Аргументset() повторяется. Он генерирует список элементов для размещения в наборе.

  • Объекты в фигурных скобках помещаются в набор без изменений, даже если они повторяемые.

Обратите внимание на разницу между этими двумя определениями:

>>>

>>> {'foo'}
{'foo'}

>>> set('foo')
{'o', 'f'}

Набор может быть пустым. Однако напомним, что Python интерпретирует пустые фигурные скобки ({}) как пустой словарь, поэтому единственный способ определить пустой набор - использовать функциюset():

>>>

>>> x = set()
>>> type(x)

>>> x
set()

>>> x = {}
>>> type(x)

Пустой набор ложен в логическом контексте:

>>>

>>> x = set()
>>> bool(x)
False
>>> x or 1
1
>>> x and 1
set()

Вы можете подумать, что самые интуитивно понятные наборы будут содержать похожие объекты, например, даже числа или фамилии:

>>>

>>> s1 = {2, 4, 6, 8, 10}
>>> s2 = {'Smith', 'McArthur', 'Wilson', 'Johansson'}

Python не требует этого, хотя. Элементы в наборе могут быть объектами разных типов:

>>>

>>> x = {42, 'foo', 3.14159, None}
>>> x
{None, 'foo', 42, 3.14159}

Не забывайте, что элементы набора должны быть неизменными. Например, кортеж может быть включен в набор:

>>>

>>> x = {42, 'foo', (1, 2, 3), 3.14159}
>>> x
{42, 'foo', 3.14159, (1, 2, 3)}

Но списки и словари являются изменяемыми, поэтому их нельзя задавать элементами:

>>>

>>> a = [1, 2, 3]
>>> {a}
Traceback (most recent call last):
  File "", line 1, in 
    {a}
TypeError: unhashable type: 'list'

>>> d = {'a': 1, 'b': 2}
>>> {d}
Traceback (most recent call last):
  File "", line 1, in 
    {d}
TypeError: unhashable type: 'dict'

Установить размер и членство

Функцияlen() возвращает количество элементов в наборе, а операторыin иnot in могут использоваться для проверки принадлежности:

>>>

>>> x = {'foo', 'bar', 'baz'}

>>> len(x)
3

>>> 'bar' in x
True
>>> 'qux' in x
False

Работа на наборе

Многие операции, которые можно использовать для других составных типов данных Python, не имеют смысла для наборов. Например, наборы не могут быть проиндексированы или разрезаны. Однако Python предоставляет целый ряд операций с объектами-наборами, которые обычно имитируютoperations, определенные для математических наборов.

Операторы против методы

Большинство, хотя и не все, операции над множествами в Python могут выполняться двумя различными способами: оператором или методом. Давайте посмотрим, как работают эти операторы и методы, используя set union в качестве примера.

Для двух наборовx1 иx2 объединениеx1 иx2 является набором, состоящим из всех элементов любого набора.

Рассмотрим эти два набора:

x1 = {'foo', 'bar', 'baz'}
x2 = {'baz', 'qux', 'quux'}

Объединениеx1 иx2 равно{'foo', 'bar', 'baz', 'qux', 'quux'}.

Note: Обратите внимание, что элемент'baz', который появляется как вx1, так и вx2, появляется только один раз в объединении. Наборы никогда не содержат повторяющихся значений.

В Python объединение множеств можно выполнить с помощью оператора|:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}
>>> x1 | x2
{'baz', 'quux', 'qux', 'bar', 'foo'}

Объединение множеств можно также получить с помощью метода.union(). Метод вызывается для одного из наборов, а другой передается в качестве аргумента:

>>>

>>> x1.union(x2)
{'baz', 'quux', 'qux', 'bar', 'foo'}

То, как они используются в приведенных выше примерах, оператор и метод ведут себя одинаково. Но между ними есть небольшая разница. Когда вы используете оператор|, должны быть установлены оба операнда. С другой стороны, метод.union() примет любую итерацию в качестве аргумента, преобразует ее в набор и затем выполнит объединение.

Обратите внимание на разницу между этими двумя утверждениями:

>>>

>>> x1 | ('baz', 'qux', 'quux')
Traceback (most recent call last):
  File "", line 1, in 
    x1 | ('baz', 'qux', 'quux')
TypeError: unsupported operand type(s) for |: 'set' and 'tuple'

>>> x1.union(('baz', 'qux', 'quux'))
{'baz', 'quux', 'qux', 'bar', 'foo'}

Оба пытаются вычислить объединениеx1 и кортежа('baz', 'qux', 'quux'). Это не удается с оператором|, но успешно с методом.union().

Доступные операторы и методы

Ниже приведен список операций над множествами, доступных в Python. Некоторые выполняются оператором, некоторые - методом, а некоторые - обоими. Принцип, изложенный выше, в целом применим: когда ожидается набор, методы обычно принимают любую итерацию в качестве аргумента, но операторы требуют фактических наборов в качестве операндов.

x1.union(x2[, x3 ...])

x1 | x2 [| x3 ...]

Вычислить объединение двух или более множеств.

x1.union(x2) иx1 | x2 возвращают набор всех элементов вx1 илиx2:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

>>> x1.union(x2)
{'foo', 'qux', 'quux', 'baz', 'bar'}

>>> x1 | x2
{'foo', 'qux', 'quux', 'baz', 'bar'}

Можно указать более двух наборов с помощью оператора или метода:

>>>

>>> a = {1, 2, 3, 4}
>>> b = {2, 3, 4, 5}
>>> c = {3, 4, 5, 6}
>>> d = {4, 5, 6, 7}

>>> a.union(b, c, d)
{1, 2, 3, 4, 5, 6, 7}

>>> a | b | c | d
{1, 2, 3, 4, 5, 6, 7}

Результирующий набор содержит все элементы, присутствующие в любом из указанных наборов.

x1.intersection(x2[, x3 ...])

x1 & x2 [& x3 ...]

Вычислить пересечение двух или более множеств.

x1.intersection(x2) иx1 & x2 возвращают набор элементов, общих дляx1 иx2:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

>>> x1.intersection(x2)
{'baz'}

>>> x1 & x2
{'baz'}

Вы можете указать несколько множеств с помощью метода пересечения и оператора, так же, как вы можете с помощью множества объединений:

>>>

>>> a = {1, 2, 3, 4}
>>> b = {2, 3, 4, 5}
>>> c = {3, 4, 5, 6}
>>> d = {4, 5, 6, 7}

>>> a.intersection(b, c, d)
{4}

>>> a & b & c & d
{4}

Результирующий набор содержит только элементы, которые присутствуют во всех указанных наборах.

x1.difference(x2[, x3 ...])

x1 - x2 [- x3 ...]

Вычислите разницу между двумя или более наборами.

x1.difference(x2) иx1 - x2 возвращают набор всех элементов, которые находятся вx1, но не вx2:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

>>> x1.difference(x2)
{'foo', 'bar'}

>>> x1 - x2
{'foo', 'bar'}

Другой способ думать об этом состоит в том, чтоx1.difference(x2) иx1 - x2 возвращают набор, который получается, когда любые элементы вx2 удаляются или вычитаются изx1.

Еще раз, вы можете указать более двух наборов:

>>>

>>> a = {1, 2, 3, 30, 300}
>>> b = {10, 20, 30, 40}
>>> c = {100, 200, 300, 400}

>>> a.difference(b, c)
{1, 2, 3}

>>> a - b - c
{1, 2, 3}

Если указано несколько наборов, операция выполняется слева направо. В приведенном выше примере сначала вычисляетсяa - b, в результате получается{1, 2, 3, 300}. Затемc вычитается из этого набора, оставляя{1, 2, 3}:

set difference

x1.symmetric_difference(x2)

x1 ^ x2 [^ x3 ...]

Вычислитеsymmetric difference между наборами.

x1.symmetric_difference(x2) иx1 ^ x2 возвращают набор всех элементов вx1 илиx2, но не в обоих:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

>>> x1.symmetric_difference(x2)
{'foo', 'qux', 'quux', 'bar'}

>>> x1 ^ x2
{'foo', 'qux', 'quux', 'bar'}

Оператор^ также допускает более двух наборов:

>>>

>>> a = {1, 2, 3, 4, 5}
>>> b = {10, 2, 3, 4, 50}
>>> c = {1, 50, 100}

>>> a ^ b ^ c
{100, 5, 10}

Как и в случае с оператором разницы, когда задано несколько наборов, операция выполняется слева направо.

Любопытно, что хотя оператор^ допускает несколько наборов, метод.symmetric_difference() не делает:

>>>

>>> a = {1, 2, 3, 4, 5}
>>> b = {10, 2, 3, 4, 50}
>>> c = {1, 50, 100}

>>> a.symmetric_difference(b, c)
Traceback (most recent call last):
  File "", line 1, in 
    a.symmetric_difference(b, c)
TypeError: symmetric_difference() takes exactly one argument (2 given)

x1.isdisjoint(x2)

Определяет, имеют ли два набора общие элементы.

x1.isdisjoint(x2) возвращаетTrue, еслиx1 иx2 не имеют общих элементов:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'baz', 'qux', 'quux'}

>>> x1.isdisjoint(x2)
False

>>> x2 - {'baz'}
{'quux', 'qux'}
>>> x1.isdisjoint(x2 - {'baz'})
True

Еслиx1.isdisjoint(x2) - этоTrue, тоx1 & x2 - это пустой набор:

>>>

>>> x1 = {1, 3, 5}
>>> x2 = {2, 4, 6}

>>> x1.isdisjoint(x2)
True
>>> x1 & x2
set()

Note: Нет оператора, соответствующего методу.isdisjoint().

x1.issubset(x2)

x1 <= x2

Определите, является ли один набор подмножеством другого.

В теории множеств наборx1 считается подмножеством другого набораx2, если каждый элементx1 находится вx2.

x1.issubset(x2) иx1 <= x2 возвращаютTrue, еслиx1 является подмножествомx2:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x1.issubset({'foo', 'bar', 'baz', 'qux', 'quux'})
True

>>> x2 = {'baz', 'qux', 'quux'}
>>> x1 <= x2
False

Набор считается подмножеством самого себя:

>>>

>>> x = {1, 2, 3, 4, 5}
>>> x.issubset(x)
True
>>> x <= x
True

Это кажется странным, возможно. Но это соответствует определению - каждый элементx находится вx.

x1 < x2

Определяет, является ли один набор правильным подмножеством другого.

Подходящее подмножество совпадает с подмножеством, за исключением того, что наборы не могут быть идентичными. Наборx1 считается правильным подмножеством другого набораx2, если каждый элементx1 находится вx2, аx1 иx2 являются не равный.

x1 < x2 возвращаетTrue, еслиx1 является правильным подмножествомx2:

>>>

>>> x1 = {'foo', 'bar'}
>>> x2 = {'foo', 'bar', 'baz'}
>>> x1 < x2
True

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'bar', 'baz'}
>>> x1 < x2
False

Хотя набор считается подмножеством самого себя, он не является собственным подмножеством:

>>>

>>> x = {1, 2, 3, 4, 5}
>>> x <= x
True
>>> x < x
False

Note: Оператор< - единственный способ проверить, является ли набор правильным подмножеством. Нет соответствующего метода.

x1.issuperset(x2)

x1 >= x2

Определите, является ли один набор надмножеством другого.

Надмножество является противоположностью подмножества. Наборx1 считается надмножеством другого набораx2, еслиx1 содержит каждый элементx2.

x1.issuperset(x2) иx1 >= x2 возвращаютTrue, еслиx1 является надмножествомx2:

>>>

>>> x1 = {'foo', 'bar', 'baz'}

>>> x1.issuperset({'foo', 'bar'})
True

>>> x2 = {'baz', 'qux', 'quux'}
>>> x1 >= x2
False

Вы уже видели, что набор считается подмножеством самого себя. Набор также считается надмножеством самого себя:

>>>

>>> x = {1, 2, 3, 4, 5}
>>> x.issuperset(x)
True
>>> x >= x
True

x1 > x2

Определяет, является ли один набор правильным надмножеством другого.

Надлежащий надмножество такое же, как надмножество, но наборы не могут быть идентичными. Наборx1 считается правильным надмножеством другого набораx2, еслиx1 содержит каждый элементx2, аx1 иx2 не являются равный.

x1 > x2 возвращаетTrue, еслиx1 является правильным надмножествомx2:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'bar'}
>>> x1 > x2
True

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'bar', 'baz'}
>>> x1 > x2
False

Набор не является надлежащим надмножеством самого себя:

>>>

>>> x = {1, 2, 3, 4, 5}
>>> x > x
False

Note: Оператор> - единственный способ проверить, является ли набор правильным надмножеством. Нет соответствующего метода.

Модификация набора

Хотя элементы, содержащиеся в наборе, должны быть неизменного типа, сами наборы могут быть изменены. Как и вышеописанные операции, существует множество операторов и методов, которые можно использовать для изменения содержимого набора.

Расширенные операторы присваивания и методы

Каждый из перечисленных выше операторов объединения, пересечения, разности и симметричной разности имеет расширенную форму присваивания, которую можно использовать для изменения набора. Для каждого есть соответствующий метод.

x1.update(x2[, x3 ...])

x1 |= x2 [| x3 ...]

Изменить набор по объединению.

x1.update(x2) иx1 |= x2 добавляют кx1 любые элементы вx2, которых уx1 еще нет:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'baz', 'qux'}

>>> x1 |= x2
>>> x1
{'qux', 'foo', 'bar', 'baz'}

>>> x1.update(['corge', 'garply'])
>>> x1
{'qux', 'corge', 'garply', 'foo', 'bar', 'baz'}

x1.intersection_update(x2[, x3 ...])

x1 &= x2 [& x3 ...]

Изменить набор пересечением.

x1.intersection_update(x2) иx1 &= x2 обновляютx1, сохраняя только элементы, найденные как вx1, так и вx2:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'baz', 'qux'}

>>> x1 &= x2
>>> x1
{'foo', 'baz'}

>>> x1.intersection_update(['baz', 'qux'])
>>> x1
{'baz'}

x1.difference_update(x2[, x3 ...])

x1 -= x2 [| x3 ...]

Изменить набор по разнице.

x1.difference_update(x2) иx1 -= x2 обновляютx1, удаляя элементы, найденные вx2:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'baz', 'qux'}

>>> x1 -= x2
>>> x1
{'bar'}

>>> x1.difference_update(['foo', 'bar', 'qux'])
>>> x1
set()

x1.symmetric_difference_update(x2)

x1 ^= x2

Изменить набор симметричной разностью.

x1.symmetric_difference_update(x2) иx1 ^= x2 обновляютx1, сохраняя элементы, найденные либо вx1, либо вx2, но не в обоих:

>>>

>>> x1 = {'foo', 'bar', 'baz'}
>>> x2 = {'foo', 'baz', 'qux'}
>>>
>>> x1 ^= x2
>>> x1
{'bar', 'qux'}
>>>
>>> x1.symmetric_difference_update(['qux', 'corge'])
>>> x1
{'bar', 'corge'}

Другие методы для модификации наборов

Помимо расширенных операторов выше, Python поддерживает несколько дополнительных методов, которые модифицируют наборы.

x.add()

Добавляет элемент в набор.

x.add(<elem>) добавляет<elem>, который должен быть единственным неизменяемым объектом, кx:

>>>

>>> x = {'foo', 'bar', 'baz'}

>>> x.add('qux')
>>> x
{'bar', 'baz', 'foo', 'qux'}

x.remove()

Удаляет элемент из набора.

x.remove(<elem>) удаляет<elem> изx. Python вызывает исключение, если<elem> не находится вx:

>>>

>>> x = {'foo', 'bar', 'baz'}

>>> x.remove('baz')
>>> x
{'bar', 'foo'}

>>> x.remove('qux')
Traceback (most recent call last):
  File "", line 1, in 
    x.remove('qux')
KeyError: 'qux'

x.discard()

Удаляет элемент из набора.

x.discard(<elem>) также удаляет<elem> изx. Однако, если<elem> отсутствует вx, этот метод незаметно ничего не делает вместо того, чтобы вызвать исключение:

>>>

>>> x = {'foo', 'bar', 'baz'}

>>> x.discard('baz')
>>> x
{'bar', 'foo'}

>>> x.discard('qux')
>>> x
{'bar', 'foo'}

x.pop()

Удаляет случайный элемент из набора.

x.pop() удаляет и возвращает произвольно выбранный элемент изx. Еслиx пусто,x.pop() вызывает исключение:

>>>

>>> x = {'foo', 'bar', 'baz'}

>>> x.pop()
'bar'
>>> x
{'baz', 'foo'}

>>> x.pop()
'baz'
>>> x
{'foo'}

>>> x.pop()
'foo'
>>> x
set()

>>> x.pop()
Traceback (most recent call last):
  File "", line 1, in 
    x.pop()
KeyError: 'pop from an empty set'

x.clear()

Очищает набор.

x.clear() удаляет все элементы изx:

>>>

>>> x = {'foo', 'bar', 'baz'}
>>> x
{'foo', 'bar', 'baz'}
>>>
>>> x.clear()
>>> x
set()

Замороженные наборы

Python предоставляет другой встроенный тип, называемыйfrozenset, который во всех отношениях в точности похож на набор, за исключением того, что frozenset является неизменяемым. Вы можете выполнять немодифицирующие операции на морозильнике:

>>>

>>> x = frozenset(['foo', 'bar', 'baz'])
>>> x
frozenset({'foo', 'baz', 'bar'})

>>> len(x)
3

>>> x & {'baz', 'qux', 'quux'}
frozenset({'baz'})

Но методы, которые пытаются изменить Frozenset, терпят неудачу:

>>>

>>> x = frozenset(['foo', 'bar', 'baz'])

>>> x.add('qux')
Traceback (most recent call last):
  File "", line 1, in 
    x.add('qux')
AttributeError: 'frozenset' object has no attribute 'add'

>>> x.pop()
Traceback (most recent call last):
  File "", line 1, in 
    x.pop()
AttributeError: 'frozenset' object has no attribute 'pop'

>>> x.clear()
Traceback (most recent call last):
  File "", line 1, in 
    x.clear()
AttributeError: 'frozenset' object has no attribute 'clear'

>>> x
frozenset({'foo', 'bar', 'baz'})

Глубокое погружение: Frozensets и дополненное задание

Поскольку frozenset является неизменяемым, вы можете подумать, что он не может быть целью расширенного оператора присваивания. Но обратите внимание:

>>>

>>> f = frozenset(['foo', 'bar', 'baz'])
>>> s = {'baz', 'qux', 'quux'}

>>> f &= s
>>> f
frozenset({'baz'})

Что дает?

Python не выполняет расширенные задания на месте Frozensets. Выражениеx &= s эффективно эквивалентноx = x & s. Это не изменяет исходныйx. Он переназначаетx новому объекту, и объектx, на который первоначально ссылались, пропал.

Вы можете проверить это с помощью функцииid():

>>>

>>> f = frozenset(['foo', 'bar', 'baz'])
>>> id(f)
56992872
>>> s = {'baz', 'qux', 'quux'}

>>> f &= s
>>> f
frozenset({'baz'})
>>> id(f)
56992152

f имеет другой целочисленный идентификатор после расширенного назначения. Он был переназначен, а не изменен на месте.

Некоторые объекты в Python изменяются на месте, когда они являются целью расширенного оператора присваивания. Но это не так.

Frozensets полезны в ситуациях, когда вы хотите использовать набор, но вам нужен неизменный объект. Например, вы не можете определить набор, элементы которого также являются наборами, потому что элементы набора должны быть неизменными:

>>>

>>> x1 = set(['foo'])
>>> x2 = set(['bar'])
>>> x3 = set(['baz'])
>>> x = {x1, x2, x3}
Traceback (most recent call last):
  File "", line 1, in 
    x = {x1, x2, x3}
TypeError: unhashable type: 'set'

Если вы действительно чувствуете необходимость определить набор множеств (эй, это может произойти), вы можете сделать это, если элементы являются замороженными, потому что они неизменны:

>>>

>>> x1 = frozenset(['foo'])
>>> x2 = frozenset(['bar'])
>>> x3 = frozenset(['baz'])
>>> x = {x1, x2, x3}
>>> x
{frozenset({'bar'}), frozenset({'baz'}), frozenset({'foo'})}

Точно так же вспомните из предыдущего руководства поdictionaries, что ключ словаря должен быть неизменным. Вы не можете использовать встроенный тип набора в качестве ключа словаря:

>>>

>>> x = {1, 2, 3}
>>> y = {'a', 'b', 'c'}
>>>
>>> d = {x: 'foo', y: 'bar'}
Traceback (most recent call last):
  File "", line 1, in 
    d = {x: 'foo', y: 'bar'}
TypeError: unhashable type: 'set'

Если вам нужно использовать наборы в качестве ключей словаря, вы можете использовать frozensets:

>>>

>>> x = frozenset({1, 2, 3})
>>> y = frozenset({'a', 'b', 'c'})
>>>
>>> d = {x: 'foo', y: 'bar'}
>>> d
{frozenset({1, 2, 3}): 'foo', frozenset({'c', 'a', 'b'}): 'bar'}

Заключение

В этом руководстве вы узнали, как определять объектыset в Python, и познакомились с функциями, операторами и методами, которые можно использовать для работы с наборами.

Теперь вы должны быть знакомы с основными встроенными типами данных, которые предоставляет Python.

Затем вы начнете исследовать, как код, который работает с этими объектами, организован и структурирован в программе Python.

__ Take the Quiz: Проверьте свои знания с помощью нашей интерактивной викторины «Наборы Python». По окончании вы получите оценку, чтобы вы могли отслеживать прогресс в обучении с течением времени: