Learn

Short lessons with real code you can edit and run on the page.

Sets in Python

Lesson 21 Python 3.14 Runs in your browser Updated
In short

A set is an unordered collection of unique values, so it drops duplicates and has no index. You write it in curly braces, such as {1, 2, 3}, or build it with set(), and it answers value in s quickly no matter how big it gets. Sets also combine with union, intersection and difference operations.

Key facts

  • {3, 1, 2, 3} holds 1, 2 and 3 once each. Duplicates disappear when the set is built.
  • set() creates an empty set. {} creates an empty dictionary.
  • add() puts one value in, remove() raises KeyError for a missing value, and discard() stays silent.
  • list(set(items)) removes duplicates from a list, and list(dict.fromkeys(items)) does it without changing the order.
  • a | b, a & b, a - b and a ^ b give the union, intersection, difference and symmetric difference.

What is a set in Python?

A set is an unordered collection of unique values, so it drops duplicates and has no index. You write the values inside curly braces, and Python keeps each value once, however many times you list it. Sets are built for two jobs, testing whether a value is present and removing duplicates, and both stay fast however large the set grows.

Python
numbers = {3, 1, 2, 3, 1}
print(numbers)
print(type(numbers))
print(len(numbers))
print(2 in numbers)
Output
{1, 2, 3}
<class 'set'>
3
True

The five values became three, because the second 3 and the second 1 were duplicates. in works as it does on a list, but a set finds the value by its hash, a number computed from the value, instead of checking items one by one. There is no numbers[0], because the values have no positions.

How do I create a set in Python?

Write the values inside curly braces, or call set() on a list, a string or any other iterable. An empty set must be written as set(), because empty braces {} create an empty dictionary.

Python
letters = set("hello")
print(sorted(letters))
print(len(letters))
empty = set()
print(empty)
print(type(empty))
print(type({}))
Output
['e', 'h', 'l', 'o']
4
set()
<class 'set'>
<class 'dict'>

set("hello") keeps each letter once, so the two l's collapse into one. The example prints the letters through sorted(), which returns them as an ordered list, because a set of strings can print in a different order each time Python starts.

A set of small whole numbers usually prints in numeric order, which is why the other examples use numbers, but no program should rely on that.

How do I add and remove values in a set?

Call add() with one value, or update() with several. remove() deletes a value and raises KeyError when it isn't there, while discard() deletes it and stays quiet otherwise.

Python
tags = {"python", "web"}
tags.add("css")
tags.add("web")
print(sorted(tags))
tags.update(["html", "js"])
print(len(tags))
tags.remove("web")
tags.discard("ruby")
print(sorted(tags))
Output
['css', 'python', 'web']
5
['css', 'html', 'js', 'python']

Adding "web" a second time changed nothing, because a set never holds a value twice. update() takes a list, a string or another set and adds every item, so it plays the role that extend() plays for lists. discard("ruby") did nothing without complaint, where remove("ruby") would have raised KeyError: 'ruby'.

How do I remove duplicates from a list in Python?

Convert the list to a set and back with list(set(items)). The set drops the repeats, and list() gives you a list again, though not necessarily in the original order. When the order matters, use list(dict.fromkeys(items)), which keeps the first occurrence of each value where it was.

Python
names = ["bob", "ada", "bob", "cy", "ada"]
unique = list(set(names))
print(len(unique))
print(sorted(unique))
in_order = list(dict.fromkeys(names))
print(in_order)
Output
3
['ada', 'bob', 'cy']
['bob', 'ada', 'cy']

dict.fromkeys() builds a dictionary with the list's values as keys, and keys can't repeat, so the duplicates vanish while the order of first appearance survives. The set version is shorter and fine whenever you sort the result or only need the count.

What are set operations in Python?

Set operations combine two sets into a new one. The union holds every value from either set, the intersection holds the values in both, the difference holds the values in the first set but not the second, and the symmetric difference holds the values in exactly one of them. Each has an operator and a method with the same result.

Python set operations
OperationOperatorMethodResult
Uniona | ba.union(b)Values in a, in b, or in both
Intersectiona & ba.intersection(b)Values in both a and b
Differencea - ba.difference(b)Values in a that are not in b
Symmetric differencea ^ ba.symmetric_difference(b)Values in a or b but not both
Python
a = {1, 2, 3, 4}
b = {3, 4, 5}
print(a | b)
print(a & b)
print(a - b)
print(a ^ b)
print(a.union(b))
print(a.intersection(b))
Output
{1, 2, 3, 4, 5}
{3, 4}
{1, 2}
{1, 2, 5}
{1, 2, 3, 4, 5}
{3, 4}

The operators need sets on both sides, while the methods accept any iterable, so a.union([5, 6]) works and a | [5, 6] raises TypeError. A set comprehension builds a set the way a list comprehension builds a list, with curly braces instead of square brackets.

Python
squares = {n * n for n in range(5)}
print(squares)
print(16 in squares)
print(len(squares))
Output
{0, 1, 4, 9, 16}
True
5

What is the difference between a set and a list?

A set holds each value once and has no order, and a list holds values in order, duplicates included. Use a set when you need uniqueness or fast membership tests, and a list when the order or the position of items matters.

Python set compared with list
TypeWritten asDuplicatesOrderedUse it when
SetCurly braces, {1, 2, 3}NoNo, and no indexingYou need membership tests or unique values
ListSquare brackets, [1, 2, 3]YesYes, with items[0]The order and position of items matter

