How to Create an Empty Set in Python

To create an empty set in Python, call set() with no arguments. Don’t write {}: empty curly braces give you an empty dictionary, not a set. Here’s the one line you need:

visited_states = set()   # empty set
not_a_set = {}           # empty dict!

Tested on Python 3.12.5: the screenshots and printed results below are the genuine output, not something typed by hand.

We’ll go through the set() constructor, the curly-brace trap, filling a set with add() and comprehensions, checking for emptiness, and the safe way to use an empty set as a default argument.

Create an empty set with set()

The set() constructor with nothing inside it returns a brand-new, empty, mutable set. Python even prints it as set(), because there’s no literal for an empty set:

visited_states = set()

print(visited_states)          # set()
print(type(visited_states))    # <class 'set'>
print(len(visited_states))     # 0
print(bool(visited_states))    # False

Output:

set()
<class 'set'>
0
False
Command Prompt output of Python set() printing an empty set, its class, a length of 0 and a truth value of False
The empty set prints as set(), its type is set, its length is 0 and it’s falsy.

Sets hold unique, unordered, hashable items. If you’re not sure a set is the right container, my comparison of Python sets vs tuples shows where each one fits.

Why doesn’t {} create an empty set in Python?

Curly braces were used for dictionaries long before sets got their own literal syntax, so {} stayed a dict. A set literal like {"Ohio"} works only when there’s at least one item inside:

a = {}
b = set()
print(type(a), type(b))
print(a == b)

c = {*()}                      # unpacking an empty tuple also gives a set
print(type(c), c)

a.add("Texas")                 # a dict has no .add()

Output:

<class 'dict'> <class 'set'>
False
<class 'set'> set()
Traceback (most recent call last):
  File "C:\pyguides\braces_dict.py", line 9, in <module>
    a.add("Texas")                 # a dict has no .add()
    ^^^^^
AttributeError: 'dict' object has no attribute 'add'
Command Prompt output showing Python {} is a dict, set() is a set, and calling add on the dict raises AttributeError
{} reports dict, the two empties aren’t equal, and .add() fails with an AttributeError.

That AttributeError is the usual symptom: the code looks fine until the first add(). The {*()} trick does build an empty set, but set() is clearer, so I stick with it.

If an empty dictionary is what you actually wanted, see creating an empty dictionary in Python.

Add items to an empty set with add() and update()

Once the set exists, add() inserts one item and update() inserts everything from an iterable. Duplicates are dropped silently, which is the main reason to start with a set in the first place:

visited_states = set()

visited_states.add("Texas")
visited_states.add("Ohio")
visited_states.add("Texas")          # duplicate, ignored
print(sorted(visited_states))

visited_states.update(["Utah", "Ohio", "Maine"])
print(sorted(visited_states), len(visited_states))

Output:

['Ohio', 'Texas']
['Maine', 'Ohio', 'Texas', 'Utah'] 4

Adding Texas twice still leaves one Texas, and update() skips the Ohio that’s already there. For more ways to insert items, read adding items to a set in Python.

Build a set from data with a loop or a set comprehension

In real code, an empty set is usually a starting point that a loop fills. Here I collect the customers who placed an order over $100.00 in the first week of October 2026:

orders = [
    ("2026-10-05", "Emily",  129.99),
    ("2026-10-05", "James",   45.50),
    ("2026-10-06", "Emily",   18.25),
    ("2026-10-06", "Olivia", 210.00),
    ("2026-10-07", "James",  150.75),
]

big_spenders = set()
for day, customer, amount in orders:
    if amount > 100:
        big_spenders.add(customer)
print("loop:         ", sorted(big_spenders))

same = {customer for _, customer, amount in orders if amount > 100}
print("comprehension:", sorted(same))

none_found = {c for _, c, amount in orders if amount > 500}
print("no matches:   ", none_found)

Output:

loop:          ['Emily', 'James', 'Olivia']
comprehension: ['Emily', 'James', 'Olivia']
no matches:    set()
Command Prompt output of Python collecting customers with orders over 100 USD into a set using a loop and a set comprehension
The loop and the comprehension return the same three names, and a filter that matches nothing returns set().

Notice that a comprehension with no matches still returns an empty set, not a dict, so it’s safe to call add() on the result later.

When you already have a list, skip the loop and pass it straight in; converting a list to a set in Python covers that, including what happens to order.

How do you check if a set is empty?

An empty set is falsy, so if not my_set is the idiomatic test. Comparing with set() works too, but comparing with {} quietly returns False:

alerts = set()

if not alerts:
    print("No alerts yet")

print(len(alerts) == 0, alerts == set(), alerts == {})

alerts.add("Low stock: SKU-1042")
if alerts:
    print(f"{len(alerts)} alert(s):", alerts)

Output:

No alerts yet
True True False
1 alert(s): {'Low stock: SKU-1042'}

That last comparison is another reason the dict/set mix-up hurts. There are more ways to test this in checking if a Python set is empty.

Create an empty frozenset and use set() as a default argument

frozenset() gives you an empty set that can’t change, which is handy as a dictionary key or a constant. An empty set and an empty frozenset compare equal:

empty_frozen = frozenset()
print(empty_frozen, type(empty_frozen).__name__)
print(set() == frozenset())

def tag_order(order_id, tags=None):
    if tags is None:
        tags = set()               # a fresh empty set on every call
    tags.add("reviewed")
    return order_id, sorted(tags)

print(tag_order("A-101"))
print(tag_order("A-102"))
print(tag_order("A-103", {"rush"}))

Output:

frozenset() frozenset
True
('A-101', ['reviewed'])
('A-102', ['reviewed'])
('A-103', ['reviewed', 'rush'])
Command Prompt output of Python frozenset() and a function that creates a fresh empty set when the tags argument is None
frozenset() equals set(), and each call that omits tags starts again from an empty set.

Never write def tag_order(order_id, tags=set()). The default is created once, so every call would share and grow the same set. Use None and create the set inside the function.

The reason behind that trap is how Python treats changeable objects, explained in mutable vs immutable types in Python.

Empty set syntax compared

CodeWhat you getCan add items?
set()Empty setYes
{}Empty dictNo (AttributeError on add)
{*()}Empty setYes, but it’s hard to read
frozenset()Empty frozen setNo, it’s immutable
{x for x in data if ...}Set, empty when nothing matchesYes

Want to keep working with sets? Pick one of these:

Frequently asked questions

How do I create an empty set in Python?

Call set() with no arguments, for example tags = set().

Why is {} not an empty set?

Empty curly braces create an empty dictionary. Set literals need at least one item, like {"Ohio"}.

How do I add elements to an empty set?

Use add() for one item and update() for an iterable. Duplicates are ignored.

How do I check if a set is empty?

Use if not my_set: or len(my_set) == 0. Don’t compare it with {}.

Can I use set() as a default argument?

Avoid it, because the default is shared between calls. Use None and create the set inside the function.

Where are Python sets documented?

See set and frozenset types in the Python docs.