set.discard()

Remove an element from the set. Silently does nothing if it is not present — the safe counterpart to set.remove().

Set methodPython 2.3+Live demo
Common call
seen.discard(item)
Returns
None — the set may lose an element
Replaces
a manual `if x in s: s.remove(x)` check
Watch out
unlike list.remove or set.remove, missing element is NOT an error
set.discard(elemelemThe element to remove. If not present, discard does nothing. Non-hashable arguments (list, dict, set) still raise TypeError — they cannot be searched for.type: hashable · required)
None

Demo

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

The demo shows the SET STATE after discarding. Python actually returns None; the meaningful effect is mutation. discard() silently ignores missing elements — that is the whole point of choosing it over remove(). Order shown is not meaningful; Python sets are unordered.

Parameters

NameTypeRequiredDescription
elemhashableyesThe element to remove. If not present, discard does nothing. Non-hashable arguments (list, dict, set) still raise TypeError — they cannot be searched for.

Return value

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

Common patterns

"Remove if present" no-branch
discard is already idempotent — no `if in` needed.
seen.discard(x)   # no branch; safe whether x is there or not
Reset a flag
Turning a flag off is a single call, regardless of prior state.
flags.discard("debug")
Prune from a set of listeners
Common in publish/subscribe patterns where the same subscriber may be removed multiple times.
subscribers.discard(callback)

Examples

1. Element present
s = {"a", "b", "c"} s.discard("b") s
Returns
{"a", "c"}
2. Missing is a no-op
s = {"a", "b"} s.discard("z") s
Returns
{"a", "b"} # unchanged, no error
3. From empty set
s = set() s.discard("x") s
Returns
set() # no error
4. Returns None
{"a", "b"}.discard("a")
Returns
None

Pitfalls

1. discard vs remove — silence vs KeyError
discard is silent on missing. remove raises KeyError. Reaching for remove when you meant discard causes a crash on the very case discard was designed for.
Blows up
s = {"a", "b"}
s.remove("z")
KeyError: 'z'
Silent
s.discard("z")
no error, no change
2. The `s = s.discard(...)` bug
discard() returns None. Assigning its result back sets your variable to None — the same class of bug as add, sort, and extend.
Now s is None
s = {"a", "b"}
s = s.discard("a")
print(s)
None
Just discard
s.discard("a")   # mutate, keep name
{"b"}
3. Silent no-op — you cannot tell if anything happened
discard gives no signal. If you need to know whether the element was actually removed, check membership before calling.
Fake count
count = 0
for x in items:
    s.discard(x)
    count += 1
count is len(items), not len(actually_removed)
Check first
count = 0
for x in items:
    if x in s:
        s.discard(x)
        count += 1
count of real removals
4. Unhashable elements still raise TypeError
discard needs to hash the element to look it up. Passing a list or dict raises before the missing-check runs.
Unhashable
s = {1, 2, 3}
s.discard([1])
TypeError: unhashable type: 'list'
Hashable
s.discard((1,))
s.discard(1)
no error

When to use

Use it
  • Removing an element that may or may not be there — the "idempotent delete" pattern
  • Resetting flags in a flag set
  • Cleanup where duplicate discards should not cause errors
  • Any code where the caller cannot guarantee the element is present
Reach for something else
  • You need to know whether the element was actually there → check membership first
  • You want an exception on missing → set.remove instead
  • You need to remove ANY element (not a specific one) → set.pop
  • Removing many at once → set.difference_update or `-=`

Notes

Complexity
O(1) amortized — hash table lookup and removal
Return
None; the set is mutated in place
CPython impl
Objects/setobject.c :: set_discard
Memory
In-place; no allocation
Thread-safe
Not safe under concurrent mutation of the same set

FAQ

discard silently does nothing when the element is missing; remove raises KeyError. Pick discard for "remove if present" workflows and remove for "this element MUST be there — raise if it is not".

History

2.3
set type added; discard has been the safe-delete method from the start.