## 15. Types `set` and `frozenset`: Set types

Mathematically speaking, a set is an unordered collection of zero or more distinct elements. Python has two set types that represent this mathematical abstraction. Use these types when you care only about whether something is a member of the set or not, and you don't need them to be in any specific order.

The elements of a Python set must be immutable. In particular, you can't have list or dictionary elements in a set.

Most operations on sets work with both `set` and `frozenset` types.

• Values of type `set` are mutable: you can add or delete members.

There are two ways to create a mutable set.

• In all Python versions of the 2.x series, the `set(S)` function operates on a sequence `S` and returns a mutable set containing the unique elements of `S`. The argument is optional; if omitted, you get a new, empty set.

```>>> s1 = set([1, 1, 1, 9, 1, 8, 9, 8, 3])
set([8, 1, 3, 9])
>>> s1 = set([1, 1, 1, 9, 1, 8, 9, 8, 3])
>>> s2 = set()
>>> s1
set([8, 1, 3, 9])
>>> s2
set([])
>>> print len(s1), len(s2)
4 0
>>> s3 = set("notlob bolton")
>>> s3
s3
set([' ', 'b', 'l', 'o', 'n', 't'])
```
• Starting in Python 2.7, you can create a set by simply enclosing one or more elements within braces `{...}` separated by commas.

```s1 = {1, 1, 1, 9, 1, 8, 9, 8, 3}
>>> s1
set([8, 9, 3, 1])
```

Note the wording “one or more:” an empty pair of braces “`{}`” is an empty dictionary, not an empty set.

• A `frozenset` value is immutable: you can't change the membership, but you can use a `frozenset` value in contexts where `set` values are not allowed. For example, you can use a `frozenset` as a key in a dictionary, but you can't use a `set` value as a dictionary key.

To create a `set` or `frozenset`, see Section 20.38, “`set()`: Create an algebraic set” and Section 20.17, “`frozenset()`: Create a frozen set”.

A number of functions that work on sequences also work on sets. In each case, the set is converted to a list before being passed to the function.

Another new feature in Python 2.7 is the set comprehension. This is similar to the feature described in Section 11.2, “List comprehensions”. Here is the general form:

```{ `e`
for `v1` in `s1`
for `v2` in `s2`
...
if `c` }
```

As with a list comprehension, you use one or more `for` clauses to iterate over sets of values, and the expression `e` is evaluated for every combination of the values in the sequences `si`. If there is no “`if`” clause, or if the “if” condition evaluates as `True`, the value is added to the sequence from which a set is then constructed.

Here is an example. Function `takeUppers()` takes one string argument and returns a set of the unique letters in that string, uppercased. The `for` clause iterates over the characters in the argument `s`; the `if` clause discards characters that aren't letters; and the `.upper()` method converts lowercase letters to uppercase.

```>>> def takeUpper(s):
...     return { c.upper()
...              for c in s
...              if c.isalpha() }
...
>>> takeUpper("A a|ccCc^#zZ")
set(['A', 'C', 'Z'])
```