set.add()

Insert a single element into the set. Silently does nothing if the element is already present.

Set methodPython 2.3+Live demo
Common call
seen.add(item)
Returns
None — the set itself gains at most one element
Replaces
a manual `if x not in s: s.add(x)` check
Watch out
element must be hashable — lists and dicts raise TypeError
set.add(elemelemThe element to add. Must be hashable — ints, floats, strings, tuples of hashables, frozensets are all fine. Lists, dicts, sets raise TypeError.type: hashable · required)
None

Demo

Live evaluation
Try:
Inputs
setsetstarting set (comma-separated)
elemAnyelement to add
Output
{'a', 'b', 'c'}.add('d')
None

The demo shows the SET STATE after adding. Python actually returns None; the meaningful effect is mutation. add() silently ignores duplicates — that is the point of sets. In the demo, duplicates in the starting CSV collapse first, then the new element is added (or not, if it's already there). Order shown is not meaningful; Python sets are unordered.

Parameters

NameTypeRequiredDescription
elemhashableyesThe element to add. Must be hashable — ints, floats, strings, tuples of hashables, frozensets are all fine. Lists, dicts, sets raise TypeError.

Return value

NoneReturns None — the useful effect is mutation. The demo shows the set state after adding.

Common patterns

Build a set incrementally
The idiomatic way to accumulate unique items in a loop.
seen = set()
for item in items:
    seen.add(item)
Track visited nodes
Classic pattern in BFS / DFS graph traversal.
visited = set()
queue = [start]
while queue:
    node = queue.pop()
    if node not in visited:
        visited.add(node)
        queue.extend(node.neighbors)
"Add if new" no-branch
add() is already idempotent — no `if not in` needed.
seen.add(x)   # no branch; safe to call whether x is there or not

Examples

1. Add a new element
s = {1, 2} s.add(3) s
Returns
{1, 2, 3}
2. Duplicate is a no-op
s = {1, 2} s.add(2) s
Returns
{1, 2} # unchanged
3. To an empty set
s = set() s.add("hello") s
Returns
{"hello"}
4. Returns None
{1, 2}.add(3)
Returns
None
5. Tuple element (hashable)
s = set() s.add((1, 2)) s
Returns
{(1, 2)}

Pitfalls

1. Unhashable elements raise TypeError
Lists, dicts, and sets are mutable and therefore unhashable — they cannot go into a set. Use a tuple, frozenset, or a hashable wrapper.
Unhashable
s = set()
s.add([1, 2])
TypeError: unhashable type: 'list'
Use tuple
s.add((1, 2))
{(1, 2)}
2. The `xs = xs.add(...)` bug
add() returns None. Assigning its result back sets your variable to None — the same class of bug as sort, extend, and insert.
Now s is None
s = {1, 2}
s = s.add(3)
print(s)
None
Just add
s.add(3)   # mutate, keep name
{1, 2, 3}
3. Silent no-op — not a signal of anything
A duplicate add() gives NO indication that nothing happened. Fine (and useful) for accumulator patterns; misleading if you were counting distinct additions.
Fake count
count = 0
for x in items:
    s.add(x)
    count += 1
count is len(items), not len(unique)
Check first
count = 0
for x in items:
    if x not in s:
        s.add(x)
        count += 1
count of new additions only
4. Confused with union() and update()
add() takes ONE element and mutates. update() takes an iterable and adds all its items. Reaching for add() with a list adds the WHOLE list as one element — but lists are unhashable, so it raises.
Wrong shape
s = {1, 2}
s.add([3, 4])
TypeError: unhashable type: 'list'
Multi-add
s.update([3, 4])
{1, 2, 3, 4}

When to use

Use it
  • Building a set incrementally from a loop or stream
  • Tracking visited / seen items in traversals
  • De-duplicating items as you encounter them
  • "Add if new" without branching — idempotent by design
Reach for something else
  • Adding many items at once → update() or the `|=` operator
  • Elements that are lists / dicts / sets → not hashable
  • You need to know whether the element was actually new → check membership first
  • Building a NEW set from an existing one → union() or the `|` operator

Notes

Complexity
O(1) amortized — hash table insertion
Return
None; the set is mutated in place
CPython impl
Objects/setobject.c :: set_add
Memory
May reallocate the underlying hash table when it grows past its load factor
Thread-safe
Not safe under concurrent mutation of the same set

FAQ

add() takes ONE element and inserts it into the set. update() takes an ITERABLE and inserts each of its items. Reaching for add() with a list will try to store the list itself — which fails because lists are unhashable.

History

2.3
set type added; add() has been the fundamental insertion method from the start.