value in a_set takes about the same time whether the set holds ten values or a million, because the hash points straight at the value. The same test on a list checks the items one after another, so it slows down as the list grows. For a handful of items the difference is invisible, and a list is the default choice until you need what a set offers.

Should I use a list, a tuple, a set or a dictionary?

Pick by asking three questions. Do the values need names, can they change, and do duplicates matter? A list is the default for an ordered group of values, a tuple for a fixed group, a set for unique values, and a dictionary for values you look up by key.

Python list, tuple, set and dictionary compared
TypeWritten asOrderedCan changeDuplicatesUse it when
List[1, 2, 2]YesYesYesAn ordered collection that grows, shrinks or gets sorted
Tuple(1, 2, 2)YesNoYesA fixed group of related values, or a dictionary key
Set{1, 2}NoYesNoUnique values and fast membership tests
Dictionary{"a": 1}YesYesKeys no, values yesValues looked up by a name

Which set methods will I use most?

The set methods you will reach for are the ones that add, remove, combine and compare. The table lists them, and the four operations have both a method and an operator. frozenset() builds a set that can't be changed and can therefore be a dictionary key or an item of another set.

Python set methods
MethodWhat it does
add(x)Adds x
remove(x)Removes x, or raises KeyError when it is missing
discard(x)Removes x when present, and does nothing otherwise
pop()Removes and returns an arbitrary value
clear()Removes every value
update(iterable)Adds every item of the iterable
copy()Returns a new set with the same values
union(other)Returns the values in either set, the same as a | b
intersection(other)Returns the values in both sets, the same as a & b
difference(other)Returns the values in this set but not the other, the same as a - b
symmetric_difference(other)Returns the values in exactly one of the sets, the same as a ^ b
issubset(other)True when every value of this set is in the other, the same as a <= b
issuperset(other)True when this set holds every value of the other, the same as a >= b
isdisjoint(other)True when the two sets share no values

Python has a few more, such as difference_update(), that change the set in place instead of returning a new one.

Common mistakes with sets in Python

These four mistakes with sets are the common ones. Three stop the program with a message, and the first creates the wrong type without a word.

  • Writing {} for an empty set. {} is an empty dictionary, and add() then fails with AttributeError: 'dict' object has no attribute 'add'. Write set().
  • TypeError: 'set' object is not subscriptable. Code tried s[0], and a set has no positions. Loop over the set, or convert it with sorted() when you need an order.
  • KeyError: 99. remove() was given a value that isn't in the set. Use discard(), or test with in first.
  • TypeError: cannot use 'list' as a set element (unhashable type: 'list'). A list was added to a set. Set values must be hashable, which means Python can compute their hash, and it can't for a value that could change, so use a tuple instead.

Run the three broken programs to see the messages, then fix them in the editor.

Python
s = {1, 2, 3}
print(s[0])
Output
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print(s[0])
          ~^^^
TypeError: 'set' object is not subscriptable
Python
s = {1, 2, 3}
s.remove(99)
Output
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    s.remove(99)
    ~~~~~~~~^^^^
KeyError: 99
Python
s = set()
s.add([1, 2])
Output
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    s.add([1, 2])
    ~~~~~^^^^^^^^
TypeError: cannot use 'list' as a set element (unhashable type: 'list')

Exercise

Turn the list into a set so each address counts once, then print how many unique addresses there are and the unique addresses in sorted order, giving 3 and ['a@x.com', 'b@x.com', 'c@x.com']. The starter counts and sorts the whole list, repeats included.

Python
emails = ["a@x.com", "b@x.com", "a@x.com", "c@x.com", "b@x.com"]
print(len(emails))
print(sorted(emails))
Output
Show the solution
emails = ["a@x.com", "b@x.com", "a@x.com", "c@x.com", "b@x.com"]
unique = set(emails)
print(len(unique))
print(sorted(unique))

Quiz

This quiz has 5 questions. Pick an answer to see why it is right or wrong.

  1. 1What does this program print?

    print(len({1, 2, 2, 3}))
  2. 2What does this program print?

    print(type({}))
  3. 3What does this program print?

    print(sorted({1, 2, 3} & {2, 3, 4}))
  4. 4Which expression creates an empty set?

  5. 5What does this program print?

    s = {1, 2}
    s.add(2)
    print(len(s))

Frequently asked questions

What is a set in Python?
A set is an unordered collection of unique values written in curly braces, such as {1, 2, 3}. It drops duplicates on its own, has no index, and answers value in s faster than a list does.
Is set() the same as {} in Python?
No. set() creates an empty set, while {} creates an empty dictionary, and type({}) prints <class 'dict'>. Braces only make a set when they hold values without colons, such as {1, 2}.
Why use a set instead of a list?
Use a set when you need each value once or need to test membership often. A set drops duplicates as items arrive and finds a value without scanning, while a list keeps order and duplicates and lets you read items by position.
Is a set faster than a list in Python?
For testing whether a value is present, yes. A set finds a value by its hash in about the same time however large it is, while a list checks its items one by one, so the gap grows with the size.
How do I remove duplicates from a list in Python?
Convert with list(set(items)) when the order does not matter. Use list(dict.fromkeys(items)) to drop duplicates and keep the first occurrence of each value in its original order.
Can a set contain a list?
No. Set values must be hashable, and a list is not, so adding one raises a TypeError. Store a tuple instead, which works as long as it holds hashable values itself.
Are Python sets ordered?
No. A set has no positions, so it cannot be indexed or sliced, and the order it prints in depends mostly on how the values hash rather than on when they were added. Call sorted() on a set when you need its values in order.